diff options
-rw-r--r-- | sys/dev/ppbus/immio.c | 78 | ||||
-rw-r--r-- | sys/dev/ppbus/nlpt.c | 26 | ||||
-rw-r--r-- | sys/dev/ppbus/ppb_msq.c | 22 | ||||
-rw-r--r-- | sys/dev/ppbus/ppbconf.c | 5 | ||||
-rw-r--r-- | sys/dev/ppbus/ppbconf.h | 4 | ||||
-rw-r--r-- | sys/dev/ppbus/vpo.c | 358 | ||||
-rw-r--r-- | sys/dev/ppbus/vpoio.c | 75 |
7 files changed, 357 insertions, 211 deletions
diff --git a/sys/dev/ppbus/immio.c b/sys/dev/ppbus/immio.c index 47ac638..3aeb95a 100644 --- a/sys/dev/ppbus/immio.c +++ b/sys/dev/ppbus/immio.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: immio.c,v 1.1 1998/09/13 18:28:15 nsouch Exp $ * */ @@ -269,7 +269,7 @@ static struct ppb_microseq epp17_instr[] = { }; static int -imm_disconnect(struct vpoio_data *vpo, int *disconnected) +imm_disconnect(struct vpoio_data *vpo, int *connected, int release_bus) { DECLARE_CPP_MICROSEQ; @@ -277,8 +277,8 @@ imm_disconnect(struct vpoio_data *vpo, int *disconnected) int ret; /* all should be ok */ - if (disconnected) - *disconnected = 0; + if (connected) + *connected = 0; ppb_MS_init_msq(cpp_microseq, 4, CPP_S1, (void *)&s1, CPP_S2, (void *)&s2, CPP_S3, (void *)&s3, @@ -287,17 +287,20 @@ imm_disconnect(struct vpoio_data *vpo, int *disconnected) ppb_MS_microseq(&vpo->vpo_dev, cpp_microseq, &ret); if ((s1 != (char)0xb8 || s2 != (char)0x18 || s3 != (char)0x38) && - disconnected) - *disconnected = VP0_ECONNECT; + connected) + *connected = VP0_ECONNECT; - return (ppb_release_bus(&vpo->vpo_dev)); + if (release_bus) + return (ppb_release_bus(&vpo->vpo_dev)); + else + return (0); } /* * how : PPB_WAIT or PPB_DONTWAIT */ static int -imm_connect(struct vpoio_data *vpo, int how, int *not_connected) +imm_connect(struct vpoio_data *vpo, int how, int *disconnected, int request_bus) { DECLARE_CPP_MICROSEQ; @@ -306,11 +309,12 @@ imm_connect(struct vpoio_data *vpo, int how, int *not_connected) int ret; /* all should be ok */ - if (not_connected) - *not_connected = 0; + if (disconnected) + *disconnected = 0; - if ((error = ppb_request_bus(&vpo->vpo_dev, how))) - return (error); + if (request_bus) + if ((error = ppb_request_bus(&vpo->vpo_dev, how))) + return (error); ppb_MS_init_msq(cpp_microseq, 3, CPP_S1, (void *)&s1, CPP_S2, (void *)&s2, CPP_S3, (void *)&s3); @@ -331,8 +335,8 @@ imm_connect(struct vpoio_data *vpo, int how, int *not_connected) ppb_MS_microseq(&vpo->vpo_dev, cpp_microseq, &ret); if ((s1 != (char)0xb8 || s2 != (char)0x18 || s3 != (char)0x30) - && not_connected) - *not_connected = VP0_ECONNECT; + && disconnected) + *disconnected = VP0_ECONNECT; return (0); } @@ -347,24 +351,42 @@ imm_detect(struct vpoio_data *vpo) { int error; - imm_disconnect(vpo, NULL); - imm_connect(vpo, PPB_DONTWAIT, &error); + if ((error = ppb_request_bus(&vpo->vpo_dev, PPB_DONTWAIT))) + return (error); + + /* disconnect the drive, keep the bus */ + imm_disconnect(vpo, NULL, 0); + + /* we already have the bus, just connect */ + imm_connect(vpo, PPB_DONTWAIT, &error, 0); - if (error) - return (VP0_EINITFAILED); + if (error) { + if (bootverbose) + printf("imm%d: can't connect to the drive\n", + vpo->vpo_unit); + goto error; + } /* send SCSI reset signal */ ppb_MS_microseq(&vpo->vpo_dev, reset_microseq, NULL); - imm_disconnect(vpo, &error); + /* release the bus now */ + imm_disconnect(vpo, &error, 1); /* ensure we are disconnected or daisy chained peripheral * may cause serious problem to the disk */ - if (error) - return (VP0_EINITFAILED); + if (error) { + if (bootverbose) + printf("imm%d: can't disconnect from the drive\n", + vpo->vpo_unit); + } return (0); + +error: + ppb_release_bus(&vpo->vpo_dev); + return (VP0_EINITFAILED); } /* @@ -609,18 +631,18 @@ imm_attach(struct vpoio_data *vpo) int imm_reset_bus(struct vpoio_data *vpo) { - int not_connected; + int disconnected; - /* first, connect to the drive */ - imm_connect(vpo, PPB_WAIT|PPB_INTR, ¬_connected); + /* first, connect to the drive and request the bus */ + imm_connect(vpo, PPB_WAIT|PPB_INTR, &disconnected, 1); - if (!not_connected) { + if (!disconnected) { /* reset the SCSI bus */ ppb_MS_microseq(&vpo->vpo_dev, reset_microseq, NULL); /* then disconnect */ - imm_disconnect(vpo, NULL); + imm_disconnect(vpo, NULL, 1); } return (0); @@ -652,7 +674,7 @@ imm_do_scsi(struct vpoio_data *vpo, int host, int target, char *command, * The only way to report the interruption is to return * EIO do upper SCSI code :^( */ - if ((error = imm_connect(vpo, PPB_WAIT|PPB_INTR, ¬_connected))) + if ((error = imm_connect(vpo, PPB_WAIT|PPB_INTR, ¬_connected, 1))) return (error); if (not_connected) { @@ -765,7 +787,7 @@ error: ppb_MS_microseq(&vpo->vpo_dev, transfer_epilog, NULL); /* return to printer state, release the ppbus */ - imm_disconnect(vpo, NULL); + imm_disconnect(vpo, NULL, 1); return (0); } diff --git a/sys/dev/ppbus/nlpt.c b/sys/dev/ppbus/nlpt.c index e855fae..2a48eb4 100644 --- a/sys/dev/ppbus/nlpt.c +++ b/sys/dev/ppbus/nlpt.c @@ -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: nlpt.c,v 1.8 1998/06/07 17:09:48 dfr Exp $ + * $Id: nlpt.c,v 1.9 1998/08/03 19:14:31 msmith Exp $ */ /* @@ -118,6 +118,8 @@ static int nlptattach(struct ppb_device *dev); static void nlptintr(int unit); static void nlpt_drvinit(void *unused); +static void nlpt_intr(int unit); /* without spls */ + #ifdef KERNEL static struct ppb_driver nlptdriver = { @@ -182,7 +184,7 @@ lpt_release_ppbus(struct lpt_data *sc) { int error; - /* we do not have the bus only if the request succeded */ + /* we do not have the bus only if the request succeeded */ if ((error = ppb_release_bus(&sc->lpt_dev)) == 0) sc->sc_state &= ~HAVEBUS; @@ -413,7 +415,7 @@ nlptout(void *arg) */ if (sc->sc_xfercnt) { pl = spltty(); - nlptintr(sc->lpt_unit); + nlpt_intr(sc->lpt_unit); splx(pl); } else { sc->sc_state &= ~OBUSY; @@ -678,7 +680,7 @@ nlptwrite(dev_t dev, struct uio *uio, int ioflag) if ((sc->sc_state & OBUSY) == 0){ nlprintf("\nC %d. ", sc->sc_xfercnt); pl = spltty(); - nlptintr(sc->lpt_unit); + nlpt_intr(sc->lpt_unit); (void) splx(pl); } nlprintf("W "); @@ -707,14 +709,14 @@ nlptwrite(dev_t dev, struct uio *uio, int ioflag) } /* - * nlptintr -- handle printer interrupts which occur when the printer is + * nlpt_intr -- handle printer interrupts which occur when the printer is * ready to accept another char. * * do checking for interrupted write call. */ static void -nlptintr(int unit) +nlpt_intr(int unit) { struct lpt_data *sc = lptdata[unit]; int sts; @@ -768,6 +770,18 @@ nlptintr(int unit) nlprintf("sts %x ", sts); } +static void +nlptintr(int unit) +{ + /* call the interrupt at required spl level */ + int s = spltty(); + + nlpt_intr(unit); + + splx(s); + return; +} + static int nlptioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) { diff --git a/sys/dev/ppbus/ppb_msq.c b/sys/dev/ppbus/ppb_msq.c index 0890e49..7e631e4 100644 --- a/sys/dev/ppbus/ppb_msq.c +++ b/sys/dev/ppbus/ppb_msq.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ppb_msq.c,v 1.1.2.3 1998/06/14 14:36:26 son Exp $ + * $Id: ppb_msq.c,v 1.2 1998/09/13 18:26:26 nsouch Exp $ * */ #include <machine/stdarg.h> @@ -246,8 +246,7 @@ ppb_MS_microseq(struct ppb_device *dev, struct ppb_microseq *msq, int *ret) { struct ppb_data *ppb = dev->ppb; struct ppb_microseq *mi; /* current microinstruction */ - int msq_index; - int pc, error; + int error; struct ppb_xfer *xfer; @@ -261,14 +260,10 @@ ppb_MS_microseq(struct ppb_device *dev, struct ppb_microseq *msq, int *ret) if (ppb->ppb_owner != dev) return (EACCES); -#define INCR_PC (pc ++) +#define INCR_PC (mi ++) - pc = 0; + mi = msq; for (;;) { - - /* retrieve the next microinstruction to execute */ - mi = &msq[pc]; - switch (mi->opcode) { case MS_OP_PUT: case MS_OP_GET: @@ -314,15 +309,12 @@ ppb_MS_microseq(struct ppb_device *dev, struct ppb_microseq *msq, int *ret) * is unknown here */ if ((error = ppb->ppb_link->adapter->exec_microseq( - dev->id_unit, msq, &pc))) - return (error); - + dev->id_unit, &mi))) + goto error; break; } } error: - if (ret) - *ret = error; - return (0); + return (error); } diff --git a/sys/dev/ppbus/ppbconf.c b/sys/dev/ppbus/ppbconf.c index b9c2ca0..86ebe02 100644 --- a/sys/dev/ppbus/ppbconf.c +++ b/sys/dev/ppbus/ppbconf.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ppbconf.c,v 1.6 1998/08/03 19:14:31 msmith Exp $ + * $Id: ppbconf.c,v 1.7 1998/09/13 18:26:26 nsouch Exp $ * */ #include <sys/param.h> @@ -264,8 +264,11 @@ ppb_attachdevs(struct ppb_data *ppb) LIST_INIT(&ppb->ppb_devs); /* initialise device/driver list */ p_drvpp = (struct ppb_driver **)ppbdriver_set.ls_items; +/* XXX wait for ieee1284 good support */ +#if 0 /* detect PnP devices */ ppb->class_id = ppb_pnp_detect(ppb); +#endif /* * Blindly try all probes here. Later we should look at diff --git a/sys/dev/ppbus/ppbconf.h b/sys/dev/ppbus/ppbconf.h index c941541..80efe28 100644 --- a/sys/dev/ppbus/ppbconf.h +++ b/sys/dev/ppbus/ppbconf.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ppbconf.h,v 1.7 1998/08/03 19:14:31 msmith Exp $ + * $Id: ppbconf.h,v 1.8 1998/09/13 18:26:26 nsouch Exp $ * */ #ifndef __PPBCONF_H @@ -181,7 +181,7 @@ struct ppb_adapter { void (*reset_epp_timeout)(int); void (*ecp_sync)(int); - int (*exec_microseq)(int, struct ppb_microseq *, int *); + int (*exec_microseq)(int, struct ppb_microseq **); int (*setmode)(int, int); diff --git a/sys/dev/ppbus/vpo.c b/sys/dev/ppbus/vpo.c index d728b62..0585a49 100644 --- a/sys/dev/ppbus/vpo.c +++ b/sys/dev/ppbus/vpo.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: vpo.c,v 1.6 1998/08/03 19:14:31 msmith Exp $ + * $Id: vpo.c,v 1.4 1997/09/01 00:51:52 bde Exp $ * */ @@ -36,8 +36,16 @@ #include <machine/clock.h> #endif /* KERNEL */ -#include <scsi/scsi_disk.h> -#include <scsi/scsiconf.h> + +#include <cam/cam.h> +#include <cam/cam_ccb.h> +#include <cam/cam_sim.h> +#include <cam/cam_xpt_sim.h> +#include <cam/cam_debug.h> + +#include <cam/scsi/scsi_all.h> +#include <cam/scsi/scsi_message.h> +#include <cam/scsi/scsi_da.h> #ifdef KERNEL #include <sys/kernel.h> @@ -46,8 +54,6 @@ #include <dev/ppbus/ppbconf.h> #include <dev/ppbus/vpoio.h> -#define VP0_BUFFER_SIZE 0x12000 - struct vpo_sense { struct scsi_sense cmd; unsigned int stat; @@ -63,56 +69,27 @@ struct vpo_data { int vpo_isplus; - struct ppb_status vpo_status; - struct vpo_sense vpo_sense; + struct cam_sim *sim; + struct cam_path *path; - unsigned char vpo_buffer[VP0_BUFFER_SIZE]; + struct vpo_sense vpo_sense; struct vpoio_data vpo_io; /* interface to low level functions */ - - struct scsi_link sc_link; }; - -static int32_t vpo_scsi_cmd(struct scsi_xfer *); -static void vpominphys(struct buf *); -static u_int32_t vpo_adapter_info(int); +/* cam related functions */ +static void vpo_action(struct cam_sim *sim, union ccb *ccb); +static void vpo_poll(struct cam_sim *sim); static int nvpo = 0; #define MAXVP0 8 /* XXX not much better! */ static struct vpo_data *vpodata[MAXVP0]; -static struct scsi_adapter vpo_switch = -{ - vpo_scsi_cmd, - vpominphys, - 0, - 0, - vpo_adapter_info, - "vpo", - { 0, 0 } -}; - -/* - * The below structure is so we have a default dev struct - * for out link struct. - */ -static struct scsi_device vpo_dev = -{ - NULL, /* Use default error handler */ - NULL, /* have a queue, served by this */ - NULL, /* have no async handler */ - NULL, /* Use default 'done' routine */ - "vpo", - 0, - { 0, 0 } -}; - +#ifdef KERNEL /* * Make ourselves visible as a ppbus driver */ - static struct ppb_device *vpoprobe(struct ppb_data *ppb); static int vpoattach(struct ppb_device *dev); @@ -121,13 +98,7 @@ static struct ppb_driver vpodriver = { }; DATA_SET(ppbdriver_set, vpodriver); - -static u_int32_t -vpo_adapter_info(int unit) -{ - - return 1; -} +#endif /* KERNEL */ /* * vpoprobe() @@ -164,10 +135,13 @@ vpoprobe(struct ppb_data *ppb) /* low level probe */ vpoio_set_unit(&vpo->vpo_io, vpo->vpo_unit); - if ((dev = imm_probe(ppb, &vpo->vpo_io))) { + /* check ZIP before ZIP+ or imm_probe() will send controls to + * the printer or whatelse connected to the port */ + if ((dev = vpoio_probe(ppb, &vpo->vpo_io))) { + vpo->vpo_isplus = 0; + } else if ((dev = imm_probe(ppb, &vpo->vpo_io))) { vpo->vpo_isplus = 1; - - } else if (!(dev = vpoio_probe(ppb, &vpo->vpo_io))) { + } else { free(vpo, M_DEVBUF); return (NULL); } @@ -183,9 +157,9 @@ vpoprobe(struct ppb_data *ppb) static int vpoattach(struct ppb_device *dev) { - struct scsibus_data *scbus; struct vpo_data *vpo = vpodata[dev->id_unit]; + struct cam_devq *devq; /* low level attachment */ if (vpo->vpo_isplus) { @@ -196,175 +170,271 @@ vpoattach(struct ppb_device *dev) return (0); } - vpo->sc_link.adapter_unit = vpo->vpo_unit; - vpo->sc_link.adapter_targ = VP0_INITIATOR; - vpo->sc_link.adapter = &vpo_switch; - vpo->sc_link.device = &vpo_dev; - vpo->sc_link.opennings = VP0_OPENNINGS; - /* - * Prepare the scsibus_data area for the upperlevel - * scsi code. - */ - scbus = scsi_alloc_bus(); - if(!scbus) + ** Now tell the generic SCSI layer + ** about our bus. + */ + devq = cam_simq_alloc(/*maxopenings*/1); + /* XXX What about low-level detach on error? */ + if (devq == NULL) return (0); - scbus->adapter_link = &vpo->sc_link; - - /* all went ok */ - printf("vpo%d: <Iomega PPA-3/VPI0/IMM SCSI controller>\n", - dev->id_unit); - scsi_attachdevs(scbus); + vpo->sim = cam_sim_alloc(vpo_action, vpo_poll, "vpo", vpo, dev->id_unit, + /*untagged*/1, /*tagged*/0, devq); + if (vpo->sim == NULL) { + cam_simq_free(devq); + return (0); + } - return (1); -} + cam_sim_set_basexfer_speed(vpo->sim, 93/*kB/s*/); + if (xpt_bus_register(vpo->sim, /*bus*/0) != CAM_SUCCESS) { + cam_sim_free(vpo->sim, /*free_devq*/TRUE); + return (0); + } -static void -vpominphys(struct buf *bp) -{ + if (xpt_create_path(&vpo->path, /*periph*/NULL, + cam_sim_path(vpo->sim), CAM_TARGET_WILDCARD, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + xpt_bus_deregister(cam_sim_path(vpo->sim)); + cam_sim_free(vpo->sim, /*free_devq*/TRUE); + return (0); + } - if (bp->b_bcount > VP0_BUFFER_SIZE) - bp->b_bcount = VP0_BUFFER_SIZE; + /* all went ok */ - return; + return (1); } /* * vpo_intr() */ static void -vpo_intr(struct vpo_data *vpo, struct scsi_xfer *xs) +vpo_intr(struct vpo_data *vpo, struct ccb_scsiio *csio) { - int errno; /* error in errno.h */ + int i, errno; /* error in errno.h */ + int s; - if (xs->datalen && !(xs->flags & SCSI_DATA_IN)) - bcopy(xs->data, vpo->vpo_buffer, xs->datalen); + s = splcam(); if (vpo->vpo_isplus) { errno = imm_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_error); + csio->ccb_h.target_id, + (char *)&csio->cdb_io.cdb_bytes, csio->cdb_len, + (char *)csio->data_ptr, csio->dxfer_len, + &vpo->vpo_stat, &vpo->vpo_count, &vpo->vpo_error); } else { 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_error); + csio->ccb_h.target_id, + (char *)&csio->cdb_io.cdb_bytes, csio->cdb_len, + (char *)csio->data_ptr, csio->dxfer_len, + &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", errno, vpo->vpo_stat, vpo->vpo_count, vpo->vpo_error); + + /* dump of command */ + for (i=0; i<csio->cdb_len; i++) + printf("%x ", ((char *)&csio->cdb_io.cdb_bytes)[i]); + + printf("\n"); #endif if (errno) { -#ifdef VP0_WARNING - log(LOG_WARNING, "vpo%d: errno = %d\n", vpo->vpo_unit, errno); -#endif /* connection to ppbus interrupted */ - xs->error = XS_DRIVER_STUFFUP; + csio->ccb_h.status = CAM_CMD_TIMEOUT; goto error; } /* if a timeout occured, no sense */ if (vpo->vpo_error) { - xs->error = XS_TIMEOUT; + if (vpo->vpo_error != VP0_ESELECT_TIMEOUT) + printf("vpo%d: VP0 error/timeout (%d)\n", + vpo->vpo_unit, vpo->vpo_error); + + csio->ccb_h.status = CAM_CMD_TIMEOUT; goto error; } -#define RESERVED_BITS_MASK 0x3e /* 00111110b */ -#define NO_SENSE 0x0 -#define CHECK_CONDITION 0x02 + /* check scsi status */ + if (vpo->vpo_stat != SCSI_STATUS_OK) { + csio->scsi_status = vpo->vpo_stat; - switch (vpo->vpo_stat & RESERVED_BITS_MASK) { - case NO_SENSE: - break; + /* check if we have to sense the drive */ + if ((vpo->vpo_stat & SCSI_STATUS_CHECK_COND) != 0) { - case CHECK_CONDITION: - vpo->vpo_sense.cmd.op_code = REQUEST_SENSE; - vpo->vpo_sense.cmd.length = sizeof(xs->sense); + vpo->vpo_sense.cmd.opcode = REQUEST_SENSE; + vpo->vpo_sense.cmd.length = csio->sense_len; vpo->vpo_sense.cmd.control = 0; if (vpo->vpo_isplus) { errno = imm_do_scsi(&vpo->vpo_io, VP0_INITIATOR, - xs->sc_link->target, + csio->ccb_h.target_id, (char *)&vpo->vpo_sense.cmd, sizeof(vpo->vpo_sense.cmd), - (char *)&xs->sense, sizeof(xs->sense), + (char *)&csio->sense_data, csio->sense_len, &vpo->vpo_sense.stat, &vpo->vpo_sense.count, &vpo->vpo_error); } else { errno = vpoio_do_scsi(&vpo->vpo_io, VP0_INITIATOR, - xs->sc_link->target, + csio->ccb_h.target_id, (char *)&vpo->vpo_sense.cmd, sizeof(vpo->vpo_sense.cmd), - (char *)&xs->sense, sizeof(xs->sense), + (char *)&csio->sense_data, csio->sense_len, &vpo->vpo_sense.stat, &vpo->vpo_sense.count, &vpo->vpo_error); } + - if (errno) - /* connection to ppbus interrupted */ - xs->error = XS_DRIVER_STUFFUP; - else - xs->error = XS_SENSE; +#ifdef VP0_DEBUG + printf("(sense) vpo_do_scsi = %d, status = 0x%x, count = %d, vpo_error = %d\n", + errno, vpo->vpo_sense.stat, vpo->vpo_sense.count, vpo->vpo_error); +#endif - goto error; + /* check sense return status */ + if (errno == 0 && vpo->vpo_sense.stat == SCSI_STATUS_OK) { + /* sense ok */ + csio->ccb_h.status = CAM_AUTOSNS_VALID | CAM_SCSI_STATUS_ERROR; + csio->sense_resid = csio->sense_len - vpo->vpo_sense.count; - default: /* BUSY or RESERVATION_CONFLICT */ - xs->error = XS_TIMEOUT; - goto error; - } +#ifdef VP0_DEBUG + /* dump of sense info */ + printf("(sense) "); + for (i=0; i<vpo->vpo_sense.count; i++) + printf("%x ", ((char *)&csio->sense_data)[i]); + printf("\n"); +#endif - if (xs->datalen && (xs->flags & SCSI_DATA_IN)) - bcopy(vpo->vpo_buffer, xs->data, xs->datalen); + } else { + /* sense failed */ + csio->ccb_h.status = CAM_AUTOSENSE_FAIL; + } + } else { + /* no sense */ + csio->ccb_h.status = CAM_SCSI_STATUS_ERROR; + } + + goto error; + } -done: - xs->resid = 0; - xs->error = XS_NOERROR; + csio->resid = csio->dxfer_len - vpo->vpo_count; + csio->ccb_h.status = CAM_REQ_CMP; error: - xs->flags |= ITSDONE; - scsi_done(xs); + splx(s); return; } -static int32_t -vpo_scsi_cmd(struct scsi_xfer *xs) +static void +vpo_action(struct cam_sim *sim, union ccb *ccb) { - int s; + struct vpo_data *vpo = (struct vpo_data *)sim->softc; - if (xs->sc_link->lun > 0) { - xs->error = XS_DRIVER_STUFFUP; - return TRY_AGAIN_LATER; - } + switch (ccb->ccb_h.func_code) { + case XPT_SCSI_IO: + { + struct ccb_scsiio *csio; + + csio = &ccb->csio; - if (xs->flags & SCSI_DATA_UIO) { - printf("UIO not supported by vpo_driver !\n"); - xs->error = XS_DRIVER_STUFFUP; - return TRY_AGAIN_LATER; +#ifdef VP0_DEBUG + printf("vpo%d: XPT_SCSI_IO (0x%x) request\n", + vpo->vpo_unit, csio->cdb_io.cdb_bytes[0]); +#endif + + vpo_intr(vpo, csio); + + xpt_done(ccb); + + break; } + case XPT_CALC_GEOMETRY: + { + struct ccb_calc_geometry *ccg; + u_int32_t size_mb; + u_int32_t secs_per_cylinder; + + ccg = &ccb->ccg; + size_mb = ccg->volume_size + / ((1024L * 1024L) / ccg->block_size); #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, - xs->cmdlen, xs->cmd, " " ); + printf("vpo%d: XPT_CALC_GEOMETRY (%d, %d) request\n", + vpo->vpo_unit, ccg->volume_size, ccg->block_size); #endif + + ccg->heads = 64; + ccg->secs_per_track = 32; - if (xs->flags & SCSI_NOMASK) { - vpo_intr(vpodata[xs->sc_link->adapter_unit], xs); - return COMPLETE; + secs_per_cylinder = ccg->heads * ccg->secs_per_track; + ccg->cylinders = ccg->volume_size / secs_per_cylinder; + + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; } + case XPT_RESET_BUS: /* Reset the specified SCSI bus */ + { - s = splbio(); +#ifdef VP0_DEBUG + printf("vpo%d: XPT_RESET_BUS request\n", vpo->vpo_unit); +#endif - vpo_intr(vpodata[xs->sc_link->adapter_unit], xs); + if (vpo->vpo_isplus) { + if (imm_reset_bus(&vpo->vpo_io)) { + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + xpt_done(ccb); + return; + } + } else { + if (vpoio_reset_bus(&vpo->vpo_io)) { + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + xpt_done(ccb); + return; + } + } - splx(s); - return SUCCESSFULLY_QUEUED; + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + case XPT_PATH_INQ: /* Path routing inquiry */ + { + struct ccb_pathinq *cpi = &ccb->cpi; + +#ifdef VP0_DEBUG + printf("vpo%d: XPT_PATH_INQ request\n", vpo->vpo_unit); +#endif + cpi->version_num = 1; /* XXX??? */ + cpi->max_target = 7; + cpi->max_lun = 0; + cpi->initiator_id = VP0_INITIATOR; + cpi->bus_id = sim->bus_id; + strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); + strncpy(cpi->hba_vid, "Iomega", HBA_IDLEN); + strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN); + cpi->unit_number = sim->unit_number; + + cpi->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + default: + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + } + + return; +} + +static void +vpo_poll(struct cam_sim *sim) +{ + /* The ZIP is actually always polled throw vpo_action() */ + return; } diff --git a/sys/dev/ppbus/vpoio.c b/sys/dev/ppbus/vpoio.c index 8c1bf18..a416efe 100644 --- a/sys/dev/ppbus/vpoio.c +++ b/sys/dev/ppbus/vpoio.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: vpoio.c,v 1.1.2.6 1998/08/07 01:59:49 son Exp $ + * $Id: vpoio.c,v 1.2 1998/09/13 18:26:26 nsouch Exp $ * */ @@ -261,9 +261,9 @@ static struct ppb_microseq in_disk_mode[] = { MS_CASS( H_AUTO | H_nSELIN | H_INIT | H_STROBE), MS_BRSET(H_FLT, 2 /* error */), - MS_RET(0), + MS_RET(1), /* error: */ - MS_RET(1) + MS_RET(0) }; static int @@ -343,26 +343,64 @@ vpoio_in_disk_mode(struct vpoio_data *vpo) static int vpoio_detect(struct vpoio_data *vpo) { - vpoio_disconnect(vpo); - vpoio_connect(vpo, PPB_DONTWAIT); + int error, ret; - if (vpoio_in_disk_mode(vpo)) { - vpoio_disconnect(vpo); - return (VP0_EINITFAILED); + /* allocate the bus, then apply microsequences */ + if ((error = ppb_request_bus(&vpo->vpo_dev, PPB_DONTWAIT))) + return (error); + + ppb_MS_microseq(&vpo->vpo_dev, disconnect_microseq, &ret); + + if (PPB_IN_EPP_MODE(&vpo->vpo_dev)) + ppb_MS_microseq(&vpo->vpo_dev, connect_epp_microseq, &ret); + else + ppb_MS_microseq(&vpo->vpo_dev, connect_spp_microseq, &ret); + + ppb_MS_microseq(&vpo->vpo_dev, in_disk_mode, &ret); + if (!ret) { + + /* try spp mode (maybe twice or because previous mode was PS2) + * NIBBLE mode will be restored on next transfers if detection + * succeed + */ + ppb_set_mode(&vpo->vpo_dev, PPB_NIBBLE); + ppb_MS_microseq(&vpo->vpo_dev, connect_spp_microseq, &ret); + + ppb_MS_microseq(&vpo->vpo_dev, in_disk_mode, &ret); + if (!ret) { + if (bootverbose) + printf("vpo%d: can't connect to the drive\n", + vpo->vpo_unit); + + /* disconnect and release the bus */ + ppb_MS_microseq(&vpo->vpo_dev, disconnect_microseq, + &ret); + goto error; + } } /* send SCSI reset signal */ vpoio_reset(vpo); - vpoio_disconnect(vpo); + ppb_MS_microseq(&vpo->vpo_dev, disconnect_microseq, &ret); /* ensure we are disconnected or daisy chained peripheral * may cause serious problem to the disk */ - if (!vpoio_in_disk_mode(vpo)) - return (VP0_EINITFAILED); + ppb_MS_microseq(&vpo->vpo_dev, in_disk_mode, &ret); + if (ret) { + if (bootverbose) + printf("vpo%d: can't disconnect from the drive\n", + vpo->vpo_unit); + goto error; + } + ppb_release_bus(&vpo->vpo_dev); return (0); + +error: + ppb_release_bus(&vpo->vpo_dev); + return (VP0_EINITFAILED); } /* @@ -666,7 +704,7 @@ int vpoio_reset_bus(struct vpoio_data *vpo) { /* first, connect to the drive */ - if (vpoio_connect(vpo, PPB_WAIT|PPB_INTR) || vpoio_in_disk_mode(vpo)) { + if (vpoio_connect(vpo, PPB_WAIT|PPB_INTR) || !vpoio_in_disk_mode(vpo)) { /* release ppbus */ vpoio_disconnect(vpo); return (1); @@ -709,7 +747,7 @@ vpoio_do_scsi(struct vpoio_data *vpo, int host, int target, char *command, if ((error = vpoio_connect(vpo, PPB_WAIT|PPB_INTR))) return (error); - if (vpoio_in_disk_mode(vpo)) { + if (!vpoio_in_disk_mode(vpo)) { *ret = VP0_ECONNECT; goto error; } @@ -753,8 +791,15 @@ vpoio_do_scsi(struct vpoio_data *vpo, int host, int target, char *command, *ret = VP0_EDATA_OVERFLOW; goto error; } - len = (((blen - *count) >= VP0_SECTOR_SIZE)) ? - VP0_SECTOR_SIZE : 1; + + /* if in EPP mode or writing bytes, try to transfer a sector + * otherwise, just send one byte + */ + if (PPB_IN_EPP_MODE(&vpo->vpo_dev) || r == (char)0xc0) + len = (((blen - *count) >= VP0_SECTOR_SIZE)) ? + VP0_SECTOR_SIZE : 1; + else + len = 1; /* ZIP wants to send data? */ if (r == (char)0xc0) |