ppb_base.c revision 119418
128257Smsmith/*-
255939Snsouch * Copyright (c) 1997, 1998, 1999 Nicolas Souchu
328257Smsmith * All rights reserved.
428257Smsmith *
528257Smsmith * Redistribution and use in source and binary forms, with or without
628257Smsmith * modification, are permitted provided that the following conditions
728257Smsmith * are met:
828257Smsmith * 1. Redistributions of source code must retain the above copyright
928257Smsmith *    notice, this list of conditions and the following disclaimer.
1028257Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1128257Smsmith *    notice, this list of conditions and the following disclaimer in the
1228257Smsmith *    documentation and/or other materials provided with the distribution.
1328257Smsmith *
1428257Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1528257Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1628257Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1728257Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1828257Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1928257Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2028257Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2128257Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2228257Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2328257Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2428257Smsmith * SUCH DAMAGE.
2528257Smsmith */
26119418Sobrien
27119418Sobrien#include <sys/cdefs.h>
28119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/ppbus/ppb_base.c 119418 2003-08-24 17:55:58Z obrien $");
29119418Sobrien
3028257Smsmith#include <sys/param.h>
3128257Smsmith#include <sys/systm.h>
3228257Smsmith#include <sys/kernel.h>
3355939Snsouch#include <sys/module.h>
3455939Snsouch#include <sys/bus.h>
3555939Snsouch
3628257Smsmith#include <dev/ppbus/ppbconf.h>
3755939Snsouch
3855939Snsouch#include "ppbus_if.h"
3928257Smsmith
4055939Snsouch#include <dev/ppbus/ppbio.h>
4155939Snsouch
42119284SimpMODULE_VERSION(ppbus, 1);
43119284Simp
4455939Snsouch#define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev))
4555939Snsouch
4628257Smsmith/*
4755939Snsouch * ppb_poll_bus()
4828257Smsmith *
4955939Snsouch * Polls the bus
5028257Smsmith *
5128257Smsmith * max is a delay in 10-milliseconds
5228257Smsmith */
5328257Smsmithint
5455939Snsouchppb_poll_bus(device_t bus, int max,
5555939Snsouch	     char mask, char status, int how)
5628257Smsmith{
5742475Snsouch	int i, j, error;
5842475Snsouch	char r;
5928257Smsmith
6042475Snsouch	/* try at least up to 10ms */
6142475Snsouch	for (j = 0; j < ((how & PPB_POLL) ? max : 1); j++) {
6242475Snsouch		for (i = 0; i < 10000; i++) {
6355939Snsouch			r = ppb_rstr(bus);
6442475Snsouch			DELAY(1);
6542475Snsouch			if ((r & mask) == status)
6642475Snsouch				return (0);
6742475Snsouch		}
6842475Snsouch	}
6942475Snsouch
7042475Snsouch	if (!(how & PPB_POLL)) {
7142475Snsouch	   for (i = 0; max == PPB_FOREVER || i < max-1; i++) {
7255939Snsouch		if ((ppb_rstr(bus) & mask) == status)
7328257Smsmith			return (0);
7428257Smsmith
7528257Smsmith		switch (how) {
7628257Smsmith		case PPB_NOINTR:
7728257Smsmith			/* wait 10 ms */
7855939Snsouch			tsleep((caddr_t)bus, PPBPRI, "ppbpoll", hz/100);
7928257Smsmith			break;
8028257Smsmith
8128257Smsmith		case PPB_INTR:
8228257Smsmith		default:
8328257Smsmith			/* wait 10 ms */
8455939Snsouch			if (((error = tsleep((caddr_t)bus, PPBPRI | PCATCH,
8543295Sdillon			    "ppbpoll", hz/100)) != EWOULDBLOCK) != 0) {
8628257Smsmith				return (error);
8743295Sdillon			}
8828257Smsmith			break;
8928257Smsmith		}
9042475Snsouch	   }
9128257Smsmith	}
9228257Smsmith
9328257Smsmith	return (EWOULDBLOCK);
9428257Smsmith}
9528257Smsmith
9628257Smsmith/*
9755939Snsouch * ppb_get_epp_protocol()
9838061Smsmith *
9955939Snsouch * Return the chipset EPP protocol
10038061Smsmith */
10138061Smsmithint
10255939Snsouchppb_get_epp_protocol(device_t bus)
10338061Smsmith{
10455939Snsouch	uintptr_t protocol;
10538061Smsmith
10655939Snsouch	BUS_READ_IVAR(device_get_parent(bus), bus, PPC_IVAR_EPP_PROTO, &protocol);
10738061Smsmith
10855939Snsouch	return (protocol);
10955939Snsouch}
11055939Snsouch
11155939Snsouch/*
11255939Snsouch * ppb_get_mode()
11355939Snsouch *
11455939Snsouch */
11555939Snsouchint
11655939Snsouchppb_get_mode(device_t bus)
11755939Snsouch{
11855939Snsouch	struct ppb_data *ppb = DEVTOSOFTC(bus);
11955939Snsouch
12038061Smsmith	/* XXX yet device mode = ppbus mode = chipset mode */
12155939Snsouch	return (ppb->mode);
12255939Snsouch}
12338061Smsmith
12455939Snsouch/*
12555939Snsouch * ppb_set_mode()
12655939Snsouch *
12755939Snsouch * Set the operating mode of the chipset, return the previous mode
12855939Snsouch */
12955939Snsouchint
13055939Snsouchppb_set_mode(device_t bus, int mode)
13155939Snsouch{
13255939Snsouch	struct ppb_data *ppb = DEVTOSOFTC(bus);
13355939Snsouch	int old_mode = ppb_get_mode(bus);
13455939Snsouch
13563458Sn_hibma	if (PPBUS_SETMODE(device_get_parent(bus), mode))
13663458Sn_hibma		return -1;
13755939Snsouch
13863458Sn_hibma	/* XXX yet device mode = ppbus mode = chipset mode */
13963458Sn_hibma	ppb->mode = (mode & PPB_MASK);
14063458Sn_hibma
14138061Smsmith	return (old_mode);
14238061Smsmith}
14338061Smsmith
14438061Smsmith/*
14542475Snsouch * ppb_write()
14642475Snsouch *
14742475Snsouch * Write charaters to the port
14842475Snsouch */
14942475Snsouchint
15055939Snsouchppb_write(device_t bus, char *buf, int len, int how)
15142475Snsouch{
15255939Snsouch	return (PPBUS_WRITE(device_get_parent(bus), buf, len, how));
15342475Snsouch}
15442475Snsouch
15542475Snsouch/*
15628257Smsmith * ppb_reset_epp_timeout()
15728257Smsmith *
15838061Smsmith * Reset the EPP timeout bit in the status register
15928257Smsmith */
16028257Smsmithint
16155939Snsouchppb_reset_epp_timeout(device_t bus)
16228257Smsmith{
16355939Snsouch	return(PPBUS_RESET_EPP(device_get_parent(bus)));
16428257Smsmith}
16528257Smsmith
16628257Smsmith/*
16728257Smsmith * ppb_ecp_sync()
16828257Smsmith *
16938061Smsmith * Wait for the ECP FIFO to be empty
17028257Smsmith */
17128257Smsmithint
17255939Snsouchppb_ecp_sync(device_t bus)
17328257Smsmith{
17455939Snsouch	return (PPBUS_ECP_SYNC(device_get_parent(bus)));
17528257Smsmith}
17628257Smsmith
17728257Smsmith/*
17828257Smsmith * ppb_get_status()
17928257Smsmith *
18038061Smsmith * Read the status register and update the status info
18128257Smsmith */
18228257Smsmithint
18355939Snsouchppb_get_status(device_t bus, struct ppb_status *status)
18428257Smsmith{
18528257Smsmith	register char r;
18628257Smsmith
18755939Snsouch	r = status->status = ppb_rstr(bus);
18828257Smsmith
18928257Smsmith	status->timeout	= r & TIMEOUT;
19028257Smsmith	status->error	= !(r & nFAULT);
19128257Smsmith	status->select	= r & SELECT;
19239134Snsouch	status->paper_end = r & PERROR;
19328257Smsmith	status->ack	= !(r & nACK);
19428257Smsmith	status->busy	= !(r & nBUSY);
19528257Smsmith
19628257Smsmith	return (0);
19728257Smsmith}
198