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