ppb_base.c revision 42475
128257Smsmith/*-
238061Smsmith * Copyright (c) 1997, 1998 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 *
2642475Snsouch *	$Id: ppb_base.c,v 1.5 1998/09/13 18:26:26 nsouch Exp $
2728257Smsmith *
2828257Smsmith */
2928257Smsmith#include <sys/param.h>
3028257Smsmith#include <sys/systm.h>
3128257Smsmith#include <sys/kernel.h>
3242475Snsouch#include <machine/clock.h>
3328257Smsmith
3428257Smsmith#include <dev/ppbus/ppbconf.h>
3528257Smsmith
3628257Smsmith/*
3728257Smsmith * ppb_intr()
3828257Smsmith *
3928257Smsmith * Function called by ppcintr() when an intr occurs.
4028257Smsmith */
4128257Smsmithvoid
4228257Smsmithppb_intr(struct ppb_link *pl)
4328257Smsmith{
4428257Smsmith	struct ppb_data *ppb = pl->ppbus;
4528257Smsmith
4628257Smsmith	/*
4728257Smsmith	 * Call chipset dependent code.
4828257Smsmith	 * Should be filled at chipset initialisation if needed.
4928257Smsmith	 */
5028257Smsmith	if (pl->adapter->intr_handler)
5128257Smsmith		(*pl->adapter->intr_handler)(pl->adapter_unit);
5228257Smsmith
5328257Smsmith	/*
5428257Smsmith	 * Call upper handler iff the bus is owned by a device and
5528257Smsmith	 * this device has specified an interrupt handler.
5628257Smsmith	 */
5728257Smsmith	if (ppb->ppb_owner && ppb->ppb_owner->intr)
5828257Smsmith		(*ppb->ppb_owner->intr)(ppb->ppb_owner->id_unit);
5928257Smsmith
6028257Smsmith	return;
6128257Smsmith}
6228257Smsmith
6328257Smsmith/*
6428257Smsmith * ppb_poll_device()
6528257Smsmith *
6628257Smsmith * Polls the device
6728257Smsmith *
6828257Smsmith * max is a delay in 10-milliseconds
6928257Smsmith */
7028257Smsmithint
7128257Smsmithppb_poll_device(struct ppb_device *dev, int max,
7228257Smsmith		char mask, char status, int how)
7328257Smsmith{
7442475Snsouch	int i, j, error;
7542475Snsouch	char r;
7628257Smsmith
7742475Snsouch	/* try at least up to 10ms */
7842475Snsouch	for (j = 0; j < ((how & PPB_POLL) ? max : 1); j++) {
7942475Snsouch		for (i = 0; i < 10000; i++) {
8042475Snsouch			r = ppb_rstr(dev);
8142475Snsouch			DELAY(1);
8242475Snsouch			if ((r & mask) == status)
8342475Snsouch				return (0);
8442475Snsouch		}
8542475Snsouch	}
8642475Snsouch
8742475Snsouch	if (!(how & PPB_POLL)) {
8842475Snsouch	   for (i = 0; max == PPB_FOREVER || i < max-1; i++) {
8928257Smsmith		if ((ppb_rstr(dev) & mask) == status)
9028257Smsmith			return (0);
9128257Smsmith
9228257Smsmith		switch (how) {
9328257Smsmith		case PPB_NOINTR:
9428257Smsmith			/* wait 10 ms */
9542475Snsouch			tsleep((caddr_t)dev, PPBPRI, "ppbpoll", hz/100);
9628257Smsmith			break;
9728257Smsmith
9828257Smsmith		case PPB_INTR:
9928257Smsmith		default:
10028257Smsmith			/* wait 10 ms */
10128257Smsmith			if ((error = tsleep((caddr_t)dev, PPBPRI | PCATCH,
10242475Snsouch					"ppbpoll", hz/100)) != EWOULDBLOCK)
10328257Smsmith				return (error);
10428257Smsmith			break;
10528257Smsmith		}
10642475Snsouch	   }
10728257Smsmith	}
10828257Smsmith
10928257Smsmith	return (EWOULDBLOCK);
11028257Smsmith}
11128257Smsmith
11228257Smsmith/*
11338061Smsmith * ppb_set_mode()
11438061Smsmith *
11538061Smsmith * Set the operating mode of the chipset
11638061Smsmith */
11738061Smsmithint
11838061Smsmithppb_set_mode(struct ppb_device *dev, int mode)
11938061Smsmith{
12038061Smsmith	struct ppb_data *ppb = dev->ppb;
12138061Smsmith	int old_mode = ppb_get_mode(dev);
12238061Smsmith
12342475Snsouch	if ((*ppb->ppb_link->adapter->setmode)(
12442475Snsouch			ppb->ppb_link->adapter_unit, mode))
12538061Smsmith		return (-1);
12638061Smsmith
12738061Smsmith	/* XXX yet device mode = ppbus mode = chipset mode */
12842475Snsouch	dev->mode = ppb->mode = (mode & PPB_MASK);
12938061Smsmith
13038061Smsmith	return (old_mode);
13138061Smsmith}
13238061Smsmith
13338061Smsmith/*
13442475Snsouch * ppb_write()
13542475Snsouch *
13642475Snsouch * Write charaters to the port
13742475Snsouch */
13842475Snsouchint
13942475Snsouchppb_write(struct ppb_device *dev, char *buf, int len, int how)
14042475Snsouch{
14142475Snsouch	struct ppb_data *ppb = dev->ppb;
14242475Snsouch
14342475Snsouch	return (ppb->ppb_link->adapter->write(ppb->ppb_link->adapter_unit,
14442475Snsouch						buf, len, how));
14542475Snsouch}
14642475Snsouch
14742475Snsouch/*
14828257Smsmith * ppb_reset_epp_timeout()
14928257Smsmith *
15038061Smsmith * Reset the EPP timeout bit in the status register
15128257Smsmith */
15228257Smsmithint
15328257Smsmithppb_reset_epp_timeout(struct ppb_device *dev)
15428257Smsmith{
15528257Smsmith	struct ppb_data *ppb = dev->ppb;
15628257Smsmith
15728257Smsmith	if (ppb->ppb_owner != dev)
15828257Smsmith		return (EACCES);
15928257Smsmith
16042475Snsouch	(*ppb->ppb_link->adapter->reset_epp_timeout)(ppb->ppb_link->adapter_unit);
16128257Smsmith
16228257Smsmith	return (0);
16328257Smsmith}
16428257Smsmith
16528257Smsmith/*
16628257Smsmith * ppb_ecp_sync()
16728257Smsmith *
16838061Smsmith * Wait for the ECP FIFO to be empty
16928257Smsmith */
17028257Smsmithint
17128257Smsmithppb_ecp_sync(struct ppb_device *dev)
17228257Smsmith{
17328257Smsmith	struct ppb_data *ppb = dev->ppb;
17428257Smsmith
17528257Smsmith	if (ppb->ppb_owner != dev)
17628257Smsmith		return (EACCES);
17728257Smsmith
17842475Snsouch	(*ppb->ppb_link->adapter->ecp_sync)(ppb->ppb_link->adapter_unit);
17928257Smsmith
18028257Smsmith	return (0);
18128257Smsmith}
18228257Smsmith
18328257Smsmith/*
18428257Smsmith * ppb_get_status()
18528257Smsmith *
18638061Smsmith * Read the status register and update the status info
18728257Smsmith */
18828257Smsmithint
18928257Smsmithppb_get_status(struct ppb_device *dev, struct ppb_status *status)
19028257Smsmith{
19128257Smsmith	struct ppb_data *ppb = dev->ppb;
19228257Smsmith	register char r;
19328257Smsmith
19428257Smsmith	if (ppb->ppb_owner != dev)
19528257Smsmith		return (EACCES);
19628257Smsmith
19728257Smsmith	r = status->status = ppb_rstr(dev);
19828257Smsmith
19928257Smsmith	status->timeout	= r & TIMEOUT;
20028257Smsmith	status->error	= !(r & nFAULT);
20128257Smsmith	status->select	= r & SELECT;
20239134Snsouch	status->paper_end = r & PERROR;
20328257Smsmith	status->ack	= !(r & nACK);
20428257Smsmith	status->busy	= !(r & nBUSY);
20528257Smsmith
20628257Smsmith	return (0);
20728257Smsmith}
208