From c7d5f60d3a7e2e3c4da23b157c62504667344438 Mon Sep 17 00:00:00 2001 From: rgrimes Date: Sat, 12 Jun 1993 14:58:17 +0000 Subject: [PATCH] Initial import, 0.1 + pk 0.2.4-B1 --- sys/scsi/ch.c | 1015 +++++++++++++++++++++++++++++++++++++++ sys/scsi/scsi_changer.h | 118 +++++ sys/sys/chio.h | 127 +++++ 3 files changed, 1260 insertions(+) create mode 100644 sys/scsi/ch.c create mode 100644 sys/scsi/scsi_changer.h create mode 100644 sys/sys/chio.h diff --git a/sys/scsi/ch.c b/sys/scsi/ch.c new file mode 100644 index 000000000000..1e7469b66b88 --- /dev/null +++ b/sys/scsi/ch.c @@ -0,0 +1,1015 @@ +/* + */ +/* + * HISTORY + * + * + * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE + * -------------------- ----- ---------------------- + * CURRENT PATCH LEVEL: 1 00098 + * -------------------- ----- ---------------------- + * + * 16 Feb 93 Julian Elischer ADDED for SCSI system + * + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined(OSF) +#define SECSIZE 512 +#endif /* defined(OSF) */ + +#include +#include +#include + + +struct scsi_xfer ch_scsi_xfer[NCH]; +int ch_xfer_block_wait[NCH]; + + +#define PAGESIZ 4096 +#define STQSIZE 4 +#define CH_RETRIES 4 + + +#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; + +int chattach(); +int ch_done(); +struct ch_data +{ + 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]; + +#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 * +\***********************************************************************/ + +int chattach(ctlr,targ,lu,scsi_switch) +struct scsi_switch *scsi_switch; +{ + int unit,i,stat; + unsigned char *tbl; + + if(scsi_debug & PRINTROUTINES) printf("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",(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; + } + else + { + printf(" ch%d: scsi changer :- offline\n", unit); + stat=CH_OPEN; + } + ch_initialized[unit] = stat; + + return; + +} + + + +/*******************************************************\ +* open the device. * +\*******************************************************/ +chopen(dev) +{ + int errcode = 0; + int unit,mode; + + unit = UNIT(dev); + mode = MODE(dev); + + /*******************************************************\ + * Check the unit is legal * + \*******************************************************/ + if ( unit >= NCH ) + { + printf("ch %d > %d\n",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); + errcode = ENXIO; + goto bad; + } + + 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); + } + } + /*******************************************************\ + * 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; + } + if(ch_debug || (scsi_debug & TRACEOPENS)) + printf("ok\n"); + + if(!(ch_test_ready(unit,0))) + { + printf("ch%d not ready\n",unit); + return(EIO); + } + + ch_info_valid[unit] = TRUE; + + /*******************************************************\ + * Load the physical device parameters * + \*******************************************************/ + + ch_data[unit].flags = CH_OPEN; + return(errcode); +bad: + return(errcode); +} + +/*******************************************************\ +* close the device.. only called if we are the LAST * +* occurence of an open device * +\*******************************************************/ +chclose(dev) +{ + unsigned char unit,mode; + + unit = UNIT(dev); + mode = MODE(dev); + + if(scsi_debug & TRACEOPENS) + printf("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; + +} + + +/*******************************************************\ +* 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 * +\*******************************************************/ +chioctl(dev, cmd, arg, mode) +dev_t dev; +int cmd; +caddr_t arg; +{ + /* struct ch_cmd_buf *args;*/ + union scsi_cmd *scsi_cmd; + register i,j; + unsigned int opri; + int 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. */ + 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; + } + + } + default: + return EINVAL; + } + + return(ret?ESUCCESS:EIO); +} + +ch_getelem(unit,stat,type,from,data,flags) +int unit,from,flags; +short *stat; +char *data; +{ + struct scsi_read_element_status scsi_cmd; + char elbuf[32]; + int ret; + + bzero(&scsi_cmd, sizeof(scsi_cmd)); + scsi_cmd.op_code = READ_ELEMENT_STATUS; + scsi_cmd.element_type_code=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 */ + return ret; +} + +ch_move(unit,stat,chm,from,to,flags) +int unit,chm,from,to,flags; +short *stat; +{ + struct scsi_move_medium scsi_cmd; + int 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; + } + return ret; +} + +ch_position(unit,stat,chm,to,flags) +int unit,chm,to,flags; +short *stat; +{ + struct scsi_position_to_element scsi_cmd; + int 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); + } + 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); +} + + +#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. * +\*******************************************************/ +ch_mode_sense(unit, flags) +int 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 *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.dbd = l; + scsi_cmd.page_code = 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)) + printf("could not mode sense for unit %d\n", unit); + return(FALSE); + } + l=scsi_sense[0]-3; + b=&scsi_sense[4]; + /*****************************\ + * To avoid alignment problems * + \*****************************/ +/*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;iopcode); + 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("st%d: unknown error category from scsi driver\n" + ,unit); + break; + } + break; + case TRY_AGAIN_LATER: + if(xs->retries-- ) + { + xs->flags &= ~ITSDONE; + goto retry; + } + retval = EIO; + break; + default: + retval = EIO; + } + xs->flags = 0; /* it's free! */ + chstart(unit); + } + else + { + printf("chd: 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_class) + { + /***************************************************************\ + * If it's class 7, use the extended stuff and interpret the key * + \***************************************************************/ + case 7: + { + key=sense->ext.extended.sense_key; + if(sense->ext.extended.ili) + if(!silent) + { + printf("length error "); + } + if(sense->valid) + xs->resid = ntohl(*((long *)sense->ext.extended.info)); + if(xs->bp) + { + xs->bp->b_flags |= B_ERROR; + return(ESUCCESS); + } + if(sense->ext.extended.eom) + if(!silent) printf("end of medium "); + if(sense->ext.extended.filemark) + if(!silent) printf("filemark "); + if(ch_debug) + { + printf("code%x class%x valid%x\n" + ,sense->error_code + ,sense->error_class + ,sense->valid); + printf("seg%x key%x ili%x eom%x fmark%x\n" + ,sense->ext.extended.segment + ,sense->ext.extended.sense_key + ,sense->ext.extended.ili + ,sense->ext.extended.eom + ,sense->ext.extended.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("st%d: soft error(corrected) ", unit); + if(sense->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] )); + } + else + { + printf("\n"); + } + } + return(ESUCCESS); + case 0x2: + if(!silent) printf("st%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("st%d: medium error ", unit); + if(sense->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] )); + } + else + { + printf("\n"); + } + } + return(EIO); + case 0x4: + if(!silent) printf("st%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("st%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("st%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("st%d: attempted protection violation " + , unit); + if(sense->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] )); + } + else + { + printf("\n"); + } + } + return(EACCES); + case 0x8: + if(!silent) + { + printf("st%d: block wrong state (worm)\n " + , unit); + if(sense->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] )); + } + else + { + printf("\n"); + } + } + return(EIO); + case 0x9: + if(!silent) printf("st%d: vendor unique\n", + unit); + return(EIO); + case 0xa: + if(!silent) printf("st%d: copy aborted\n ", + unit); + return(EIO); + case 0xb: + if(!silent) printf("st%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("st%d: search returned\n ", unit); + if(sense->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] )); + } + else + { + printf("\n"); + } + } + return(ESUCCESS); + case 0xd: + if(!silent) printf("st%d: volume overflow\n ", + unit); + return(ENOSPC); + case 0xe: + if(!silent) + { + printf("st%d: verify miscompare\n ", unit); + if(sense->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] )); + } + else + { + printf("\n"); + } + } + return(EIO); + case 0xf: + if(!silent) printf("st%d: unknown error key\n ", + unit); + return(EIO); + } + break; + } + /***************************************************************\ + * If it's NOT class 7, just report it. * + \***************************************************************/ + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + { + if(!silent) printf("st%d: error class %d code %d\n", + unit, + sense->error_class, + sense->error_code); + if(sense->valid) + if(!silent) printf("block no. %d (decimal)\n", + (sense->ext.unextended.blockhi <<16), + + (sense->ext.unextended.blockmed <<8), + + (sense->ext.unextended.blocklow )); + } + return(EIO); + } +} + + + diff --git a/sys/scsi/scsi_changer.h b/sys/scsi/scsi_changer.h new file mode 100644 index 000000000000..63a5b1398a29 --- /dev/null +++ b/sys/scsi/scsi_changer.h @@ -0,0 +1,118 @@ +/* + * HISTORY + * + * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE + * -------------------- ----- ---------------------- + * CURRENT PATCH LEVEL: 1 00098 + * -------------------- ----- ---------------------- + * + * 16 Feb 93 Julian Elischer ADDED for SCSI system + * + */ + +/* + * SCSI changer interface description + */ + +/* + * Written by Stefan Grefen (grefen@goofy.zdv.uni-mainz.de soon grefen@convex.com) + * based on the SCSI System by written Julian Elischer (julian@tfs.com) + * for TRW Financial Systems. + * + * TRW Financial Systems, in accordance with their agreement with Carnegie + * Mellon University, makes this software available to CMU to distribute + * or use in any manner that they see fit as long as this message is kept with + * the software. For this reason TFS also grants any other persons or + * organisations permission to use or modify this software. + * + * TFS supplies this software to be publicly redistributed + * on the understanding that TFS is not responsible for the correct + * functioning of this software in any circumstances. + * + */ + +/* + * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + */ + +/* + * SCSI command format + */ +struct scsi_read_element_status +{ + u_char op_code; + u_char element_type_code:4; + u_char voltag:1; + u_char lun:3; + u_char starting_element_addr[2]; + u_char number_of_elements[2]; + u_char resv1; + u_char allocation_length[3]; + u_char resv2; + u_char link:1; + u_char flag:1; + u_char :6; +}; +#define RE_ALL_ELEMENTS 0 +#define RE_MEDIUM_TRANSPORT_ELEMENT 1 +#define RE_STORAGE_ELEMENT 2 +#define RE_IMPORT_EXPORT 3 +#define RE_DATA_TRANSFER_ELEMENT 4 + +struct scsi_move_medium +{ + u_char op_code; + u_char :5; + u_char lun:3; + u_char transport_element_address[2]; + u_char source_address[2]; + u_char destination_address[2]; + u_char rsvd[2]; + u_char invert:1; + u_char :7; + u_char link:1; + u_char flag:1; + u_char :6; +}; + +struct scsi_position_to_element +{ + u_char op_code; + u_char :5; + u_char lun:3; + u_char transport_element_address[2]; + u_char source_address[2]; + u_char rsvd[2]; + u_char invert:1; + u_char :7; + u_char link:1; + u_char flag:1; + u_char :6; +}; + +/* + * Opcodes + */ +#define POSITION_TO_ELEMENT 0x2b +#define MOVE_MEDIUM 0xa5 +#define READ_ELEMENT_STATUS 0xb8 + +struct scsi_element_status_data +{ + u_char first_element_reported[2]; + u_char number_of_elements_reported[2]; + u_char rsvd; + u_char byte_count_of_report[3]; +}; + +struct element_status_page +{ + u_char element_type_code; + u_char :5; + u_char avoltag:1; + u_char pvoltag:1; + u_char element_descriptor_length[2]; + u_char rsvd; + u_char byte_count_of_descriptor_data[3]; +}; + diff --git a/sys/sys/chio.h b/sys/sys/chio.h new file mode 100644 index 000000000000..532e6eed54dc --- /dev/null +++ b/sys/sys/chio.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1982, 1986 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)chio.h 7.6 (Berkeley) 2/5/91 + * + * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE + * -------------------- ----- ---------------------- + * CURRENT PATCH LEVEL: 1 00098 + * -------------------- ----- ---------------------- + * + * 16 Feb 93 Julian Elischer ADDED for SCSI system + */ + +/* This is a "convertet" mtio.h from 386BSD + Stefan Grefen grefen@goofy.zdv.uni-mainz.de + */ + +/* + * Structures and definitions for changer io control commands + */ +#ifndef _CHIO_H_ +#define _CHIO_H_ + +#define CH_INVERT 0x10000 +#define CH_ADDR_MASK 0xffff +struct chop { + short ch_op; /* operations defined below */ + short result; /* The result */ + union { + struct { + int chm; /* Transport element */ + int from; + int to; + } move; + struct { + int chm; /* Transport element */ + int to; + } position; + struct { + 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 */ + } getparam; + struct { + int type; +#define CH_CHM 1 +#define CH_STOR 2 +#define CH_IMEX 3 +#define CH_CTS 4 + int from; + struct { + u_char elema_1; + u_char elema_0; + u_char full:1; + u_char rsvd:1; + u_char except:1; + u_char :5; + u_char rsvd2; + union { + struct { + u_char add_sense_code; + u_char add_sense_code_qualifier; + } specs; + short add_sense; +/* WARINING LSB only */ +#define CH_CHOLDER 0x0290 /* Cartridge holder is missing */ +#define CH_STATUSQ 0x0390 /* Status is questionable */ +#define CH_CTS_CLOSED 0x0490 /* CTS door is closed */ + + } ch_add_sense; + u_char rsvd3[3]; + u_char :6; + u_char invert:1; + u_char svalid:1; + u_char source_1; + u_char source_0; + u_char rsvd4[4]; + } elem_data; + } get_elem_stat; + } u; +}; + +/* operations */ +#define CHMOVE 1 +#define CHPOSITION 2 +#define CHGETPARAM 3 +#define CHGETELEM 4 + + +/* Changer IO control command */ +#define CHIOOP _IOWR('c', 1, struct chop) /* do a mag tape op */ +#endif