Sync with ppbus-970815 from the author :

- interrupt-driven printing now works (nlpt)
 - Rearrangement of bus-related functions into ppb_base/ppbconf
 - Addition of ieee1284 interface functions, preliminary parallel-port
   PnP support

Submitted by:	Nicolas Souchu <Nicolas.Souchu@prism.uvsq.fr>
This commit is contained in:
msmith 1997-08-16 14:05:38 +00:00
parent 9109c1638f
commit b96b8da32b
10 changed files with 902 additions and 247 deletions

View File

@ -47,7 +47,7 @@
*
* from: unknown origin, 386BSD 0.1
* From Id: lpt.c,v 1.55.2.1 1996/11/12 09:08:38 phk Exp
* $Id$
* $Id: nlpt.c,v 1.1 1997/08/14 13:57:40 msmith Exp $
*/
/*
@ -71,6 +71,9 @@
#include <sys/kernel.h>
#include <sys/uio.h>
#include <sys/syslog.h>
#ifdef DEVFS
#include <sys/devfsext.h>
#endif /*DEVFS*/
#include <sys/malloc.h>
#include <machine/stdarg.h>
@ -86,7 +89,7 @@
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/nlpt.h>
#ifndef DEBUG
#ifndef NLPT_DEBUG
#define nlprintf (void)
#else
#define nlprintf if (nlptflag) printf
@ -133,6 +136,8 @@ DATA_SET(ppbdriver_set, nlptdriver);
#define INIT (1<<6) /* waiting to initialize for open */
#define INTERRUPTED (1<<7) /* write call was interrupted */
#define HAVEBUS (1<<8) /* the driver owns the bus */
/* status masks to interrogate printer status */
#define RDY_MASK (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR) /* ready ? */
@ -158,6 +163,20 @@ static struct cdevsw nlpt_cdevsw =
nlptioctl, nullstop, nullreset, nodevtotty,/* lpt */
seltrue, nommap, nostrat, "nlpt", NULL, -1 };
static int
lpt_request_ppbus(struct lpt_data *lpt, int how)
{
lpt->sc_state |= HAVEBUS;
return (ppb_request_bus(&lpt->lpt_dev, how));
}
static int
lpt_release_ppbus(struct lpt_data *lpt)
{
lpt->sc_state &= ~HAVEBUS;
return (ppb_release_bus(&lpt->lpt_dev));
}
/*
* Internal routine to nlptprobe to do port tests of one byte value
*/
@ -228,12 +247,12 @@ nlpt_detect(struct lpt_data *lpt)
int status;
u_char data;
u_char mask;
int i;
int i, error;
status = IO_LPTSIZE;
if (ppb_request_bus(&lpt->lpt_dev, PPB_DONTWAIT)) {
printf("nlpt: cannot alloc ppbus!\n");
if ((error = lpt_request_ppbus(lpt, PPB_DONTWAIT))) {
printf("nlpt: cannot alloc ppbus (%d)!\n", error);
status = 0 ; goto end_probe ;
}
@ -263,7 +282,7 @@ nlpt_detect(struct lpt_data *lpt)
ppb_wdtr(&lpt->lpt_dev, 0);
ppb_wctr(&lpt->lpt_dev, 0);
ppb_release_bus(&lpt->lpt_dev);
lpt_release_ppbus(lpt);
return (status);
}
@ -316,6 +335,7 @@ static int
nlptattach(struct ppb_device *dev)
{
struct lpt_data *lpt = lptdata[dev->id_unit];
int error;
/*
* Report ourselves
@ -325,8 +345,8 @@ nlptattach(struct ppb_device *dev)
lpt->sc_primed = 0; /* not primed yet */
if (ppb_request_bus(&lpt->lpt_dev, PPB_DONTWAIT)) {
printf("nlpt: cannot alloc ppbus!\n");
if ((error = lpt_request_ppbus(lpt, PPB_DONTWAIT))) {
printf("nlpt: cannot alloc ppbus (%d)!\n", error);
return (0);
}
@ -343,7 +363,17 @@ nlptattach(struct ppb_device *dev)
}
nlprintf("irq %x\n", lpt->sc_irq);
ppb_release_bus(&lpt->lpt_dev);
lpt_release_ppbus(lpt);
#ifdef DEVFS
/* XXX what to do about the flags in the minor number? */
sc->devfs_token = devfs_add_devswf(&nlpt_cdevsw,
unit, DV_CHR,
UID_ROOT, GID_WHEEL, 0600, "nlpt%d", unit);
sc->devfs_token_ctl = devfs_add_devswf(&nlpt_cdevsw,
unit | LP_BYPASS, DV_CHR,
UID_ROOT, GID_WHEEL, 0600, "lpctl%d", unit);
#endif
return (1);
}
@ -368,6 +398,19 @@ nlptout(struct lpt_data *lpt)
* Avoid possible hangs do to missed interrupts
*/
if (lpt->sc_xfercnt) {
/* if we cannot allocate the bus NOW, retry later */
if ((lpt->sc_state & HAVEBUS) == 0 &&
lpt_request_ppbus (lpt, PPB_DONTWAIT)) {
lpt->sc_backoff++;
if (lpt->sc_backoff > hz/LPTOUTMAX)
lpt->sc_backoff =
lpt->sc_backoff > hz/LPTOUTMAX;
timeout((timeout_func_t)nlptout, (caddr_t)lpt,
lpt->sc_backoff);
return;
}
pl = spltty();
nlptintr(lpt->lpt_unit);
splx(pl);
@ -375,8 +418,6 @@ nlptout(struct lpt_data *lpt)
lpt->sc_state &= ~OBUSY;
wakeup((caddr_t)lpt);
}
ppb_release_bus(&lpt->lpt_dev);
}
/*
@ -399,9 +440,6 @@ nlptopen(dev_t dev, int flags, int fmt, struct proc *p)
lpt = lptdata[unit];
if (ppb_request_bus(&lpt->lpt_dev, PPB_WAIT|PPB_INTR))
return (EINTR);
if (lpt->sc_state) {
nlprintf("nlpt: still open %x\n", lpt->sc_state);
return(EBUSY);
@ -416,6 +454,9 @@ nlptopen(dev_t dev, int flags, int fmt, struct proc *p)
return(0);
}
if (lpt_request_ppbus(lpt, PPB_WAIT|PPB_INTR))
return (EINTR);
s = spltty();
nlprintf("nlpt flags 0x%x\n", lpt->sc_flags);
@ -445,7 +486,7 @@ nlptopen(dev_t dev, int flags, int fmt, struct proc *p)
lpt->sc_state = 0;
nlprintf ("status %x\n", ppb_rstr(&lpt->lpt_dev) );
ppb_release_bus(&lpt->lpt_dev);
lpt_release_ppbus(lpt);
return (EBUSY);
}
@ -455,7 +496,7 @@ nlptopen(dev_t dev, int flags, int fmt, struct proc *p)
lpt->sc_state = 0;
splx(s);
ppb_release_bus(&lpt->lpt_dev);
lpt_release_ppbus(lpt);
return (EBUSY);
}
@ -479,14 +520,16 @@ nlptopen(dev_t dev, int flags, int fmt, struct proc *p)
lpt->sc_xfercnt = 0;
splx(s);
/* release the bus, nlptout() will try to allocate it later */
lpt_release_ppbus(lpt);
/* only use timeout if using interrupt */
nlprintf("irq %x\n", lpt->sc_irq);
if (lpt->sc_irq & LP_USE_IRQ) {
lpt->sc_state |= TOUT;
timeout((timeout_func_t)nlptout, (caddr_t)lpt,
(lpt->sc_backoff = hz/LPTOUTINITIAL));
} else
ppb_release_bus(&lpt->lpt_dev);
}
nlprintf("opened.\n");
return(0);
@ -502,12 +545,14 @@ static int
nlptclose(dev_t dev, int flags, int fmt, struct proc *p)
{
struct lpt_data *lpt = lptdata[LPTUNIT(minor(dev))];
int err;
if(lpt->sc_flags & LP_BYPASS)
goto end_close;
if (ppb_request_bus(&lpt->lpt_dev, PPB_WAIT|PPB_INTR))
return (EINTR);
if ((lpt->sc_state & HAVEBUS) == 0 &&
(err = lpt_request_ppbus(lpt, PPB_WAIT|PPB_INTR)))
return (err);
lpt->sc_state &= ~OPEN;
@ -524,7 +569,7 @@ nlptclose(dev_t dev, int flags, int fmt, struct proc *p)
ppb_wctr(&lpt->lpt_dev, LPC_NINIT);
brelse(lpt->sc_inbuf);
ppb_release_bus(&lpt->lpt_dev);
lpt_release_ppbus(lpt);
end_close:
lpt->sc_state = 0;
@ -612,7 +657,7 @@ nlptwrite(dev_t dev, struct uio *uio, int ioflag)
return(EPERM);
}
if (ppb_request_bus(&lpt->lpt_dev, PPB_WAIT|PPB_INTR))
if (lpt_request_ppbus(lpt, PPB_WAIT|PPB_INTR))
return (EINTR);
lpt->sc_state &= ~INTERRUPTED;
@ -641,11 +686,13 @@ nlptwrite(dev_t dev, struct uio *uio, int ioflag)
/* check to see if we must do a polled write */
if(!(lpt->sc_irq & LP_USE_IRQ) && (lpt->sc_xfercnt)) {
nlprintf("p");
if((err = nlpt_pushbytes(lpt)))
err = nlpt_pushbytes(lpt);
lpt_release_ppbus(lpt);
if (err)
return(err);
}
ppb_release_bus(&lpt->lpt_dev);
}
return(0);
}
@ -694,6 +741,8 @@ nlptintr(int unit)
* Wakeup is not done if write call was interrupted.
*/
lpt->sc_state &= ~OBUSY;
lpt_release_ppbus(lpt);
if(!(lpt->sc_state & INTERRUPTED))
wakeup((caddr_t)lpt);
nlprintf("w ");

View File

@ -27,7 +27,7 @@
* @(#)lptreg.h 1.1 (Berkeley) 12/19/90
* Id: lptreg.h,v 1.6 1997/02/22 09:36:52 peter Exp
*
* $Id$
* $Id: nlpt.h,v 1.1 1997/08/14 13:57:40 msmith Exp $
*/
#ifndef __NLPT_H
#define __NLPT_H
@ -69,6 +69,11 @@ struct lpt_data {
#define LP_USE_IRQ 0x02 /* we are using our irq */
#define LP_ENABLE_IRQ 0x04 /* enable IRQ on open */
u_char sc_backoff ; /* time to call lptout() again */
#ifdef DEVFS
void *devfs_token;
void *devfs_token_ctl;
#endif
};
#endif

163
sys/dev/ppbus/ppb_1284.c Normal file
View File

@ -0,0 +1,163 @@
/*-
* Copyright (c) 1997 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/proc.h>
#include <sys/buf.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/uio.h>
#include <sys/syslog.h>
#include <machine/clock.h>
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_1284.h>
/*
* nibble_1284_wait()
*
* Wait for the peripherial up to 40ms
*/
int
nibble_1284_wait(struct ppb_device *dev, char mask, char status)
{
int i;
return (ppb_poll_device(dev, 4, mask, status, PPB_NOINTR));
}
#define nibble2char(s) (((s & ~nACK) >> 3) | (~s & nBUSY) >> 4)
/*
* nibble_1284_inbyte()
*
* Read data in NIBBLE mode
*/
int
nibble_1284_inbyte(struct ppb_device *dev, char *buffer)
{
char nibble[2], r;
int i, error;
r = ppb_rctr(dev);
for (i = 0; i < 2; i++) {
/* ready to take data (nAUTO low) */
ppb_wctr(dev, r | AUTOFEED);
if ((error = nibble_1284_wait(dev, nACK, 0))) {
ppb_wctr(dev, r);
return (error);
}
/* read nibble */
nibble[i] = ppb_rstr(dev);
#ifdef DEBUG_1284
printf("nibble_1284_inbyte: nibble[%d]=0x%x\n", i, nibble[i]);
#endif
/* ack, not ready for another nibble */
ppb_wctr(dev, r & ~AUTOFEED);
/* wait ack from peripherial */
if ((error = nibble_1284_wait(dev, nACK, nACK))) {
ppb_wctr(dev, r);
return (error);
}
}
*buffer = ((nibble2char(nibble[1]) << 4) & 0xf0) |
(nibble2char(nibble[0]) & 0x0f);
#ifdef DEBUG_1284
printf("nibble_1284_inbyte: byte=0x%x\n", *buffer);
#endif
return (0);
}
/*
* nibble_1284_sync()
*/
void
nibble_1284_sync(struct ppb_device *dev)
{
char ctr;
ctr = ppb_rctr(dev);
ppb_wctr(dev, (ctr & ~AUTOFEED) | SELECTIN);
if (nibble_1284_wait(dev, nACK, 0))
return;
ppb_wctr(dev, ctr | AUTOFEED);
nibble_1284_wait(dev, nACK, nACK);
ppb_wctr(dev, (ctr & ~AUTOFEED) | SELECTIN);
return;
}
/*
* nibble_1284_mode()
*
* Normal nibble mode or request device id mode (see ppb_1284.h)
*/
int
nibble_1284_mode(struct ppb_device *dev, int mode)
{
char ctrl;
int error;
ctrl = ppb_rctr(dev);
ppb_wdtr(dev, mode);
DELAY(5);
ppb_wctr(dev, (ctrl & ~SELECTIN) | AUTOFEED);
if ((error = nibble_1284_wait(dev, nACK | ERROR | SELECT | nFAULT,
ERROR | SELECT | nFAULT))) {
ppb_wctr(dev, ctrl);
return (error);
}
ppb_wctr(dev, ppb_rctr(dev) | STROBE);
DELAY(5);
ppb_wctr(dev, ppb_rctr(dev) & ~STROBE);
DELAY(5);
ppb_wctr(dev, ppb_rctr(dev) & ~AUTOFEED);
return (0);
}

40
sys/dev/ppbus/ppb_1284.h Normal file
View File

@ -0,0 +1,40 @@
/*-
* Copyright (c) 1997 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*
*/
#ifndef __1284_H
#define __1284_H
#define NIBBLE_1284_NORMAL 0
#define NIBBLE_1284_REQUEST_ID 4
extern void nibble_1284_sync(struct ppb_device *);
extern int nibble_1284_inbyte(struct ppb_device *, char *);
extern int nibble_1284_wait(struct ppb_device *, char, char);
extern int nibble_1284_mode(struct ppb_device *, int);
#endif

210
sys/dev/ppbus/ppb_base.c Normal file
View File

@ -0,0 +1,210 @@
/*-
* Copyright (c) 1997 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/proc.h>
#include <sys/buf.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/uio.h>
#include <sys/syslog.h>
#include <machine/clock.h>
#include <machine/lpt.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <i386/isa/isa.h>
#include <i386/isa/isa_device.h>
#include <dev/ppbus/ppbconf.h>
/*
* ppb_intr()
*
* Function called by ppcintr() when an intr occurs.
*/
void
ppb_intr(struct ppb_link *pl)
{
struct ppb_data *ppb = pl->ppbus;
/*
* Call chipset dependent code.
* Should be filled at chipset initialisation if needed.
*/
if (pl->adapter->intr_handler)
(*pl->adapter->intr_handler)(pl->adapter_unit);
/*
* Call upper handler iff the bus is owned by a device and
* this device has specified an interrupt handler.
*/
if (ppb->ppb_owner && ppb->ppb_owner->intr)
(*ppb->ppb_owner->intr)(ppb->ppb_owner->id_unit);
return;
}
/*
* ppb_poll_device()
*
* Polls the device
*
* max is a delay in 10-milliseconds
*/
int
ppb_poll_device(struct ppb_device *dev, int max,
char mask, char status, int how)
{
int i, error;
for (i = 0; i < max; i++) {
if ((ppb_rstr(dev) & mask) == status)
return (0);
switch (how) {
case PPB_NOINTR:
/* wait 10 ms */
if ((error = tsleep((caddr_t)dev, PPBPRI,
"ppbpoll", hz/100)))
return (error);
break;
case PPB_INTR:
default:
/* wait 10 ms */
if ((error = tsleep((caddr_t)dev, PPBPRI | PCATCH,
"ppbpoll", hz/100)))
return (error);
break;
}
}
return (EWOULDBLOCK);
}
/*
* ppb_reset_epp_timeout()
*
* Reset the EPP timeout bit in the status register.
*/
int
ppb_reset_epp_timeout(struct ppb_device *dev)
{
struct ppb_data *ppb = dev->ppb;
if (ppb->ppb_owner != dev)
return (EACCES);
(*ppb->ppb_link->adapter->reset_epp_timeout)(dev->id_unit);
return (0);
}
/*
* ppb_ecp_sync()
*
* Wait for the ECP FIFO to be empty.
*/
int
ppb_ecp_sync(struct ppb_device *dev)
{
struct ppb_data *ppb = dev->ppb;
if (ppb->ppb_owner != dev)
return (EACCES);
(*ppb->ppb_link->adapter->ecp_sync)(dev->id_unit);
return (0);
}
/*
* ppb_get_mode()
*
* Read the mode (SPP, EPP...) of the chipset.
*/
int
ppb_get_mode(struct ppb_device *dev)
{
return (dev->ppb->ppb_link->mode);
}
/*
* ppb_get_epp_protocol()
*
* Read the EPP protocol (1.9 or 1.7).
*/
int
ppb_get_epp_protocol(struct ppb_device *dev)
{
return (dev->ppb->ppb_link->epp_protocol);
}
/*
* ppb_get_irq()
*
* Return the irq, 0 if none.
*/
int
ppb_get_irq(struct ppb_device *dev)
{
return (dev->ppb->ppb_link->id_irq);
}
/*
* ppb_get_status()
*
* Read the status register and update the status info.
*/
int
ppb_get_status(struct ppb_device *dev, struct ppb_status *status)
{
struct ppb_data *ppb = dev->ppb;
register char r;
if (ppb->ppb_owner != dev)
return (EACCES);
r = status->status = ppb_rstr(dev);
status->timeout = r & TIMEOUT;
status->error = !(r & nFAULT);
status->select = r & SELECT;
status->paper_end = r & ERROR;
status->ack = !(r & nACK);
status->busy = !(r & nBUSY);
return (0);
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: ppbconf.c,v 1.1 1997/08/14 13:57:41 msmith Exp $
*
*/
#include <sys/param.h>
@ -48,6 +48,7 @@
#include <i386/isa/isa_device.h>
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_1284.h>
LIST_HEAD(, ppb_data) ppbdata; /* list of existing ppbus */
@ -61,11 +62,6 @@ static struct ppb_driver nulldriver = {
DATA_SET(ppbdriver_set, nulldriver);
/*
* Parallel Port Bus sleep/wakeup queue.
*/
#define PRIPPB 28 /* PSOCK < PRIPPB < PWAIT XXX */
/*
* ppb_alloc_bus()
*
@ -98,6 +94,159 @@ ppb_alloc_bus(void)
return(ppb);
}
static char *pnp_tokens[] = {
"PRINTER", "MODEM", "NET", "HDC", "PCMCIA", "MEDIA",
"FDC", "PORTS", "SCANNER", "DIGICAM", "", NULL };
static char *pnp_classes[] = {
"printer", "modem", "network device",
"hard disk", "PCMCIA", "multimedia device",
"floppy disk", "ports", "scanner",
"digital camera", "unknown device", NULL };
/*
* search_token()
*
* Search the first occurence of a token within a string
*/
static char *
search_token(char *str, int slen, char *token)
{
char *p;
int tlen, i, j;
#define UNKNOWN_LENGTH -1
if (slen == UNKNOWN_LENGTH)
/* get string's length */
for (slen = 0, p = str; *p != '\0'; p++)
slen ++;
/* get token's length */
for (tlen = 0, p = token; *p != '\0'; p++)
tlen ++;
if (tlen == 0)
return (str);
for (i = 0; i <= slen-tlen; i++) {
for (j = 0; j < tlen; j++)
if (str[i+j] != token[j])
break;
if (j == tlen)
return (&str[i]);
}
return (NULL);
}
/*
* ppb_pnp_detect()
*
* Returns the class id. of the peripherial, -1 otherwise
*/
static int
ppb_pnp_detect(struct ppb_data *ppb)
{
char *token, *q, *class = 0;
int i, len, error;
char str[PPB_PnP_STRING_SIZE+1];
struct ppb_device pnpdev; /* temporary device to perform I/O */
/* initialize the pnpdev structure for future use */
bzero(&pnpdev, sizeof(pnpdev));
pnpdev.ppb = ppb;
#ifdef PnP_DEBUG
printf("ppb: <PnP> probing PnP devices on ppbus%d...\n",
ppb->ppb_link->adapter_unit);
#endif
ppb_wctr(&pnpdev, nINIT | SELECTIN);
/* select NIBBLE_1284_REQUEST_ID mode */
if ((error = nibble_1284_mode(&pnpdev, NIBBLE_1284_REQUEST_ID))) {
#ifdef PnP_DEBUG
printf("ppb: <PnP> nibble_1284_mode()=%d\n", error);
#endif
return (-1);
}
len = 0;
for (q = str; !(ppb_rstr(&pnpdev) & ERROR); q++) {
if ((error = nibble_1284_inbyte(&pnpdev, q))) {
#ifdef PnP_DEBUG
printf("ppb: <PnP> nibble_1284_inbyte()=%d\n", error);
#endif
return (-1);
}
if (len++ >= PPB_PnP_STRING_SIZE) {
printf("ppb: <PnP> not space left!\n");
return (-1);
}
}
*q = '\0';
nibble_1284_sync(&pnpdev);
#ifdef PnP_DEBUG
printf("ppb: <PnP> %d characters: ", len);
for (i = 0; i < len; i++)
printf("0x%x ", str[i]);
printf("\n");
#endif
/* replace ';' characters by '\0' */
for (i = 0; i < len; i++)
str[i] = (str[i] == ';') ? '\0' : str[i];
if ((token = search_token(str, len, "MFG")) != NULL)
printf("ppbus%d: <%s", ppb->ppb_link->adapter_unit,
search_token(token, UNKNOWN_LENGTH, ":") + 1);
else
printf("ppbus%d: <unknown", ppb->ppb_link->adapter_unit);
if ((token = search_token(str, len, "MDL")) != NULL)
printf(" %s",
search_token(token, UNKNOWN_LENGTH, ":") + 1);
else
printf(" unknown");
if ((token = search_token(str, len, "VER")) != NULL)
printf("/%s",
search_token(token, UNKNOWN_LENGTH, ":") + 1);
if ((token = search_token(str, len, "REV")) != NULL)
printf(".%s",
search_token(token, UNKNOWN_LENGTH, ":") + 1);
printf(">");
if ((token = search_token(str, len, "CLS")) != NULL) {
class = search_token(token, UNKNOWN_LENGTH, ":") + 1;
printf(" %s", class);
}
if ((token = search_token(str, len, "CMD")) != NULL)
printf(" %s",
search_token(token, UNKNOWN_LENGTH, ":") + 1);
printf("\n");
if (class)
/* identify class ident */
for (i = 0; pnp_tokens[i] != NULL; i++) {
if (search_token(class, len, pnp_tokens[i]) != NULL) {
return (i);
break;
}
}
return (PPB_PnP_UNKNOWN);
}
/*
* ppb_attachdevs()
*
@ -110,9 +259,12 @@ ppb_attachdevs(struct ppb_data *ppb)
int error;
struct ppb_device *dev;
struct ppb_driver **p_drvpp, *p_drvp;
LIST_INIT(&ppb->ppb_devs); /* initialise device/driver list */
p_drvpp = (struct ppb_driver **)ppbdriver_set.ls_items;
/* detect PnP devices */
ppb->class_id = ppb_pnp_detect(ppb);
/*
* Blindly try all probes here. Later we should look at
@ -133,6 +285,69 @@ ppb_attachdevs(struct ppb_data *ppb)
return (0);
}
/*
* ppb_next_bus()
*
* Return the next bus in ppbus queue
*/
struct ppb_data *
ppb_next_bus(struct ppb_data *ppb)
{
if (ppb == NULL)
return (ppbdata.lh_first);
return (ppb->ppb_chain.le_next);
}
/*
* ppb_lookup_bus()
*
* Get ppb_data structure pointer according to the base address of the ppbus
*/
struct ppb_data *
ppb_lookup_bus(int base_port)
{
struct ppb_data *ppb;
for (ppb = ppbdata.lh_first; ppb; ppb = ppb->ppb_chain.le_next)
if (ppb->ppb_link->base == base_port)
break;
return (ppb);
}
/*
* ppb_attach_device()
*
* Called by loadable kernel modules to add a device
*/
int
ppb_attach_device(struct ppb_device *dev)
{
struct ppb_data *ppb = dev->ppb;
/* add the device to the list of probed devices */
LIST_INSERT_HEAD(&ppb->ppb_devs, dev, chain);
return (0);
}
/*
* ppb_remove_device()
*
* Called by loadable kernel modules to remove a device
*/
void
ppb_remove_device(struct ppb_device *dev)
{
/* remove the device from the list of probed devices */
LIST_REMOVE(dev, chain);
return;
}
/*
* ppb_request_bus()
*
@ -146,28 +361,22 @@ ppb_request_bus(struct ppb_device *dev, int how)
int s, error = 0;
struct ppb_data *ppb = dev->ppb;
/*
* During initialisation, ppb is null.
*/
if (!ppb)
return (0);
while (error != EINTR) {
while (!error) {
s = splhigh();
if (ppb->ppb_owner) {
splx(s);
switch (how) {
case (PPB_WAIT | PPB_INTR):
error = tsleep(ppb, PRIPPB | PCATCH,
"ppbreq", 0);
error = tsleep(ppb, PPBPRI|PCATCH, "ppbreq", 0);
break;
case (PPB_WAIT):
error = tsleep(ppb, PRIPPB, "ppbreq", 0);
case (PPB_WAIT | PPB_NOINTR):
error = tsleep(ppb, PPBPRI, "ppbreq", 0);
break;
default:
return EWOULDBLOCK;
return (EWOULDBLOCK);
break;
}
@ -179,7 +388,7 @@ ppb_request_bus(struct ppb_device *dev, int how)
}
}
return (EINTR);
return (error);
}
/*
@ -193,12 +402,6 @@ ppb_release_bus(struct ppb_device *dev)
int s;
struct ppb_data *ppb = dev->ppb;
/*
* During initialisation, ppb is null.
*/
if (!ppb)
return (0);
s = splhigh();
if (ppb->ppb_owner != dev) {
splx(s);
@ -208,132 +411,8 @@ ppb_release_bus(struct ppb_device *dev)
ppb->ppb_owner = 0;
splx(s);
/*
* Wakeup waiting processes.
*/
/* wakeup waiting processes */
wakeup(ppb);
return (0);
}
/*
* ppb_intr()
*
* Function called by ppcintr() when an intr occurs.
*/
void
ppb_intr(struct ppb_link *pl)
{
struct ppb_data *ppb = pl->ppbus;
/*
* Call chipset dependent code.
* Should be filled at chipset initialisation if needed.
*/
if (pl->adapter->intr_handler)
(*pl->adapter->intr_handler)(pl->adapter_unit);
/*
* Call upper handler iff the bus is owned by a device and
* this device has specified an interrupt handler.
*/
if (ppb->ppb_owner && ppb->ppb_owner->intr)
(*ppb->ppb_owner->intr)(ppb->ppb_owner->id_unit);
return;
}
/*
* ppb_reset_epp_timeout()
*
* Reset the EPP timeout bit in the status register.
*/
int
ppb_reset_epp_timeout(struct ppb_device *dev)
{
struct ppb_data *ppb = dev->ppb;
if (ppb->ppb_owner != dev)
return (EACCES);
(*ppb->ppb_link->adapter->reset_epp_timeout)(dev->id_unit);
return (0);
}
/*
* ppb_ecp_sync()
*
* Wait for the ECP FIFO to be empty.
*/
int
ppb_ecp_sync(struct ppb_device *dev)
{
struct ppb_data *ppb = dev->ppb;
if (ppb->ppb_owner != dev)
return (EACCES);
(*ppb->ppb_link->adapter->ecp_sync)(dev->id_unit);
return (0);
}
/*
* ppb_get_mode()
*
* Read the mode (SPP, EPP...) of the chipset.
*/
int
ppb_get_mode(struct ppb_device *dev)
{
return (dev->ppb->ppb_link->mode);
}
/*
* ppb_get_epp_protocol()
*
* Read the EPP protocol (1.9 or 1.7).
*/
int
ppb_get_epp_protocol(struct ppb_device *dev)
{
return (dev->ppb->ppb_link->epp_protocol);
}
/*
* ppb_get_irq()
*
* Return the irq, 0 if none.
*/
int
ppb_get_irq(struct ppb_device *dev)
{
return (dev->ppb->ppb_link->id_irq);
}
/*
* ppb_get_status()
*
* Read the status register and update the status info.
*/
int
ppb_get_status(struct ppb_device *dev, struct ppb_status *status)
{
struct ppb_data *ppb = dev->ppb;
register char r;
if (ppb->ppb_owner != dev)
return (EACCES);
r = status->status = ppb_rstr(dev);
status->timeout = r & TIMEOUT;
status->error = !(r & nFAULT);
status->select = r & SELECT;
status->paper_end = r & ERROR;
status->ack = !(r & nACK);
status->busy = !(r & nBUSY);
return (0);
}

View File

@ -23,12 +23,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: ppbconf.h,v 1.1 1997/08/14 13:57:42 msmith Exp $
*
*/
#ifndef __PPBCONF_H
#define __PPBCONF_H
/*
* Parallel Port Bus sleep/wakeup queue.
*/
#define PPBPRI PZERO+8
/*
* Parallel Port Chipset modes.
*/
@ -140,6 +145,7 @@ struct ppb_link {
int adapter_unit; /* unit of the adapter */
int base; /* base address of the port */
int id_irq; /* != 0 if irq enabled */
int mode; /* NIBBLE, PS2, EPP, ECP */
@ -152,11 +158,29 @@ struct ppb_link {
struct ppb_data *ppbus; /* link to the ppbus */
};
/*
* Maximum size of the PnP info string
*/
#define PPB_PnP_STRING_SIZE 160 /* XXX */
/*
* Parallel Port Bus structure.
*/
struct ppb_data {
#define PPB_PnP_PRINTER 0
#define PPB_PnP_MODEM 1
#define PPB_PnP_NET 2
#define PPB_PnP_HDC 3
#define PPB_PnP_PCMCIA 4
#define PPB_PnP_MEDIA 5
#define PPB_PnP_FDC 6
#define PPB_PnP_PORTS 7
#define PPB_PnP_SCANNER 8
#define PPB_PnP_DIGICAM 9
#define PPB_PnP_UNKNOWN 10
int class_id; /* not a PnP device if class_id < 0 */
struct ppb_link *ppb_link; /* link to the adapter */
struct ppb_device *ppb_owner; /* device which owns the bus */
LIST_HEAD(, ppb_device) ppb_devs; /* list of devices on the bus */
@ -176,11 +200,20 @@ struct ppb_driver
extern struct linker_set ppbdriver_set;
extern struct ppb_data *ppb_alloc_bus(void);
extern struct ppb_data *ppb_next_bus(struct ppb_data *);
extern struct ppb_data *ppb_lookup_bus(int);
extern int ppb_attach_device(struct ppb_device *);
extern void ppb_remove_device(struct ppb_device *);
extern int ppb_attachdevs(struct ppb_data *);
extern int ppb_request_bus(struct ppb_device *, int);
extern int ppb_release_bus(struct ppb_device *);
extern void ppb_intr(struct ppb_link *);
extern int ppb_poll_device(struct ppb_device *, int, char, char, int);
extern int ppb_reset_epp_timeout(struct ppb_device *);
extern int ppb_ecp_sync(struct ppb_device *);
extern int ppb_get_status(struct ppb_device *, struct ppb_status *);

View File

@ -23,9 +23,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: ppi.c,v 1.1 1997/08/14 13:57:43 msmith Exp $
*
*/
#include "ppi.h"
#if NPPI > 0
#include <sys/types.h>
#ifdef KERNEL
@ -49,10 +53,16 @@
#endif /*KERNEL */
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppi.h>
static int nppi = 0;
struct ppi_data {
int ppi_unit;
struct ppb_device ppi_dev;
};
#define MAXPPI 8 /* XXX not much better! */
static int nppi = 0;
static struct ppi_data *ppidata[MAXPPI];
/*
@ -63,14 +73,11 @@ static struct ppb_device *ppiprobe(struct ppb_data *ppb);
static int ppiattach(struct ppb_device *dev);
static void ppiintr(int unit);
#ifdef KERNEL
static struct ppb_driver ppidriver = {
ppiprobe, ppiattach, "ppi"
};
DATA_SET(ppbdriver_set, ppidriver);
#endif /* KERNEL */
static d_open_t ppiopen;
static d_close_t ppiclose;
@ -78,7 +85,7 @@ static d_ioctl_t ppiioctl;
#define CDEV_MAJOR 14 /* XXX */
static struct cdevsw ppi_cdevsw =
{ ppiopen, ppiclose, noread, nowrite,
{ ppiopen, ppiclose, noread, nowrite, /* 14 */
ppiioctl, nullstop, nullreset, nodevtotty,
seltrue, nommap, nostrat, "ppi", NULL, -1 };
@ -141,6 +148,13 @@ ppiintr(int unit)
static int
ppiopen(dev_t dev, int flags, int fmt, struct proc *p)
{
u_int unit = minor(dev);
if (unit >= nppi)
return (ENXIO);
printf("ppi open!\n");
return (EOPNOTSUPP);
}
@ -156,17 +170,66 @@ ppiioctl(dev_t dev, int cmd, caddr_t data, int flags, struct proc *p)
return (EOPNOTSUPP);
}
#ifdef PPI_MODULE
#include <sys/exec.h>
#include <sys/sysent.h>
#include <sys/lkm.h>
MOD_DEV(ppi, LM_DT_CHAR, CDEV_MAJOR, &ppi_cdevsw);
static int
ppi_load(struct lkm_table *lkmtp, int cmd)
{
struct ppb_data *ppb;
struct ppb_device *dev;
int i;
for (ppb = ppb_next_bus(NULL); ppb; ppb = ppb_next_bus(ppb)) {
dev = ppiprobe(ppb);
ppiattach(dev);
ppb_attach_device(dev);
}
return (0);
}
static int
ppi_unload(struct lkm_table *lkmtp, int cmd)
{
int i;
for (i = nppi-1; i > 0; i--) {
ppb_remove_device(&ppidata[i]->ppi_dev);
free(ppidata[i], M_TEMP);
}
return (0);
}
int
ppi_mod(struct lkm_table *lkmtp, int cmd, int ver)
{
DISPATCH(lkmtp, cmd, ver, ppi_load, ppi_unload, lkm_nullcmd);
}
#endif /* PPI_MODULE */
static ppi_devsw_installed = 0;
static void ppi_drvinit(void *unused)
static void ppi_drvinit(void *unused)
{
dev_t dev;
if( ! ppi_devsw_installed ) {
if (!ppi_devsw_installed ) {
dev = makedev(CDEV_MAJOR, 0);
cdevsw_add(&dev, &ppi_cdevsw, NULL);
ppi_devsw_installed = 1;
}
}
SYSINIT(ppidev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, ppi_drvinit, NULL)
SYSINIT(ppidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ppi_drvinit,NULL)
#endif /* NPPI */

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: vpo.c,v 1.1 1997/08/14 13:57:44 msmith Exp $
*
*/
#include <sys/types.h>
@ -65,14 +65,6 @@
#define VP0_FAST_SPINTMO 500000 /* wait status timeout */
#define VP0_LOW_SPINTMO 5000000 /* wait status timeout */
/* XXX
* This is ALPHA/BETA code, warnings are mandatory.
*/
#ifndef VP0_WARNING
#define VP0_WARNING /* defined to get warnings about timeouts,
* except select timeouts */
#endif
/*
* DO NOT MODIFY ANYTHING UNDER THIS LINE
* --------------------------------------------------------------------
@ -175,9 +167,9 @@ vpoprobe(struct ppb_data *ppb)
vpo->vpo_dev.ppb = ppb;
/* now, try to initialise the drive */
if (vpo_detect(vpo) != 0) {
if (vpo_detect(vpo)) {
free(vpo, M_DEVBUF);
return(NULL);
return (NULL);
}
/* ok, go to next device on next probe */
@ -288,25 +280,37 @@ static inline void
vpointr(struct vpo_data *vpo, struct scsi_xfer *xs)
{
register int timeout;
int errno; /* error in errno.h */
if (xs->datalen && !(xs->flags & SCSI_DATA_IN))
bcopy(xs->data, vpo->vpo_buffer, xs->datalen);
timeout = vpoio_do_scsi(vpo, VP0_INITIATOR,
xs->sc_link->target,
(char *)xs->cmd, xs->cmdlen,
vpo->vpo_buffer, xs->datalen,
&vpo->vpo_stat, &vpo->vpo_count);
errno = vpoio_do_scsi(vpo, VP0_INITIATOR,
xs->sc_link->target, (char *)xs->cmd, xs->cmdlen,
vpo->vpo_buffer, xs->datalen, &vpo->vpo_stat, &vpo->vpo_count);
#ifdef VP0_DEBUG
printf("vpo_do_scsi = %d, status = 0x%x, count = %d, vpo_error = %d\n",
errno, vpo->vpo_stat, vpo->vpo_count, vpo->vpo_error);
#endif
if (errno) {
#ifdef VP0_WARNING
vpo_warning(vpo, xs, timeout);
log(LOG_WARNING, "vpo%d: errno = %d\n", vpo->vpo_unit, errno);
#endif
/* connection to ppbus interrupted */
xs->error = XS_DRIVER_STUFFUP;
goto error;
}
#ifdef VP03_DEBUG
printf("vpo_do_scsi = %d, status = 0x%x, count = %d\n",
timeout, vpo->vpo_stat, vpo->vpo_count);
/* if a timeout occured, no sense */
if (vpo->vpo_error) {
#ifdef VP0_WARNING
vpo_warning(vpo, xs, vpo->vpo_error);
#endif
xs->error = XS_TIMEOUT;
goto error;
}
#define RESERVED_BITS_MASK 0x3e /* 00111110b */
#define NO_SENSE 0x0
@ -317,23 +321,25 @@ vpointr(struct vpo_data *vpo, struct scsi_xfer *xs)
break;
case CHECK_CONDITION:
default:
vpo->vpo_sense.cmd.op_code = REQUEST_SENSE;
vpo->vpo_sense.cmd.length = sizeof(xs->sense);
vpo->vpo_sense.cmd.control = 0;
timeout = vpoio_do_scsi(vpo, VP0_INITIATOR,
xs->sc_link->target,
(char *)&vpo->vpo_sense.cmd,
errno = vpoio_do_scsi(vpo, VP0_INITIATOR,
xs->sc_link->target, (char *)&vpo->vpo_sense.cmd,
sizeof(vpo->vpo_sense.cmd),
(char *)&xs->sense, sizeof(xs->sense),
&vpo->vpo_sense.stat, &vpo->vpo_sense.count);
xs->error = XS_SENSE;
goto error;
}
if (errno)
/* connection to ppbus interrupted */
xs->error = XS_DRIVER_STUFFUP;
else
xs->error = XS_SENSE;
if (timeout) {
goto error;
default: /* BUSY or RESERVATION_CONFLICT */
xs->error = XS_TIMEOUT;
goto error;
}
@ -369,7 +375,7 @@ vpo_scsi_cmd(struct scsi_xfer *xs)
return TRY_AGAIN_LATER;
}
#ifdef VP03_DEBUG
#ifdef VP0_DEBUG
printf("vpo_scsi_cmd(): xs->flags = 0x%x, "\
"xs->data = 0x%x, xs->datalen = %d\ncommand : %*D\n",
xs->flags, xs->data, xs->datalen,
@ -729,8 +735,15 @@ vpoio_wait(struct vpo_data *vpo, int tmo)
register int k;
register char r;
#if 0 /* broken */
if (ppb_poll_device(&vpo->vpo_dev, 150, nBUSY, nBUSY, PPB_INTR))
return (0);
return (ppb_rstr(&vpo->vpo_dev) & 0xf0);
#endif
k = 0;
while (!((r = ppb_rstr(&vpo->vpo_dev)) & 0x80) && (k++ < tmo))
while (!((r = ppb_rstr(&vpo->vpo_dev)) & nBUSY) && (k++ < tmo))
barrier();
/*
@ -756,14 +769,22 @@ vpoio_do_scsi(struct vpo_data *vpo, int host, int target, char *command,
int rw, len, error = 0;
register int k;
/* enter disk state, allocate the ppbus */
vpoio_connect(vpo, PPB_WAIT | PPB_NOINTR);
/*
* enter disk state, allocate the ppbus
*
* XXX
* Should we allow this call to be interruptible?
* The only way to report the interruption is to return
* EIO do upper SCSI code :^(
*/
if ((error = vpoio_connect(vpo, PPB_WAIT|PPB_INTR)))
return (error);
if (!vpoio_in_disk_mode(vpo)) {
error = VP0_ECONNECT; goto error;
vpo->vpo_error = VP0_ECONNECT; goto error;
}
if ((error = vpoio_select(vpo,host,target)))
if ((vpo->vpo_error = vpoio_select(vpo,host,target)))
goto error;
/*
@ -773,23 +794,23 @@ vpoio_do_scsi(struct vpo_data *vpo, int host, int target, char *command,
*/
ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE);
#ifdef VP03_DEBUG
#ifdef VP0_DEBUG
printf("vpo%d: drive selected, now sending the command...\n",
vpo->vpo_unit);
#endif
for (k = 0; k < clen; k++) {
if (vpoio_wait(vpo, VP0_FAST_SPINTMO) != (char)0xe0) {
error = VP0_ECMD_TIMEOUT;
vpo->vpo_error = VP0_ECMD_TIMEOUT;
goto error;
}
if (vpoio_outstr(vpo, &command[k], 1)) {
error = VP0_EPPDATA_TIMEOUT;
vpo->vpo_error = VP0_EPPDATA_TIMEOUT;
goto error;
}
}
#ifdef VP03_DEBUG
#ifdef VP0_DEBUG
printf("vpo%d: command sent, now completing the request...\n",
vpo->vpo_unit);
#endif
@ -804,7 +825,7 @@ vpoio_do_scsi(struct vpo_data *vpo, int host, int target, char *command,
for (;;) {
if (!(r = vpoio_wait(vpo, VP0_LOW_SPINTMO))) {
error = VP0_ESTATUS_TIMEOUT; goto error;
vpo->vpo_error = VP0_ESTATUS_TIMEOUT; goto error;
}
/* stop when the ZIP wants to send status */
@ -812,7 +833,7 @@ vpoio_do_scsi(struct vpo_data *vpo, int host, int target, char *command,
break;
if (*count >= blen) {
error = VP0_EDATA_OVERFLOW;
vpo->vpo_error = VP0_EDATA_OVERFLOW;
goto error;
}
len = (rw && ((blen - *count) >= VP0_SECTOR_SIZE)) ?
@ -824,37 +845,28 @@ vpoio_do_scsi(struct vpo_data *vpo, int host, int target, char *command,
else
error = vpoio_instr(vpo, &buffer[*count], len);
if (error)
if (error) {
vpo->vpo_error = error;
goto error;
}
*count += len;
}
if (vpoio_instr(vpo, &l, 1)) {
error = VP0_EOTHER; goto error;
vpo->vpo_error = VP0_EOTHER; goto error;
}
/* check if the ZIP wants to send more status */
if (vpoio_wait(vpo, VP0_FAST_SPINTMO) == (char)0xf0)
if (vpoio_instr(vpo, &h, 1)) {
error = VP0_EOTHER+2; goto error;
vpo->vpo_error = VP0_EOTHER+2; goto error;
}
/* return to printer state */
vpoio_disconnect(vpo);
#if 0
if (vpoio_in_disk_mode(vpo)) {
vpoio_reset (vpo);
error = VP0_EDISCONNECT; goto error;
}
#endif
*result = ((int) h << 8) | ((int) l & 0xff);
return (0);
error:
/* return to printer state, release the ppbus */
vpoio_disconnect(vpo);
return (error);
return (0);
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: vpo.h,v 1.1 1997/08/14 13:57:45 msmith Exp $
*
*/
#ifndef __VP03_H
@ -96,6 +96,7 @@ struct vpo_data {
int vpo_stat;
int vpo_count;
int vpo_error;
struct ppb_status vpo_status;
struct vpo_sense vpo_sense;