summaryrefslogtreecommitdiffstats
path: root/sys/dev/ppbus/vpo.c
diff options
context:
space:
mode:
authormsmith <msmith@FreeBSD.org>1998-08-03 19:14:33 +0000
committermsmith <msmith@FreeBSD.org>1998-08-03 19:14:33 +0000
commit2fdb23234a18b64b994328bb4be606a420e3b56d (patch)
treef8a4d5d9ba99cb367e9263ec96d08ecb8919f529 /sys/dev/ppbus/vpo.c
parentcfef94c8ca2347c78a745676fe6061eb1f172be7 (diff)
downloadFreeBSD-src-2fdb23234a18b64b994328bb4be606a420e3b56d.zip
FreeBSD-src-2fdb23234a18b64b994328bb4be606a420e3b56d.tar.gz
Major ppbus updates from the author.
- ppbus now supports PLIP via the if_plip driver - ieee1284 infrastructure added, including parallel-port PnP - port microsequencer added, for scripting the sort of port I/O that is common with parallel devices without endless calls up and down through the driver structure. - improved bus ownership behaviour among the ppbus-using drivers. - improved I/O chipset feature detection The vpo driver is now implemented using the microsequencer, leading to some performance improvements as well as providing an extensive example of its use. Reviewed by: msmith Submitted by: Nicolas Souchu <Nicolas.Souchu@prism.uvsq.fr>
Diffstat (limited to 'sys/dev/ppbus/vpo.c')
-rw-r--r--sys/dev/ppbus/vpo.c626
1 files changed, 51 insertions, 575 deletions
diff --git a/sys/dev/ppbus/vpo.c b/sys/dev/ppbus/vpo.c
index 44cb54d..aa5779a 100644
--- a/sys/dev/ppbus/vpo.c
+++ b/sys/dev/ppbus/vpo.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1997 Nicolas Souchu
+ * Copyright (c) 1997, 1998 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,39 +44,42 @@
#endif /*KERNEL */
#include <dev/ppbus/ppbconf.h>
-#include <dev/ppbus/vpo.h>
+#include <dev/ppbus/vpoio.h>
-/* --------------------------------------------------------------------
- * HERE ARE THINGS YOU MAY HAVE/WANT TO CHANGE
- */
+#define VP0_BUFFER_SIZE 0x12000
-/*
- * XXX
- * We may add a timeout queue to avoid active polling on nACK.
- */
-#define VP0_SELTMO 5000 /* select timeout */
-#define VP0_FAST_SPINTMO 500000 /* wait status timeout */
-#define VP0_LOW_SPINTMO 5000000 /* wait status timeout */
+struct vpo_sense {
+ struct scsi_sense cmd;
+ unsigned int stat;
+ unsigned int count;
+};
-/*
- * DO NOT MODIFY ANYTHING UNDER THIS LINE
- * --------------------------------------------------------------------
- */
+struct vpo_data {
+ unsigned short vpo_unit;
+
+ int vpo_stat;
+ int vpo_count;
+ int vpo_error;
+
+ struct ppb_status vpo_status;
+ struct vpo_sense vpo_sense;
+
+ unsigned char vpo_buffer[VP0_BUFFER_SIZE];
+
+ struct vpoio_data vpo_io; /* interface to low level functions */
+
+ struct scsi_link sc_link;
+};
-static __inline int vpoio_do_scsi(struct vpo_data *, int, int, char *, int,
- char *, int, int *, int *);
static int32_t vpo_scsi_cmd(struct scsi_xfer *);
static void vpominphys(struct buf *);
static u_int32_t vpo_adapter_info(int);
-static int vpo_detect(struct vpo_data *vpo);
-
static int nvpo = 0;
#define MAXVP0 8 /* XXX not much better! */
static struct vpo_data *vpodata[MAXVP0];
-#ifdef KERNEL
static struct scsi_adapter vpo_switch =
{
vpo_scsi_cmd,
@@ -117,8 +120,6 @@ static struct ppb_driver vpodriver = {
DATA_SET(ppbdriver_set, vpodriver);
-#endif /* KERNEL */
-
static u_int32_t
vpo_adapter_info(int unit)
{
@@ -134,8 +135,8 @@ vpo_adapter_info(int unit)
static struct ppb_device *
vpoprobe(struct ppb_data *ppb)
{
-
struct vpo_data *vpo;
+ struct ppb_device *dev;
if (nvpo >= MAXVP0) {
printf("vpo: Too many devices (max %d)\n", MAXVP0);
@@ -155,20 +156,18 @@ vpoprobe(struct ppb_data *ppb)
/* vpo dependent initialisation */
vpo->vpo_unit = nvpo;
- /* ppbus dependent initialisation */
- vpo->vpo_dev.id_unit = vpo->vpo_unit;
- vpo->vpo_dev.ppb = ppb;
+ /* ok, go to next device on next probe */
+ nvpo ++;
+
+ /* low level probe */
+ vpoio_set_unit(&vpo->vpo_io, vpo->vpo_unit);
- /* now, try to initialise the drive */
- if (vpo_detect(vpo)) {
+ if (!(dev = vpoio_probe(ppb, &vpo->vpo_io))) {
free(vpo, M_DEVBUF);
return (NULL);
}
- /* ok, go to next device on next probe */
- nvpo ++;
-
- return (&vpo->vpo_dev);
+ return (dev);
}
/*
@@ -183,6 +182,10 @@ vpoattach(struct ppb_device *dev)
struct scsibus_data *scbus;
struct vpo_data *vpo = vpodata[dev->id_unit];
+ /* low level attachment */
+ if (!vpoio_attach(&vpo->vpo_io))
+ return (0);
+
vpo->sc_link.adapter_unit = vpo->vpo_unit;
vpo->sc_link.adapter_targ = VP0_INITIATOR;
vpo->sc_link.adapter = &vpo_switch;
@@ -190,12 +193,6 @@ vpoattach(struct ppb_device *dev)
vpo->sc_link.opennings = VP0_OPENNINGS;
/*
- * Report ourselves
- */
- printf("vpo%d: <Adaptec aic7110 scsi> on ppbus %d\n",
- dev->id_unit, dev->ppb->ppb_link->adapter_unit);
-
- /*
* Prepare the scsibus_data area for the upperlevel
* scsi code.
*/
@@ -204,6 +201,9 @@ vpoattach(struct ppb_device *dev)
return (0);
scbus->adapter_link = &vpo->sc_link;
+ /* all went ok */
+ printf("vpo%d: <Iomega PPA-3/VPI0 SCSI controller>\n", dev->id_unit);
+
scsi_attachdevs(scbus);
return (1);
@@ -219,58 +219,11 @@ vpominphys(struct buf *bp)
return;
}
-#ifdef VP0_WARNING
-static __inline void
-vpo_warning(struct vpo_data *vpo, struct scsi_xfer *xs, int timeout)
-{
-
- switch (timeout) {
- case 0:
- case VP0_ESELECT_TIMEOUT:
- /* log(LOG_WARNING,
- "vpo%d: select timeout\n", vpo->vpo_unit); */
- break;
- case VP0_EDISCONNECT:
- log(LOG_WARNING,
- "vpo%d: can't get printer state\n", vpo->vpo_unit);
- break;
- case VP0_ECONNECT:
- log(LOG_WARNING,
- "vpo%d: can't get disk state\n", vpo->vpo_unit);
- break;
- case VP0_ECMD_TIMEOUT:
- log(LOG_WARNING,
- "vpo%d: command timeout\n", vpo->vpo_unit);
- break;
- case VP0_EPPDATA_TIMEOUT:
- log(LOG_WARNING,
- "vpo%d: EPP data timeout\n", vpo->vpo_unit);
- break;
- case VP0_ESTATUS_TIMEOUT:
- log(LOG_WARNING,
- "vpo%d: status timeout\n", vpo->vpo_unit);
- break;
- case VP0_EDATA_OVERFLOW:
- log(LOG_WARNING,
- "vpo%d: data overflow\n", vpo->vpo_unit);
- break;
- case VP0_EINTR:
- log(LOG_WARNING,
- "vpo%d: ppb request interrupted\n", vpo->vpo_unit);
- break;
- default:
- log(LOG_WARNING,
- "vpo%d: timeout = %d\n", vpo->vpo_unit, timeout);
- break;
- }
-}
-#endif /* VP0_WARNING */
-
/*
- * vpointr()
+ * vpo_intr()
*/
-static __inline void
-vpointr(struct vpo_data *vpo, struct scsi_xfer *xs)
+static void
+vpo_intr(struct vpo_data *vpo, struct scsi_xfer *xs)
{
int errno; /* error in errno.h */
@@ -278,9 +231,10 @@ vpointr(struct vpo_data *vpo, struct scsi_xfer *xs)
if (xs->datalen && !(xs->flags & SCSI_DATA_IN))
bcopy(xs->data, vpo->vpo_buffer, xs->datalen);
- errno = vpoio_do_scsi(vpo, VP0_INITIATOR,
+ errno = vpoio_do_scsi(&vpo->vpo_io, VP0_INITIATOR,
xs->sc_link->target, (char *)xs->cmd, xs->cmdlen,
- vpo->vpo_buffer, xs->datalen, &vpo->vpo_stat, &vpo->vpo_count);
+ vpo->vpo_buffer, xs->datalen, &vpo->vpo_stat, &vpo->vpo_count,
+ &vpo->vpo_error);
#ifdef VP0_DEBUG
printf("vpo_do_scsi = %d, status = 0x%x, count = %d, vpo_error = %d\n",
@@ -298,9 +252,6 @@ vpointr(struct vpo_data *vpo, struct scsi_xfer *xs)
/* 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;
}
@@ -318,11 +269,12 @@ vpointr(struct vpo_data *vpo, struct scsi_xfer *xs)
vpo->vpo_sense.cmd.length = sizeof(xs->sense);
vpo->vpo_sense.cmd.control = 0;
- errno = vpoio_do_scsi(vpo, VP0_INITIATOR,
+ errno = vpoio_do_scsi(&vpo->vpo_io, 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);
+ &vpo->vpo_sense.stat, &vpo->vpo_sense.count,
+ &vpo->vpo_error);
if (errno)
/* connection to ppbus interrupted */
@@ -376,490 +328,14 @@ vpo_scsi_cmd(struct scsi_xfer *xs)
#endif
if (xs->flags & SCSI_NOMASK) {
- vpointr(vpodata[xs->sc_link->adapter_unit], xs);
+ vpo_intr(vpodata[xs->sc_link->adapter_unit], xs);
return COMPLETE;
}
- s = VP0_SPL();
+ s = splbio();
- vpointr(vpodata[xs->sc_link->adapter_unit], xs);
+ vpo_intr(vpodata[xs->sc_link->adapter_unit], xs);
splx(s);
return SUCCESSFULLY_QUEUED;
}
-
-#define vpoio_d_pulse(vpo,b) { \
- ppb_wdtr(&(vpo)->vpo_dev, b); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \
-}
-
-#define vpoio_c_pulse(vpo,b) { \
- ppb_wdtr(&(vpo)->vpo_dev, b); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_SELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_SELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_SELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \
- ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \
-}
-
-static int
-vpoio_disconnect(struct vpo_data *vpo)
-{
-
- vpoio_d_pulse(vpo, 0);
- vpoio_d_pulse(vpo, 0x3c);
- vpoio_d_pulse(vpo, 0x20);
- vpoio_d_pulse(vpo, 0xf);
-
- return (ppb_release_bus(&vpo->vpo_dev));
-}
-
-/*
- * how : PPB_WAIT or PPB_DONTWAIT
- */
-static int
-vpoio_connect(struct vpo_data *vpo, int how)
-{
- int error;
-
- if ((error = ppb_request_bus(&vpo->vpo_dev, how)))
- return error;
-
- vpoio_c_pulse(vpo, 0);
- vpoio_c_pulse(vpo, 0x3c);
- vpoio_c_pulse(vpo, 0x20);
-
- if (PPB_IN_EPP_MODE(&vpo->vpo_dev)) {
- vpoio_c_pulse(vpo, 0xcf);
- } else {
- vpoio_c_pulse(vpo, 0x8f);
- }
-
- return (0);
-}
-
-/*
- * vpoio_in_disk_mode()
- *
- * Check if we are in disk mode
- */
-static int
-vpoio_in_disk_mode(struct vpo_data *vpo)
-{
-
- /* first, set H_AUTO high */
- ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE);
-
- /* when H_AUTO is set low, H_FLT should be high */
- ppb_wctr(&vpo->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE);
- if ((ppb_rstr(&vpo->vpo_dev) & H_FLT) == 0)
- return (0);
-
- /* when H_AUTO is set high, H_FLT should be low */
- ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE);
- if ((ppb_rstr(&vpo->vpo_dev) & H_FLT) != 0)
- return (0);
-
- return (1);
-}
-
-/*
- * vpoio_reset()
- *
- * SCSI reset signal, the drive must be in disk mode
- */
-static void
-vpoio_reset (struct vpo_data *vpo)
-{
-
- /*
- * SCSI reset signal.
- */
- ppb_wdtr(&vpo->vpo_dev, (1 << 7));
- ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_nINIT | H_STROBE);
- DELAY(25);
- ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE);
-
- return;
-}
-
-
-/*
- * vpo_detect()
- *
- * Detect and initialise the VP0 adapter.
- */
-static int
-vpo_detect(struct vpo_data *vpo)
-{
-
- vpoio_disconnect(vpo);
- vpoio_connect(vpo, PPB_DONTWAIT);
-
- if (!vpoio_in_disk_mode(vpo)) {
- vpoio_disconnect(vpo);
- return (VP0_EINITFAILED);
- }
-
- /* send SCSI reset signal */
- vpoio_reset (vpo);
-
- vpoio_disconnect(vpo);
-
- if (vpoio_in_disk_mode(vpo))
- return (VP0_EINITFAILED);
-
- return (0);
-}
-
-#define vpo_wctr(dev,byte,delay) { \
- int i; int iter = delay / MHZ_16_IO_DURATION; \
- for (i = 0; i < iter; i++) { \
- ppb_wctr(dev, byte); \
- } \
-}
-
-#define vpoio_spp_outbyte(vpo,byte) { \
- ppb_wdtr(&vpo->vpo_dev, byte); \
- ppb_wctr(&vpo->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE); \
- vpo_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE, \
- VP0_SPP_WRITE_PULSE); \
-}
-
-#define vpoio_nibble_inbyte(vpo,buffer) { \
- register char h, l; \
- vpo_wctr(&vpo->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE, \
- VP0_NIBBLE_READ_PULSE); \
- h = ppb_rstr(&vpo->vpo_dev); \
- ppb_wctr(&vpo->vpo_dev, H_nAUTO | H_SELIN | H_INIT | H_STROBE); \
- l = ppb_rstr(&vpo->vpo_dev); \
- *buffer = ((l >> 4) & 0x0f) + (h & 0xf0); \
-}
-
-#define vpoio_ps2_inbyte(vpo,buffer) { \
- *buffer = ppb_rdtr(&vpo->vpo_dev); \
- ppb_wctr(&vpo->vpo_dev, PCD | H_nAUTO | H_SELIN | H_INIT | H_nSTROBE); \
- ppb_wctr(&vpo->vpo_dev, PCD | H_AUTO | H_SELIN | H_INIT | H_nSTROBE); \
-}
-
-/*
- * vpoio_outstr()
- */
-static int
-vpoio_outstr(struct vpo_data *vpo, char *buffer, int size)
-{
-
- register int k;
- int error = 0;
- int r, mode, epp;
-
- mode = ppb_get_mode(&vpo->vpo_dev);
- switch (mode) {
- case PPB_NIBBLE:
- case PPB_PS2:
- for (k = 0; k < size; k++) {
- vpoio_spp_outbyte(vpo, *buffer++);
- }
- break;
-
- case PPB_EPP:
- case PPB_ECP_EPP:
- epp = ppb_get_epp_protocol(&vpo->vpo_dev);
-
- ppb_reset_epp_timeout(&vpo->vpo_dev);
- ppb_wctr(&vpo->vpo_dev,
- H_AUTO | H_SELIN | H_INIT | H_STROBE);
-
- if (epp == EPP_1_7)
- for (k = 0; k < size; k++) {
- ppb_wepp(&vpo->vpo_dev, *buffer++);
- if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) {
- error = VP0_EPPDATA_TIMEOUT;
- break;
- }
- }
- else {
- if (((long) buffer | size) & 0x03)
- ppb_outsb_epp(&vpo->vpo_dev,
- buffer, size);
- else
- ppb_outsl_epp(&vpo->vpo_dev,
- buffer, size/4);
-
- if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) {
- error = VP0_EPPDATA_TIMEOUT;
- break;
- }
- }
- ppb_wctr(&vpo->vpo_dev,
- H_AUTO | H_nSELIN | H_INIT | H_STROBE);
- /* ppb_ecp_sync(&vpo->vpo_dev); */
- break;
-
- default:
- printf("vpoio_outstr(): unknown transfer mode (%d)!\n",
- mode);
- return (1); /* XXX */
- }
-
- return (error);
-}
-
-/*
- * vpoio_instr()
- */
-static int
-vpoio_instr(struct vpo_data *vpo, char *buffer, int size)
-{
-
- register int k;
- int error = 0;
- int r, mode, epp;
-
- mode = ppb_get_mode(&vpo->vpo_dev);
- switch (mode) {
- case PPB_NIBBLE:
- for (k = 0; k < size; k++) {
- vpoio_nibble_inbyte(vpo, buffer++);
- }
- ppb_wctr(&vpo->vpo_dev,
- H_AUTO | H_nSELIN | H_INIT | H_STROBE);
- break;
-
- case PPB_PS2:
- ppb_wctr(&vpo->vpo_dev, PCD |
- H_AUTO | H_SELIN | H_INIT | H_nSTROBE);
-
- for (k = 0; k < size; k++) {
- vpoio_ps2_inbyte(vpo, buffer++);
- }
- ppb_wctr(&vpo->vpo_dev,
- H_AUTO | H_nSELIN | H_INIT | H_STROBE);
- break;
-
- case PPB_EPP:
- case PPB_ECP_EPP:
- epp = ppb_get_epp_protocol(&vpo->vpo_dev);
-
- ppb_reset_epp_timeout(&vpo->vpo_dev);
- ppb_wctr(&vpo->vpo_dev, PCD |
- H_AUTO | H_SELIN | H_INIT | H_STROBE);
-
- if (epp == EPP_1_7)
- for (k = 0; k < size; k++) {
- *buffer++ = ppb_repp(&vpo->vpo_dev);
- if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) {
- error = VP0_EPPDATA_TIMEOUT;
- break;
- }
- }
- else {
- if (((long) buffer | size) & 0x03)
- ppb_insb_epp(&vpo->vpo_dev,
- buffer, size);
- else
- ppb_insl_epp(&vpo->vpo_dev,
- buffer, size/4);
-
- if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) {
- error = VP0_EPPDATA_TIMEOUT;
- break;
- }
- }
- ppb_wctr(&vpo->vpo_dev, PCD |
- H_AUTO | H_nSELIN | H_INIT | H_STROBE);
- /* ppb_ecp_sync(&vpo->vpo_dev); */
- break;
-
- default:
- printf("vpoio_instr(): unknown transfer mode (%d)!\n",
- mode);
- return (1); /* XXX */
- }
-
- return (error);
-}
-
-static __inline char
-vpoio_select(struct vpo_data *vpo, int initiator, int target)
-{
-
- register int k;
-
- ppb_wdtr(&vpo->vpo_dev, (1 << target));
- ppb_wctr(&vpo->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE);
- ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE);
- ppb_wdtr(&vpo->vpo_dev, (1 << initiator));
- ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_nINIT | H_STROBE);
-
- k = 0;
- while (!(ppb_rstr(&vpo->vpo_dev) & 0x40) && (k++ < VP0_SELTMO))
- barrier();
-
- if (k >= VP0_SELTMO)
- return (VP0_ESELECT_TIMEOUT);
-
- return (0);
-}
-
-/*
- * vpoio_wait()
- *
- * H_SELIN must be low.
- */
-static __inline char
-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)) & nBUSY) && (k++ < tmo))
- barrier();
-
- /*
- * Return some status information.
- * Semantics : 0xc0 = ZIP wants more data
- * 0xd0 = ZIP wants to send more data
- * 0xe0 = ZIP wants command
- * 0xf0 = end of transfer, ZIP is sending status
- */
- if (k < tmo)
- return (r & 0xf0);
-
- return (0); /* command timed out */
-}
-
-static __inline int
-vpoio_do_scsi(struct vpo_data *vpo, int host, int target, char *command,
- int clen, char *buffer, int blen, int *result, int *count)
-{
-
- register char r;
- char l, h = 0;
- int rw, len, error = 0;
- register int k;
-
- /*
- * 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)) {
- vpo->vpo_error = VP0_ECONNECT; goto error;
- }
-
- if ((vpo->vpo_error = vpoio_select(vpo,host,target)))
- goto error;
-
- /*
- * Send the command ...
- *
- * set H_SELIN low for vpoio_wait().
- */
- ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE);
-
-#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) {
- vpo->vpo_error = VP0_ECMD_TIMEOUT;
- goto error;
- }
- if (vpoio_outstr(vpo, &command[k], 1)) {
- vpo->vpo_error = VP0_EPPDATA_TIMEOUT;
- goto error;
- }
- }
-
-#ifdef VP0_DEBUG
- printf("vpo%d: command sent, now completing the request...\n",
- vpo->vpo_unit);
-#endif
-
- /*
- * Completion ...
- */
- rw = ((command[0] == READ_COMMAND) || (command[0] == READ_BIG) ||
- (command[0] == WRITE_COMMAND) || (command[0] == WRITE_BIG));
-
- *count = 0;
- for (;;) {
-
- if (!(r = vpoio_wait(vpo, VP0_LOW_SPINTMO))) {
- vpo->vpo_error = VP0_ESTATUS_TIMEOUT; goto error;
- }
-
- /* stop when the ZIP wants to send status */
- if (r == (char)0xf0)
- break;
-
- if (*count >= blen) {
- vpo->vpo_error = VP0_EDATA_OVERFLOW;
- goto error;
- }
- len = (rw && ((blen - *count) >= VP0_SECTOR_SIZE)) ?
- VP0_SECTOR_SIZE : 1;
-
- /* ZIP wants to send data? */
- if (r == (char)0xc0)
- error = vpoio_outstr(vpo, &buffer[*count], len);
- else
- error = vpoio_instr(vpo, &buffer[*count], len);
-
- if (error) {
- vpo->vpo_error = error;
- goto error;
- }
-
- *count += len;
- }
-
- if (vpoio_instr(vpo, &l, 1)) {
- 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)) {
- vpo->vpo_error = VP0_EOTHER+2; goto error;
- }
-
- *result = ((int) h << 8) | ((int) l & 0xff);
-
-error:
- /* return to printer state, release the ppbus */
- vpoio_disconnect(vpo);
- return (0);
-}
OpenPOWER on IntegriCloud