ppb_base.c revision 39134
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 *
2639134Snsouch *	$Id: ppb_base.c,v 1.4 1998/08/03 19:14:31 msmith Exp $
2728257Smsmith *
2828257Smsmith */
2928257Smsmith#include <sys/param.h>
3028257Smsmith#include <sys/systm.h>
3128257Smsmith#include <sys/kernel.h>
3228257Smsmith
3328257Smsmith#include <dev/ppbus/ppbconf.h>
3428257Smsmith
3528257Smsmith/*
3628257Smsmith * ppb_intr()
3728257Smsmith *
3828257Smsmith * Function called by ppcintr() when an intr occurs.
3928257Smsmith */
4028257Smsmithvoid
4128257Smsmithppb_intr(struct ppb_link *pl)
4228257Smsmith{
4328257Smsmith	struct ppb_data *ppb = pl->ppbus;
4428257Smsmith
4528257Smsmith	/*
4628257Smsmith	 * Call chipset dependent code.
4728257Smsmith	 * Should be filled at chipset initialisation if needed.
4828257Smsmith	 */
4928257Smsmith	if (pl->adapter->intr_handler)
5028257Smsmith		(*pl->adapter->intr_handler)(pl->adapter_unit);
5128257Smsmith
5228257Smsmith	/*
5328257Smsmith	 * Call upper handler iff the bus is owned by a device and
5428257Smsmith	 * this device has specified an interrupt handler.
5528257Smsmith	 */
5628257Smsmith	if (ppb->ppb_owner && ppb->ppb_owner->intr)
5728257Smsmith		(*ppb->ppb_owner->intr)(ppb->ppb_owner->id_unit);
5828257Smsmith
5928257Smsmith	return;
6028257Smsmith}
6128257Smsmith
6228257Smsmith/*
6328257Smsmith * ppb_poll_device()
6428257Smsmith *
6528257Smsmith * Polls the device
6628257Smsmith *
6728257Smsmith * max is a delay in 10-milliseconds
6828257Smsmith */
6928257Smsmithint
7028257Smsmithppb_poll_device(struct ppb_device *dev, int max,
7128257Smsmith		char mask, char status, int how)
7228257Smsmith{
7328257Smsmith	int i, error;
7428257Smsmith
7528257Smsmith	for (i = 0; i < max; i++) {
7628257Smsmith		if ((ppb_rstr(dev) & mask) == status)
7728257Smsmith			return (0);
7828257Smsmith
7928257Smsmith		switch (how) {
8028257Smsmith		case PPB_NOINTR:
8128257Smsmith			/* wait 10 ms */
8228257Smsmith			if ((error = tsleep((caddr_t)dev, PPBPRI,
8328257Smsmith						"ppbpoll", hz/100)))
8428257Smsmith				return (error);
8528257Smsmith			break;
8628257Smsmith
8728257Smsmith		case PPB_INTR:
8828257Smsmith		default:
8928257Smsmith			/* wait 10 ms */
9028257Smsmith			if ((error = tsleep((caddr_t)dev, PPBPRI | PCATCH,
9128257Smsmith						"ppbpoll", hz/100)))
9228257Smsmith				return (error);
9328257Smsmith			break;
9428257Smsmith		}
9528257Smsmith	}
9628257Smsmith
9728257Smsmith	return (EWOULDBLOCK);
9828257Smsmith}
9928257Smsmith
10028257Smsmith/*
10138061Smsmith * ppb_set_mode()
10238061Smsmith *
10338061Smsmith * Set the operating mode of the chipset
10438061Smsmith */
10538061Smsmithint
10638061Smsmithppb_set_mode(struct ppb_device *dev, int mode)
10738061Smsmith{
10838061Smsmith	struct ppb_data *ppb = dev->ppb;
10938061Smsmith	int old_mode = ppb_get_mode(dev);
11038061Smsmith
11138061Smsmith	if ((*ppb->ppb_link->adapter->setmode)(dev->id_unit, mode))
11238061Smsmith		return (-1);
11338061Smsmith
11438061Smsmith	/* XXX yet device mode = ppbus mode = chipset mode */
11538061Smsmith	dev->mode = ppb->mode = mode;
11638061Smsmith
11738061Smsmith	return (old_mode);
11838061Smsmith}
11938061Smsmith
12038061Smsmith/*
12128257Smsmith * ppb_reset_epp_timeout()
12228257Smsmith *
12338061Smsmith * Reset the EPP timeout bit in the status register
12428257Smsmith */
12528257Smsmithint
12628257Smsmithppb_reset_epp_timeout(struct ppb_device *dev)
12728257Smsmith{
12828257Smsmith	struct ppb_data *ppb = dev->ppb;
12928257Smsmith
13028257Smsmith	if (ppb->ppb_owner != dev)
13128257Smsmith		return (EACCES);
13228257Smsmith
13328257Smsmith	(*ppb->ppb_link->adapter->reset_epp_timeout)(dev->id_unit);
13428257Smsmith
13528257Smsmith	return (0);
13628257Smsmith}
13728257Smsmith
13828257Smsmith/*
13928257Smsmith * ppb_ecp_sync()
14028257Smsmith *
14138061Smsmith * Wait for the ECP FIFO to be empty
14228257Smsmith */
14328257Smsmithint
14428257Smsmithppb_ecp_sync(struct ppb_device *dev)
14528257Smsmith{
14628257Smsmith	struct ppb_data *ppb = dev->ppb;
14728257Smsmith
14828257Smsmith	if (ppb->ppb_owner != dev)
14928257Smsmith		return (EACCES);
15028257Smsmith
15128257Smsmith	(*ppb->ppb_link->adapter->ecp_sync)(dev->id_unit);
15228257Smsmith
15328257Smsmith	return (0);
15428257Smsmith}
15528257Smsmith
15628257Smsmith/*
15728257Smsmith * ppb_get_status()
15828257Smsmith *
15938061Smsmith * Read the status register and update the status info
16028257Smsmith */
16128257Smsmithint
16228257Smsmithppb_get_status(struct ppb_device *dev, struct ppb_status *status)
16328257Smsmith{
16428257Smsmith	struct ppb_data *ppb = dev->ppb;
16528257Smsmith	register char r;
16628257Smsmith
16728257Smsmith	if (ppb->ppb_owner != dev)
16828257Smsmith		return (EACCES);
16928257Smsmith
17028257Smsmith	r = status->status = ppb_rstr(dev);
17128257Smsmith
17228257Smsmith	status->timeout	= r & TIMEOUT;
17328257Smsmith	status->error	= !(r & nFAULT);
17428257Smsmith	status->select	= r & SELECT;
17539134Snsouch	status->paper_end = r & PERROR;
17628257Smsmith	status->ack	= !(r & nACK);
17728257Smsmith	status->busy	= !(r & nBUSY);
17828257Smsmith
17928257Smsmith	return (0);
18028257Smsmith}
181