summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ppbus/immio.c78
-rw-r--r--sys/dev/ppbus/nlpt.c26
-rw-r--r--sys/dev/ppbus/ppb_msq.c22
-rw-r--r--sys/dev/ppbus/ppbconf.c5
-rw-r--r--sys/dev/ppbus/ppbconf.h4
-rw-r--r--sys/dev/ppbus/vpo.c358
-rw-r--r--sys/dev/ppbus/vpoio.c75
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, &not_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, &not_connected)))
+ if ((error = imm_connect(vpo, PPB_WAIT|PPB_INTR, &not_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)
OpenPOWER on IntegriCloud