summaryrefslogtreecommitdiffstats
path: root/sys/scsi/ch.c
diff options
context:
space:
mode:
authorrgrimes <rgrimes@FreeBSD.org>1993-11-18 05:03:27 +0000
committerrgrimes <rgrimes@FreeBSD.org>1993-11-18 05:03:27 +0000
commit73dd2628a2d9f88e008196681e15c6d3a0dc11be (patch)
tree6d93e911e7337a8936028ed9a12d64183f6766d3 /sys/scsi/ch.c
parentdbf6b5a2db39d182aba158f88c9cd5005db5d6e0 (diff)
downloadFreeBSD-src-73dd2628a2d9f88e008196681e15c6d3a0dc11be.zip
FreeBSD-src-73dd2628a2d9f88e008196681e15c6d3a0dc11be.tar.gz
New version of scsi code from Julian
Diffstat (limited to 'sys/scsi/ch.c')
-rw-r--r--sys/scsi/ch.c1204
1 files changed, 352 insertions, 852 deletions
diff --git a/sys/scsi/ch.c b/sys/scsi/ch.c
index a76d522..c403fe5 100644
--- a/sys/scsi/ch.c
+++ b/sys/scsi/ch.c
@@ -1,7 +1,8 @@
/*
- * Written by Julian Elischer (julian@tfs.com)
+ * Written by grefen@?????
+ * Based on scsi drivers by Julian Elischer (julian@tfs.com)
*
- * $Id$
+ * $Id: ch.c,v 2.2 93/10/16 00:58:30 julian Exp Locker: julian $
*/
#include <sys/types.h>
@@ -17,965 +18,464 @@
#include <sys/user.h>
#include <sys/chio.h>
-#if defined(OSF)
-#define SECSIZE 512
-#endif /* defined(OSF) */
-
#include <scsi/scsi_all.h>
#include <scsi/scsi_changer.h>
#include <scsi/scsiconf.h>
-
-struct scsi_xfer ch_scsi_xfer[NCH];
-int ch_xfer_block_wait[NCH];
-
+struct scsi_xfer ch_scsi_xfer[NCH];
+u_int32 ch_xfer_block_wait[NCH];
#define PAGESIZ 4096
#define STQSIZE 4
-#define CH_RETRIES 4
-
+#define CHRETRIES 2
#define MODE(z) ( (minor(z) & 0x0F) )
#define UNIT(z) ( (minor(z) >> 4) )
-#ifndef MACH
#define ESUCCESS 0
-#endif MACH
-int ch_info_valid[NCH]; /* the info about the device is valid */
-int ch_initialized[NCH] ;
-int ch_debug = 1;
+errval chattach();
-int chattach();
-int ch_done();
-struct ch_data
+/*
+ * This driver is so simple it uses all the default services
+ */
+struct scsi_device ch_switch =
{
- int flags;
- struct scsi_switch *sc_sw; /* address of scsi low level switch */
- int ctlr; /* so they know which one we want */
- int targ; /* our scsi target ID */
- int lu; /* out scsi lu */
- short chmo; /* Offset of first CHM */
- short chms; /* No. of CHM */
- short slots; /* No. of Storage Elements */
- short sloto; /* Offset of first SE */
- short imexs; /* No. of Import/Export Slots */
- short imexo; /* Offset of first IM/EX */
- short drives; /* No. of CTS */
- short driveo; /* Offset of first CTS */
- short rot; /* CHM can rotate */
- u_long op_matrix; /* possible opertaions */
- u_short lsterr; /* details of lasterror */
- u_char stor; /* posible Storage locations */
-}ch_data[NCH];
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "ch",
+ 0,
+ 0, 0
+};
+
+struct ch_data {
+ u_int32 flags;
+ struct scsi_link *sc_link; /* all the inter level info */
+ u_int16 chmo; /* Offset of first CHM */
+ u_int16 chms; /* No. of CHM */
+ u_int16 slots; /* No. of Storage Elements */
+ u_int16 sloto; /* Offset of first SE */
+ u_int16 imexs; /* No. of Import/Export Slots */
+ u_int16 imexo; /* Offset of first IM/EX */
+ u_int16 drives; /* No. of CTS */
+ u_int16 driveo; /* Offset of first CTS */
+ u_int16 rot; /* CHM can rotate */
+ u_long op_matrix; /* possible opertaions */
+ u_int16 lsterr; /* details of lasterror */
+ u_char stor; /* posible Storage locations */
+ u_int32 initialized;
+} ch_data[NCH];
#define CH_OPEN 0x01
#define CH_KNOWN 0x02
-static int next_ch_unit = 0;
-/***********************************************************************\
-* The routine called by the low level scsi routine when it discovers *
-* A device suitable for this driver *
-\***********************************************************************/
+static u_int32 next_ch_unit = 0;
-int chattach(ctlr,targ,lu,scsi_switch)
-struct scsi_switch *scsi_switch;
+/*
+ * The routine called by the low level scsi routine when it discovers
+ * a device suitable for this driver.
+ */
+errval
+chattach(sc_link)
+ struct scsi_link *sc_link;
{
- int unit,i,stat;
+ u_int32 unit, i, stat;
unsigned char *tbl;
- if(scsi_debug & PRINTROUTINES) printf("chattach: ");
- /*******************************************************\
- * Check we have the resources for another drive *
- \*******************************************************/
+ SC_DEBUG(sc_link, SDEV_DB2, ("chattach: "));
+ /*
+ * Check we have the resources for another drive
+ */
unit = next_ch_unit++;
- if( unit >= NCH)
- {
- printf("Too many scsi changers..(%d > %d) reconfigure kernel\n",(unit + 1),NCH);
- return(0);
- }
- /*******************************************************\
- * Store information needed to contact our base driver *
- \*******************************************************/
- ch_data[unit].sc_sw = scsi_switch;
- ch_data[unit].ctlr = ctlr;
- ch_data[unit].targ = targ;
- ch_data[unit].lu = lu;
-
- /*******************************************************\
- * Use the subdriver to request information regarding *
- * the drive. We cannot use interrupts yet, so the *
- * request must specify this. *
- \*******************************************************/
- if((ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK /*| SCSI_SILENT*/)))
- {
- printf("ch%d: scsi changer, %d slot(s) %d drive(s) %d arm(s) %d i/e-slot(s)\n",
- unit, ch_data[unit].slots, ch_data[unit].drives, ch_data[unit].chms, ch_data[unit].imexs);
- stat=CH_KNOWN;
+ if (unit >= NCH) {
+ printf("Too many scsi changers..(%d > %d) reconfigure kernel\n", (unit + 1), NCH);
+ return (0);
}
- else
- {
+ /*
+ * Store information needed to contact our base driver
+ */
+ ch_data[unit].sc_link = sc_link;
+ sc_link->device = &ch_switch;
+ sc_link->dev_unit = unit;
+
+ /*
+ * Use the subdriver to request information regarding
+ * the drive. We cannot use interrupts yet, so the
+ * request must specify this.
+ */
+ if ((ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK /*| SCSI_SILENT */ ))) {
printf("ch%d: scsi changer :- offline\n", unit);
- stat=CH_OPEN;
+ stat = CH_OPEN;
+ } else {
+ printf("ch%d: scsi changer, %d slot(s) %d drive(s) %d arm(s) %d i/e-slot(s)\n",
+ unit, ch_data[unit].slots, ch_data[unit].drives, ch_data[unit].chms, ch_data[unit].imexs);
+ stat = CH_KNOWN;
}
- ch_initialized[unit] = stat;
+ ch_data[unit].initialized = 1;
return;
}
-
-
-/*******************************************************\
-* open the device. *
-\*******************************************************/
+/*
+ * open the device.
+ */
+errval
chopen(dev)
{
- int errcode = 0;
- int unit,mode;
+ errval errcode = 0;
+ u_int32 unit, mode;
+ struct scsi_link *sc_link;
unit = UNIT(dev);
mode = MODE(dev);
- /*******************************************************\
- * Check the unit is legal *
- \*******************************************************/
- if ( unit >= NCH )
- {
- printf("ch%d: ch %d > %d\n",unit,unit,NCH);
- errcode = ENXIO;
- return(errcode);
- }
- /*******************************************************\
- * Only allow one at a time *
- \*******************************************************/
- if(ch_data[unit].flags & CH_OPEN)
- {
- printf("ch%d: already open\n",unit);
+ /*
+ * Check the unit is legal
+ */
+ if (unit >= NCH) {
+ printf("ch%d: ch %d > %d\n", unit, unit, NCH);
errcode = ENXIO;
- goto bad;
+ return (errcode);
}
-
- if(ch_debug||(scsi_debug & (PRINTROUTINES | TRACEOPENS)))
- printf("chopen: dev=0x%x (unit %d (of %d))\n"
- , dev, unit, NCH);
- /*******************************************************\
- * Make sure the device has been initialised *
- \*******************************************************/
-
- if (!ch_initialized[unit])
- return(ENXIO);
- if (ch_initialized[unit]!=CH_KNOWN) {
- if((ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK /*| SCSI_SILENT*/)))
- {
- ch_initialized[unit]=CH_KNOWN;
- }
- else
- {
- printf("ch%d: scsi changer :- offline\n", unit);
- return(ENXIO);
- }
+ /*
+ * Only allow one at a time
+ */
+ if (ch_data[unit].flags & CH_OPEN) {
+ printf("ch%d: already open\n", unit);
+ return ENXIO;
}
- /*******************************************************\
- * Check that it is still responding and ok. *
- \*******************************************************/
-
- if(ch_debug || (scsi_debug & TRACEOPENS))
- printf("device is ");
- if (!(ch_req_sense(unit, 0)))
- {
- errcode = ENXIO;
- if(ch_debug || (scsi_debug & TRACEOPENS))
- printf("not responding\n");
- goto bad;
+ /*
+ * Make sure the device has been initialised
+ */
+ if (!ch_data[unit].initialized)
+ return (ENXIO);
+
+ sc_link = ch_data[unit].sc_link;
+
+ SC_DEBUG(sc_link, SDEV_DB1, ("chopen: dev=0x%x (unit %d (of %d))\n"
+ ,dev, unit, NCH));
+ /*
+ * Catch any unit attention errors.
+ */
+ scsi_test_unit_ready(sc_link, SCSI_SILENT);
+
+ sc_link->flags |= SDEV_OPEN;
+ /*
+ * Check that it is still responding and ok.
+ */
+ if (errcode = (scsi_test_unit_ready(sc_link, 0))) {
+ printf("ch%d: not ready\n", unit);
+ sc_link->flags &= ~SDEV_OPEN;
+ return errcode;
}
- if(ch_debug || (scsi_debug & TRACEOPENS))
- printf("ok\n");
-
- if(!(ch_test_ready(unit,0)))
- {
- printf("ch%d: not ready\n",unit);
- return(EIO);
+ /*
+ * Make sure data is loaded
+ */
+ if (errcode = (ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK))) {
+ printf("ch%d: scsi changer :- offline\n", unit);
+ sc_link->flags &= ~SDEV_OPEN;
+ return (errcode);
}
-
- ch_info_valid[unit] = TRUE;
-
- /*******************************************************\
- * Load the physical device parameters *
- \*******************************************************/
-
ch_data[unit].flags = CH_OPEN;
- return(errcode);
-bad:
- return(errcode);
+ return 0;
}
-/*******************************************************\
-* close the device.. only called if we are the LAST *
-* occurence of an open device *
-\*******************************************************/
+/*
+ * close the device.. only called if we are the LAST
+ * occurence of an open device
+ */
+errval
chclose(dev)
{
- unsigned char unit,mode;
+ unsigned char unit, mode;
+ struct scsi_link *sc_link;
unit = UNIT(dev);
mode = MODE(dev);
+ sc_link = ch_data[unit].sc_link;
- if(scsi_debug & TRACEOPENS)
- printf("Closing device");
+ SC_DEBUG(sc_link, SDEV_DB1, ("Closing device"));
ch_data[unit].flags = 0;
- return(0);
-}
-
-
-
-/***************************************************************\
-* chstart *
-* This routine is also called after other non-queued requests *
-* have been made of the scsi driver, to ensure that the queue *
-* continues to be drained. *
-\***************************************************************/
-/* chstart() is called at splbio */
-chstart(unit)
-{
- int drivecount;
- register struct buf *bp = 0;
- register struct buf *dp;
- struct scsi_xfer *xs;
- int blkno, nblk;
-
-
- if(scsi_debug & PRINTROUTINES) printf("chstart%d ",unit);
- /*******************************************************\
- * See if there is a buf to do and we are not already *
- * doing one *
- \*******************************************************/
- xs=&ch_scsi_xfer[unit];
- if(xs->flags & INUSE)
- {
- return; /* unit already underway */
- }
- if(ch_xfer_block_wait[unit]) /* a special awaits, let it proceed first */
- {
- wakeup(&ch_xfer_block_wait[unit]);
- return;
- }
-
- return;
-
+ sc_link->flags &= ~SDEV_OPEN;
+ return (0);
}
-
-/*******************************************************\
-* This routine is called by the scsi interrupt when *
-* the transfer is complete.
-\*******************************************************/
-int ch_done(unit,xs)
-int unit;
-struct scsi_xfer *xs;
-{
- struct buf *bp;
- int retval;
-
- if(ch_debug||(scsi_debug & PRINTROUTINES)) printf("ch_done%d ",unit);
- if (! (xs->flags & INUSE))
- panic("scsi_xfer not in use!");
- wakeup(xs);
-}
-/*******************************************************\
-* Perform special action on behalf of the user *
-* Knows about the internals of this device *
-\*******************************************************/
+/*
+ * Perform special action on behalf of the user
+ * Knows about the internals of this device
+ */
+errval
chioctl(dev, cmd, arg, mode)
-dev_t dev;
-int cmd;
-caddr_t arg;
+ dev_t dev;
+ u_int32 cmd;
+ caddr_t arg;
{
- /* struct ch_cmd_buf *args;*/
+ /* struct ch_cmd_buf *args; */
union scsi_cmd *scsi_cmd;
- register i,j;
- unsigned int opri;
- int errcode = 0;
+ register i, j;
+ u_int32 opri;
+ errval errcode = 0;
unsigned char unit;
- int number,flags,ret;
-
- /*******************************************************\
- * Find the device that the user is talking about *
- \*******************************************************/
- flags = 0; /* give error messages, act on errors etc. */
+ u_int32 number, flags;
+ errval ret;
+ struct scsi_link *sc_link;
+
+ /*
+ * Find the device that the user is talking about
+ */
+ flags = 0; /* give error messages, act on errors etc. */
unit = UNIT(dev);
-
- switch(cmd)
- {
- case CHIOOP: {
- struct chop *ch=(struct chop *) arg;
- if (ch_debug)
- printf("[chtape_chop: %x]\n", ch->ch_op);
-
- switch ((short)(ch->ch_op)) {
- case CHGETPARAM:
- ch->u.getparam.chmo= ch_data[unit].chmo;
- ch->u.getparam.chms= ch_data[unit].chms;
- ch->u.getparam.sloto= ch_data[unit].sloto;
- ch->u.getparam.slots= ch_data[unit].slots;
- ch->u.getparam.imexo= ch_data[unit].imexo;
- ch->u.getparam.imexs= ch_data[unit].imexs;
- ch->u.getparam.driveo= ch_data[unit].driveo;
- ch->u.getparam.drives= ch_data[unit].drives;
- ch->u.getparam.rot= ch_data[unit].rot;
- ch->result=0;
- return 0;
- break;
- case CHPOSITION:
- return ch_position(unit,&ch->result,ch->u.position.chm,
- ch->u.position.to,
- flags);
- case CHMOVE:
- return ch_move(unit,&ch->result, ch->u.position.chm,
- ch->u.move.from, ch->u.move.to,
- flags);
- case CHGETELEM:
- return ch_getelem(unit,&ch->result, ch->u.get_elem_stat.type,
- ch->u.get_elem_stat.from, &ch->u.get_elem_stat.elem_data,
- flags);
- default:
- return EINVAL;
+ sc_link = ch_data[unit].sc_link;
+
+ switch (cmd) {
+ case CHIOOP:{
+ struct chop *ch = (struct chop *) arg;
+ SC_DEBUG(sc_link, SDEV_DB2,
+ ("[chtape_chop: %x]\n", ch->ch_op));
+
+ switch ((short) (ch->ch_op)) {
+ case CHGETPARAM:
+ ch->u.getparam.chmo = ch_data[unit].chmo;
+ ch->u.getparam.chms = ch_data[unit].chms;
+ ch->u.getparam.sloto = ch_data[unit].sloto;
+ ch->u.getparam.slots = ch_data[unit].slots;
+ ch->u.getparam.imexo = ch_data[unit].imexo;
+ ch->u.getparam.imexs = ch_data[unit].imexs;
+ ch->u.getparam.driveo = ch_data[unit].driveo;
+ ch->u.getparam.drives = ch_data[unit].drives;
+ ch->u.getparam.rot = ch_data[unit].rot;
+ ch->result = 0;
+ return 0;
+ break;
+ case CHPOSITION:
+ return ch_position(unit, &ch->result, ch->u.position.chm,
+ ch->u.position.to,
+ flags);
+ case CHMOVE:
+ return ch_move(unit, &ch->result, ch->u.position.chm,
+ ch->u.move.from, ch->u.move.to,
+ flags);
+ case CHGETELEM:
+ return ch_getelem(unit, &ch->result, ch->u.get_elem_stat.type,
+ ch->u.get_elem_stat.from, &ch->u.get_elem_stat.elem_data,
+ flags);
+ default:
+ return EINVAL;
+ }
}
-
- }
default:
- return EINVAL;
+ return scsi_do_ioctl(sc_link, cmd, arg, mode);
}
-
- return(ret?ESUCCESS:EIO);
+ return (ret ? ESUCCESS : EIO);
}
-ch_getelem(unit,stat,type,from,data,flags)
-int unit,from,flags;
-short *stat;
-char *data;
+errval
+ch_getelem(unit, stat, type, from, data, flags)
+ u_int32 unit, from, flags;
+ short *stat;
+ char *data;
{
struct scsi_read_element_status scsi_cmd;
- char elbuf[32];
- int ret;
+ char elbuf[32];
+ errval ret;
bzero(&scsi_cmd, sizeof(scsi_cmd));
scsi_cmd.op_code = READ_ELEMENT_STATUS;
scsi_cmd.byte2 = type;
- scsi_cmd.starting_element_addr[0]=(from>>8)&0xff;
- scsi_cmd.starting_element_addr[1]=from&0xff;
- scsi_cmd.number_of_elements[1]=1;
- scsi_cmd.allocation_length[2]=32;
-
- if ((ret=ch_scsi_cmd(unit,
- &scsi_cmd,
- sizeof(scsi_cmd),
- elbuf,
- 32,
- 100000,
- flags) !=ESUCCESS)) {
- *stat=ch_data[unit].lsterr;
- bcopy(elbuf+16,data,16);
- return ret;
- }
- bcopy(elbuf+16,data,16); /*Just a hack sh */
+ scsi_cmd.starting_element_addr[0] = (from >> 8) & 0xff;
+ scsi_cmd.starting_element_addr[1] = from & 0xff;
+ scsi_cmd.number_of_elements[1] = 1;
+ scsi_cmd.allocation_length[2] = 32;
+
+ if ((ret = scsi_scsi_cmd(ch_data[unit].sc_link,
+ (struct scsi_generic *) &scsi_cmd,
+ sizeof(scsi_cmd),
+ (u_char *) elbuf,
+ 32,
+ CHRETRIES,
+ 100000,
+ NULL,
+ SCSI_DATA_IN | flags) != ESUCCESS)) {
+ *stat = ch_data[unit].lsterr;
+ bcopy(elbuf + 16, data, 16);
+ return ret;
+ }
+ bcopy(elbuf + 16, data, 16); /*Just a hack sh */
return ret;
}
-ch_move(unit,stat,chm,from,to,flags)
-int unit,chm,from,to,flags;
-short *stat;
+errval
+ch_move(unit, stat, chm, from, to, flags)
+ u_int32 unit, chm, from, to, flags;
+ short *stat;
{
struct scsi_move_medium scsi_cmd;
- int ret;
+ errval ret;
bzero(&scsi_cmd, sizeof(scsi_cmd));
scsi_cmd.op_code = MOVE_MEDIUM;
- scsi_cmd.transport_element_address[0]=(chm>>8)&0xff;
- scsi_cmd.transport_element_address[1]=chm&0xff;
- scsi_cmd.source_address[0]=(from>>8)&0xff;
- scsi_cmd.source_address[1]=from&0xff;
- scsi_cmd.destination_address[0]=(to>>8)&0xff;
- scsi_cmd.destination_address[1]=to&0xff;
- scsi_cmd.invert=(chm&CH_INVERT)?1:0;
- if ((ret=ch_scsi_cmd(unit,
- &scsi_cmd,
- sizeof(scsi_cmd),
- NULL,
- 0,
- 100000,
- flags) !=ESUCCESS)) {
- *stat=ch_data[unit].lsterr;
- return ret;
- }
+ scsi_cmd.transport_element_address[0] = (chm >> 8) & 0xff;
+ scsi_cmd.transport_element_address[1] = chm & 0xff;
+ scsi_cmd.source_address[0] = (from >> 8) & 0xff;
+ scsi_cmd.source_address[1] = from & 0xff;
+ scsi_cmd.destination_address[0] = (to >> 8) & 0xff;
+ scsi_cmd.destination_address[1] = to & 0xff;
+ scsi_cmd.invert = (chm & CH_INVERT) ? 1 : 0;
+ if ((ret = scsi_scsi_cmd(ch_data[unit].sc_link,
+ (struct scsi_generic *) &scsi_cmd,
+ sizeof(scsi_cmd),
+ NULL,
+ 0,
+ CHRETRIES,
+ 100000,
+ NULL,
+ flags) != ESUCCESS)) {
+ *stat = ch_data[unit].lsterr;
+ return ret;
+ }
return ret;
}
-ch_position(unit,stat,chm,to,flags)
-int unit,chm,to,flags;
-short *stat;
+errval
+ch_position(unit, stat, chm, to, flags)
+ u_int32 unit, chm, to, flags;
+ short *stat;
{
struct scsi_position_to_element scsi_cmd;
- int ret;
+ errval ret;
bzero(&scsi_cmd, sizeof(scsi_cmd));
scsi_cmd.op_code = POSITION_TO_ELEMENT;
- scsi_cmd.transport_element_address[0]=(chm>>8)&0xff;
- scsi_cmd.transport_element_address[1]=chm&0xff;
- scsi_cmd.source_address[0]=(to>>8)&0xff;
- scsi_cmd.source_address[1]=to&0xff;
- scsi_cmd.invert=(chm&CH_INVERT)?1:0;
- if ((ret=ch_scsi_cmd(unit,
- &scsi_cmd,
- sizeof(scsi_cmd),
- NULL,
- 0,
- 100000,
- flags) !=ESUCCESS)) {
- *stat=ch_data[unit].lsterr;
- return ret;
- }
- return ret;
-}
-
-/*******************************************************\
-* Check with the device that it is ok, (via scsi driver)*
-\*******************************************************/
-ch_req_sense(unit, flags)
-int flags;
-{
- struct scsi_sense_data sense;
- struct scsi_sense scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = REQUEST_SENSE;
- scsi_cmd.length = sizeof(sense);
-
- if (ch_scsi_cmd(unit,
- &scsi_cmd,
- sizeof(struct scsi_sense),
- &sense,
- sizeof(sense),
- 100000,
- flags | SCSI_DATA_IN) != 0)
- {
- return(FALSE);
+ scsi_cmd.transport_element_address[0] = (chm >> 8) & 0xff;
+ scsi_cmd.transport_element_address[1] = chm & 0xff;
+ scsi_cmd.source_address[0] = (to >> 8) & 0xff;
+ scsi_cmd.source_address[1] = to & 0xff;
+ scsi_cmd.invert = (chm & CH_INVERT) ? 1 : 0;
+ if ((ret = scsi_scsi_cmd(ch_data[unit].sc_link,
+ (struct scsi_generic *) &scsi_cmd,
+ sizeof(scsi_cmd),
+ NULL,
+ 0,
+ CHRETRIES,
+ 100000,
+ NULL,
+ flags) != ESUCCESS)) {
+ *stat = ch_data[unit].lsterr;
+ return ret;
}
- else
- return(TRUE);
-}
-
-/*******************************************************\
-* Get scsi driver to send a "are you ready" command *
-\*******************************************************/
-ch_test_ready(unit,flags)
-int unit,flags;
-{
- struct scsi_test_unit_ready scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = TEST_UNIT_READY;
-
- if (ch_scsi_cmd(unit,
- &scsi_cmd,
- sizeof(struct scsi_test_unit_ready),
- 0,
- 0,
- 100000,
- flags) != 0) {
- return(FALSE);
- } else
- return(TRUE);
+ return ret;
}
-
#ifdef __STDC__
#define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
#else
#define b2tol(a) (((unsigned)(a/**/_1) << 8) + (unsigned)a/**/_0 )
#endif
-/*******************************************************\
-* Get the scsi driver to send a full inquiry to the *
-* device and use the results to fill out the global *
-* parameter structure. *
-\*******************************************************/
+/*
+ * Get the scsi driver to send a full inquiry to the
+ * device and use the results to fill out the global
+ * parameter structure.
+ */
+errval
ch_mode_sense(unit, flags)
-int unit,flags;
+ u_int32 unit, flags;
{
struct scsi_mode_sense scsi_cmd;
- u_char scsi_sense[128]; /* Can't use scsi_mode_sense_data because of */
- /* missing block descriptor */
+ u_char scsi_sense[128]; /* Can't use scsi_mode_sense_data because of
+ * missing block descriptor
+ */
u_char *b;
- int i,l;
-
- /*******************************************************\
- * First check if we have it all loaded *
- \*******************************************************/
- if (ch_info_valid[unit]==CH_KNOWN) return(TRUE);
- /*******************************************************\
- * First do a mode sense *
- \*******************************************************/
- ch_info_valid[unit] &= ~CH_KNOWN;
- for(l=1;l>=0;l--) {
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SENSE;
- scsi_cmd.byte2 = SMS_DBD;
- scsi_cmd.page = 0x3f; /* All Pages */
- scsi_cmd.length = sizeof(scsi_sense);
- /*******************************************************\
- * do the command, but we don't need the results *
- * just print them for our interest's sake *
- \*******************************************************/
- if (ch_scsi_cmd(unit,
- &scsi_cmd,
- sizeof(struct scsi_mode_sense),
- &scsi_sense,
- sizeof(scsi_sense),
- 5000,
- flags | SCSI_DATA_IN) == 0) {
- ch_info_valid[unit] = CH_KNOWN;
- break;
- }
- }
- if (ch_info_valid[unit]!=CH_KNOWN) {
- if(!(flags & SCSI_SILENT))
+ int32 i, l;
+ errval errcode;
+ struct scsi_link *sc_link = ch_data[unit].sc_link;
+
+ /*
+ * First check if we have it all loaded
+ */
+ if (sc_link->flags & SDEV_MEDIA_LOADED)
+ return 0;
+
+ /*
+ * First do a mode sense
+ */
+ /* sc_link->flags &= ~SDEV_MEDIA_LOADED; *//*XXX */
+ bzero(&scsi_cmd, sizeof(scsi_cmd));
+ scsi_cmd.op_code = MODE_SENSE;
+ scsi_cmd.byte2 = SMS_DBD;
+ scsi_cmd.page = 0x3f; /* All Pages */
+ scsi_cmd.length = sizeof(scsi_sense);
+
+ /*
+ * Read in the pages
+ */
+ if (errcode = scsi_scsi_cmd(sc_link,
+ (struct scsi_generic *) &scsi_cmd,
+ sizeof(struct scsi_mode_sense),
+ (u_char *) & scsi_sense,
+ sizeof (scsi_sense),
+ CHRETRIES,
+ 5000,
+ NULL,
+ flags | SCSI_DATA_IN) != 0) {
+ if (!(flags & SCSI_SILENT))
printf("ch%d: could not mode sense\n", unit);
- return(FALSE);
+ return (errcode);
}
- l=scsi_sense[0]-3;
- b=&scsi_sense[4];
- /*****************************\
- * To avoid alignment problems *
- \*****************************/
-/*FIX THIS FOR MSB */
+ sc_link->flags |= SDEV_MEDIA_LOADED;
+ l = scsi_sense[0] - 3;
+ b = &scsi_sense[4];
+
+ /*
+ * To avoid alignment problems
+ */
+/* XXX - FIX THIS FOR MSB */
#define p2copy(valp) (valp[1]+ (valp[0]<<8));valp+=2
#define p4copy(valp) (valp[3]+ (valp[2]<<8) + (valp[1]<<16) + (valp[0]<<24));valp+=4
#if 0
- printf("\nmode_sense %d\n",l);
- for(i=0;i<l+4;i++) {
- printf("%x%c",scsi_sense[i],i%8==7?'\n':':');
- }
- printf("\n");
+ printf("\nmode_sense %d\n", l);
+ for (i = 0; i < l + 4; i++) {
+ printf("%x%c", scsi_sense[i], i % 8 == 7 ? '\n' : ':');
+ } printf("\n");
#endif
- for(i=0;i<l;) {
- int pc=(*b++)&0x3f;
- int pl=*b++;
- u_char *bb=b;
- switch(pc) {
- case 0x1d:
- ch_data[unit].chmo =p2copy(bb);
- ch_data[unit].chms =p2copy(bb);
- ch_data[unit].sloto =p2copy(bb);
- ch_data[unit].slots =p2copy(bb);
- ch_data[unit].imexo =p2copy(bb);
- ch_data[unit].imexs =p2copy(bb);
- ch_data[unit].driveo =p2copy(bb);
- ch_data[unit].drives =p2copy(bb);
- break;
- case 0x1e:
- ch_data[unit].rot = (*b)&1;
- break;
- case 0x1f:
- ch_data[unit].stor = *b&0xf;
- bb+=2;
- ch_data[unit].stor =p4copy(bb);
- break;
- default:
- break;
- }
- b+=pl;
- i+=pl+2;
- }
- if (ch_debug)
- {
- printf("unit %d: cht(%d-%d)slot(%d-%d)imex(%d-%d)cts(%d-%d) %s rotate\n",
- unit,
- ch_data[unit].chmo,
- ch_data[unit].chms,
- ch_data[unit].sloto,
- ch_data[unit].slots,
- ch_data[unit].imexo,
- ch_data[unit].imexs,
- ch_data[unit].driveo,
- ch_data[unit].drives,
- ch_data[unit].rot?"can":"can't");
- }
- return(TRUE);
-}
-
-/*******************************************************\
-* ask the scsi driver to perform a command for us. *
-* Call it through the switch table, and tell it which *
-* sub-unit we want, and what target and lu we wish to *
-* talk to. Also tell it where to find the command *
-* how long int is. *
-* Also tell it where to read/write the data, and how *
-* long the data is supposed to be *
-\*******************************************************/
-int ch_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags)
-
-int unit,flags;
-struct scsi_generic *scsi_cmd;
-int cmdlen;
-int timeout;
-u_char *data_addr;
-int datalen;
-{
- struct scsi_xfer *xs;
- int retval;
- int s;
-
- if(ch_debug||(scsi_debug & PRINTROUTINES)) printf("\nch_scsi_cmd%d %x",
- unit,scsi_cmd->opcode);
- if(ch_data[unit].sc_sw) /* If we have a scsi driver */
- {
-
- xs = &(ch_scsi_xfer[unit]);
- if(!(flags & SCSI_NOMASK))
- s = splbio();
- ch_xfer_block_wait[unit]++; /* there is someone waiting */
- while (xs->flags & INUSE)
- {
- sleep(&ch_xfer_block_wait[unit],PRIBIO+1);
- }
- ch_xfer_block_wait[unit]--;
- xs->flags = INUSE;
- if(!(flags & SCSI_NOMASK))
- splx(s);
-
- /*******************************************************\
- * Fill out the scsi_xfer structure *
- \*******************************************************/
- xs->flags |= flags;
- xs->adapter = ch_data[unit].ctlr;
- xs->targ = ch_data[unit].targ;
- xs->lu = ch_data[unit].lu;
- xs->retries = CH_RETRIES;
- xs->timeout = timeout;
- xs->cmd = scsi_cmd;
- xs->cmdlen = cmdlen;
- xs->data = data_addr;
- xs->datalen = datalen;
- xs->resid = datalen;
- xs->when_done = (flags & SCSI_NOMASK)
- ?(int (*)())0
- :ch_done;
- xs->done_arg = unit;
- xs->done_arg2 = (int)xs;
-retry: xs->error = XS_NOERROR;
- xs->bp = 0;
- ch_data[unit].lsterr=0;
- retval = (*(ch_data[unit].sc_sw->scsi_cmd))(xs);
- switch(retval)
- {
- case SUCCESSFULLY_QUEUED:
- while(!(xs->flags & ITSDONE))
- sleep(xs,PRIBIO+1);
-
- case HAD_ERROR:
- case COMPLETE:
- switch(xs->error)
- {
- case XS_NOERROR:
- retval = ESUCCESS;
- break;
- case XS_SENSE:
- retval = (ch_interpret_sense(unit,xs));
- break;
- case XS_DRIVER_STUFFUP:
- retval = EIO;
- break;
- case XS_TIMEOUT:
- if(xs->retries-- )
- {
- xs->flags &= ~ITSDONE;
- goto retry;
- }
- retval = EIO;
- break;
- case XS_BUSY:
- if(xs->retries-- )
- {
- xs->flags &= ~ITSDONE;
- goto retry;
- }
- retval = EIO;
- break;
- default:
- retval = EIO;
- printf("ch%d: unknown error category from scsi driver\n"
- ,unit);
- break;
- }
+ for (i = 0; i < l;) {
+ u_int32 pc = (*b++) & 0x3f;
+ u_int32 pl = *b++;
+ u_char *bb = b;
+ switch (pc) {
+ case 0x1d:
+ ch_data[unit].chmo = p2copy(bb);
+ ch_data[unit].chms = p2copy(bb);
+ ch_data[unit].sloto = p2copy(bb);
+ ch_data[unit].slots = p2copy(bb);
+ ch_data[unit].imexo = p2copy(bb);
+ ch_data[unit].imexs = p2copy(bb);
+ ch_data[unit].driveo = p2copy(bb);
+ ch_data[unit].drives = p2copy(bb);
break;
- case TRY_AGAIN_LATER:
- if(xs->retries-- )
- {
- xs->flags &= ~ITSDONE;
- goto retry;
- }
- retval = EIO;
+ case 0x1e:
+ ch_data[unit].rot = (*b) & 1;
+ break;
+ case 0x1f:
+ ch_data[unit].stor = *b & 0xf;
+ bb += 2;
+ ch_data[unit].stor = p4copy(bb);
break;
default:
- retval = EIO;
- }
- xs->flags = 0; /* it's free! */
- chstart(unit);
- }
- else
- {
- printf("ch%d: not set up\n",unit);
- return(EINVAL);
- }
- return(retval);
-}
-/***************************************************************\
-* Look at the returned sense and act on the error and detirmine *
-* The unix error number to pass back... (0 = report no error) *
-\***************************************************************/
-
-int ch_interpret_sense(unit,xs)
-int unit;
-struct scsi_xfer *xs;
-{
- struct scsi_sense_data *sense;
- int key;
- int silent = xs->flags & SCSI_SILENT;
-
- /***************************************************************\
- * If errors are ok, report a success *
- \***************************************************************/
- if(xs->flags & SCSI_ERR_OK) return(ESUCCESS);
-
- /***************************************************************\
- * Get the sense fields and work out what CLASS *
- \***************************************************************/
- sense = &(xs->sense);
- switch(sense->error_code & SSD_ERRCODE)
- {
- /***************************************************************\
- * If it's class 7, use the extended stuff and interpret the key *
- \***************************************************************/
- case 0x70:
- {
- key=sense->ext.extended.flags & SSD_KEY;
- if(sense->ext.extended.flags & SSD_ILI)
- if(!silent)
- {
- printf("length error ");
- }
- if(sense->error_code & SSD_ERRCODE_VALID)
- xs->resid = ntohl(*((long *)sense->ext.extended.info));
- if(xs->bp)
- {
- xs->bp->b_flags |= B_ERROR;
- return(ESUCCESS);
- }
- if(sense->ext.extended.flags & SSD_EOM)
- if(!silent) printf("end of medium ");
- if(sense->ext.extended.flags & SSD_FILEMARK)
- if(!silent) printf("filemark ");
- if(ch_debug)
- {
- printf("code%x valid%x\n"
- ,sense->error_code & SSD_ERRCODE
- ,sense->error_code & SSD_ERRCODE_VALID);
- printf("seg%x key%x ili%x eom%x fmark%x\n"
- ,sense->ext.extended.segment
- ,sense->ext.extended.flags & SSD_KEY
- ,sense->ext.extended.flags & SSD_ILI
- ,sense->ext.extended.flags & SSD_EOM
- ,sense->ext.extended.flags & SSD_FILEMARK);
- printf("info: %x %x %x %x followed by %d extra bytes\n"
- ,sense->ext.extended.info[0]
- ,sense->ext.extended.info[1]
- ,sense->ext.extended.info[2]
- ,sense->ext.extended.info[3]
- ,sense->ext.extended.extra_len);
- printf("extra: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n"
- ,sense->ext.extended.extra_bytes[0]
- ,sense->ext.extended.extra_bytes[1]
- ,sense->ext.extended.extra_bytes[2]
- ,sense->ext.extended.extra_bytes[3]
- ,sense->ext.extended.extra_bytes[4]
- ,sense->ext.extended.extra_bytes[5]
- ,sense->ext.extended.extra_bytes[6]
- ,sense->ext.extended.extra_bytes[7]
- ,sense->ext.extended.extra_bytes[8]
- ,sense->ext.extended.extra_bytes[9]
- ,sense->ext.extended.extra_bytes[10]
- ,sense->ext.extended.extra_bytes[11]
- ,sense->ext.extended.extra_bytes[12]
- ,sense->ext.extended.extra_bytes[13]
- ,sense->ext.extended.extra_bytes[14]
- ,sense->ext.extended.extra_bytes[15]);
-
- }
- switch(key)
- {
- case 0x0:
- return(ESUCCESS);
- case 0x1:
- if(!silent)
- {
- printf("ch%d: soft error(corrected)", unit);
- if(sense->error_code & SSD_ERRCODE_VALID)
- {
- printf(" block no. %d (decimal)",
- (sense->ext.extended.info[0] <<24)|
- (sense->ext.extended.info[1] <<16)|
- (sense->ext.extended.info[2] <<8)|
- (sense->ext.extended.info[3] ));
- }
- printf("\n");
- }
- return(ESUCCESS);
- case 0x2:
- if(!silent) printf("ch%d: not ready\n", unit);
- ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
- sense->ext.extended.info[13] ;
- return(ENODEV);
- case 0x3:
- if(!silent)
- {
- printf("ch%d: medium error", unit);
- if(sense->error_code & SSD_ERRCODE_VALID)
- {
- printf(" block no. %d (decimal)",
- (sense->ext.extended.info[0] <<24)|
- (sense->ext.extended.info[1] <<16)|
- (sense->ext.extended.info[2] <<8)|
- (sense->ext.extended.info[3] ));
- }
- printf("\n");
- }
- return(EIO);
- case 0x4:
- if(!silent) printf("ch%d: non-media hardware failure\n",
- unit);
- ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
- sense->ext.extended.info[13] ;
- return(EIO);
- case 0x5:
- if(!silent) printf("ch%d: illegal request\n", unit);
- ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
- sense->ext.extended.info[13] ;
- return(EINVAL);
- case 0x6:
- if(!silent) printf("ch%d: Unit attention\n", unit);
- ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
- sense->ext.extended.info[13] ;
- ch_info_valid[unit] = FALSE;
- if (ch_data[unit].flags & CH_OPEN) /* TEMP!!!! */
- return(EIO);
- else
- return(ESUCCESS);
- case 0x7:
- if(!silent)
- {
- printf("ch%d: attempted protection violation"
- , unit);
- if(sense->error_code & SSD_ERRCODE_VALID)
- {
- printf(" block no. %d (decimal)\n",
- (sense->ext.extended.info[0] <<24)|
- (sense->ext.extended.info[1] <<16)|
- (sense->ext.extended.info[2] <<8)|
- (sense->ext.extended.info[3] ));
- }
- printf("\n");
- }
- return(EACCES);
- case 0x8:
- if(!silent)
- {
- printf("ch%d: block wrong state (worm)"
- , unit);
- if(sense->error_code & SSD_ERRCODE_VALID)
- {
- printf(" block no. %d (decimal)",
- (sense->ext.extended.info[0] <<24)|
- (sense->ext.extended.info[1] <<16)|
- (sense->ext.extended.info[2] <<8)|
- (sense->ext.extended.info[3] ));
- }
- printf("\n");
- }
- return(EIO);
- case 0x9:
- if(!silent) printf("ch%d: vendor unique\n", unit);
- return(EIO);
- case 0xa:
- if(!silent) printf("ch%d: copy aborted\n", unit);
- return(EIO);
- case 0xb:
- if(!silent) printf("ch%d: command aborted\n", unit);
- ch_data[unit].lsterr=(sense->ext.extended.info[12]<<8)|
- sense->ext.extended.info[13] ;
- return(EIO);
- case 0xc:
- if(!silent)
- {
- printf("ch%d: search returned", unit);
- if(sense->error_code & SSD_ERRCODE_VALID)
- {
- printf(" block no. %d (decimal)",
- (sense->ext.extended.info[0] <<24)|
- (sense->ext.extended.info[1] <<16)|
- (sense->ext.extended.info[2] <<8)|
- (sense->ext.extended.info[3] ));
- }
- printf("\n");
- }
- return(ESUCCESS);
- case 0xd:
- if(!silent) printf("ch%d: volume overflow\n", unit);
- return(ENOSPC);
- case 0xe:
- if(!silent)
- {
- printf("ch%d: verify miscompare", unit);
- if(sense->error_code & SSD_ERRCODE_VALID)
- {
- printf(" block no. %d (decimal)",
- (sense->ext.extended.info[0] <<24)|
- (sense->ext.extended.info[1] <<16)|
- (sense->ext.extended.info[2] <<8)|
- (sense->ext.extended.info[3] ));
- }
- printf("\n");
- }
- return(EIO);
- case 0xf:
- if(!silent) printf("ch%d: unknown error key\n", unit);
- return(EIO);
- }
- break;
- }
- /***************************************************************\
- * If it's NOT class 7, just report it. *
- \***************************************************************/
- default:
- {
- if(!silent)
- {
- printf("ch%d: error code %d",
- unit,
- sense->error_code & SSD_ERRCODE);
- if(sense->error_code & SSD_ERRCODE_VALID)
- {
- printf(" block no. %d (decimal)",
- (sense->ext.unextended.blockhi <<16),
- + (sense->ext.unextended.blockmed <<8),
- + (sense->ext.unextended.blocklow ));
- }
- printf("\n");
- }
+ break;
}
- return(EIO);
+ b += pl;
+ i += pl + 2;
}
+ SC_DEBUG(sc_link, SDEV_DB2,
+ (" cht(%d-%d)slot(%d-%d)imex(%d-%d)cts(%d-%d) %s rotate\n",
+ ch_data[unit].chmo, ch_data[unit].chms,
+ ch_data[unit].sloto, ch_data[unit].slots,
+ ch_data[unit].imexo, ch_data[unit].imexs,
+ ch_data[unit].driveo, ch_data[unit].drives,
+ ch_data[unit].rot ? "can" : "can't"));
+ return (0);
}
-
-
-
OpenPOWER on IntegriCloud