153901Smckusick /* 253901Smckusick * Copyright (c) 1992 The Regents of the University of California. 353901Smckusick * All rights reserved. 453901Smckusick * 553901Smckusick * This code is derived from software contributed to Berkeley by 653901Smckusick * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. 753901Smckusick * 853901Smckusick * %sccs.include.redist.c% 953901Smckusick * 1053901Smckusick * from: $Hdr: scsi.c,v 4.300 91/06/27 20:42:51 root Rel41 $ SONY 1153901Smckusick * 12*58618Sutashiro * @(#)scsi.c 7.3 (Berkeley) 03/09/93 1353901Smckusick */ 1453901Smckusick 1553901Smckusick /* 1653901Smckusick * scsi.c ver 1.1 1753901Smckusick */ 1853901Smckusick 1957182Sutashiro #include <machine/param.h> 2053901Smckusick 2157182Sutashiro #include <sys/param.h> 2257182Sutashiro #include <sys/buf.h> 2357182Sutashiro #include <sys/proc.h> 2457182Sutashiro #include <sys/user.h> 2553901Smckusick 2657182Sutashiro # include <machine/cpu.h> 2753901Smckusick 2857182Sutashiro #include <news3400/hbdev/hbvar.h> 2957182Sutashiro #include <news3400/hbdev/scsic.h> 3057182Sutashiro #include <news3400/hbdev/screg_1185.h> 3153901Smckusick 3257182Sutashiro #include <news3400/iodev/scsireg.h> 3357182Sutashiro #include <news3400/iodev/ioptohb.h> 3453901Smckusick 3553901Smckusick #define DEBUG_LOSSBSY_HUNG 3653901Smckusick 3753901Smckusick #ifdef DEBUG_LOSSBSY_HUNG 3853901Smckusick # define PROBE_MAXRETRY 100 3953901Smckusick #endif 4053901Smckusick 4153901Smckusick #ifndef NO_SCSI_DISCONNECT 4253901Smckusick int Scsi_Disconnect = IDT_DISCON; 4353901Smckusick #else 4453901Smckusick int Scsi_Disconnect = 0; 4553901Smckusick #endif 4653901Smckusick 4753901Smckusick # define MAXCTLR 8 4853901Smckusick struct sc_data sc_data[MAXCTLR]; 4953901Smckusick struct scintsw scintsw[MAXCTLR]; 5053901Smckusick 5153901Smckusick #ifdef RSENSE_MSG_DISP 5253901Smckusick int rsense_msg_disp = 1; /* RSENSE-message display flag */ 5353901Smckusick #else 5453901Smckusick int rsense_msg_disp = 0; /* RSENSE-message display flag */ 5553901Smckusick #endif 5653901Smckusick 5753901Smckusick int mo_disp_format = 0; /* MO format mode display flag */ 5853901Smckusick 5953901Smckusick struct msg_list { 6053901Smckusick int ml_code; /* message code */ 6153901Smckusick int ml_msglvl; /* message level */ 6253901Smckusick char *ml_msgstr; /* message string */ 6353901Smckusick }; 6453901Smckusick 6553901Smckusick #ifdef NO_SHRINK_RSENSE_MSG 66*58618Sutashiro # define MSG(m) m 67*58618Sutashiro #else 68*58618Sutashiro # define MSG(m) NULL 69*58618Sutashiro #endif 70*58618Sutashiro 7153901Smckusick struct msg_list skeylist[] = { 72*58618Sutashiro { 0x00, 1, MSG("No Sense") }, 73*58618Sutashiro { 0x01, 0, MSG("Recoverable Error") }, 74*58618Sutashiro { 0x02, 0, MSG("Not Ready") }, 75*58618Sutashiro { 0x03, 0, MSG("Medium Error") }, 76*58618Sutashiro { 0x04, 0, MSG("Hardware Error") }, 77*58618Sutashiro { 0x05, 0, MSG("Illegal Request") }, 78*58618Sutashiro { 0x06, 1, MSG("Unit Attention") }, 79*58618Sutashiro { 0x07, 1, MSG("Data protect") }, 80*58618Sutashiro { 0x08, 0, MSG("Blank Check") }, 81*58618Sutashiro { 0x09, 0, MSG("Vendor Unique") }, 82*58618Sutashiro { 0x0a, 0, MSG("Copy/Compare Aborted") }, 83*58618Sutashiro { 0x0b, 0, MSG("Aborted Command") }, 84*58618Sutashiro { 0x0c, 0, MSG("Equal") }, 85*58618Sutashiro { 0x0d, 0, MSG("Volume Overflow") }, 86*58618Sutashiro { 0x0e, 0, MSG("Miscompare") }, 8753901Smckusick { -1, 0, (caddr_t)0 } 8853901Smckusick }; 8953901Smckusick 9053901Smckusick struct msg_list ecodelist[] = { 91*58618Sutashiro { 0x00, 9, MSG("No Additional Sense Information") }, 92*58618Sutashiro /*HD*/ { 0x01, 1, MSG("No Index/Address Mark Found signal") }, 93*58618Sutashiro { 0x02, 0, MSG("No Seek Complete") }, 94*58618Sutashiro { 0x03, 0, MSG("Write Fault") }, 95*58618Sutashiro { 0x04, 9, MSG("Drive Not Ready") }, 96*58618Sutashiro { 0x05, 0, MSG("Drive Not Selected") }, 97*58618Sutashiro /*HD*/ { 0x06, 0, MSG("No Track Zero") }, 98*58618Sutashiro { 0x07, 0, MSG("Multiple Drives Selected") }, 99*58618Sutashiro { 0x08, 0, MSG("Logical Unit Communication Failure") }, 100*58618Sutashiro { 0x09, 2, MSG("Track Following Error") }, 101*58618Sutashiro /*MO*/ { 0x0a, 1, MSG("No Disk") }, 102*58618Sutashiro /*MO*/ { 0x0b, 1, MSG("Load/Unload Failure") }, 103*58618Sutashiro /*MO*/ { 0x0c, 1, MSG("Spindle Failure") }, 104*58618Sutashiro /*MO*/ { 0x0d, 1, MSG("Focus Failure") }, 105*58618Sutashiro /*MO*/ { 0x0e, 1, MSG("Tracking Failure") }, 106*58618Sutashiro /*MO*/ { 0x0f, 0, MSG("Drive Initialization Failure") }, 107*58618Sutashiro { 0x10, 1, MSG("ID CRC or ECC error") }, 108*58618Sutashiro { 0x11, 0, MSG("Unrecoverd Read error") }, 109*58618Sutashiro /*HD*/ { 0x12, 0, MSG("No Address Mark (byte sync byte) found in ID field") }, 110*58618Sutashiro /*HD*/ { 0x13, 0, MSG("No Address Mark (byte sync byte) found in Data field") }, 111*58618Sutashiro /*HD*/ { 0x14, 0, MSG("No record found") }, 112*58618Sutashiro { 0x15, 1, MSG("Seek Positioning Error") }, 11353901Smckusick 114*58618Sutashiro /*HD*/ { 0x17, 0, MSG("Recovered Read data with Read retries") }, 115*58618Sutashiro { 0x18, 0, MSG("Recovered Read data with ECC procedure") }, 116*58618Sutashiro /*HD*/ { 0x19, 0, MSG("Defect List error") }, 117*58618Sutashiro /*HD*/ { 0x1a, 0, MSG("Parameter overrun") }, 118*58618Sutashiro /*HD*/ { 0x1b, 0, MSG("Synchronous transfer error") }, 119*58618Sutashiro /*HD*/ { 0x1c, 0, MSG("Primary Defect List not found") }, 120*58618Sutashiro /*HD*/ { 0x1d, 0, MSG("Compare error") }, 12153901Smckusick 122*58618Sutashiro { 0x20, 0, MSG("Invalid Command Operation Code") }, 123*58618Sutashiro { 0x21, 0, MSG("Illegal Logical Block Address") }, 124*58618Sutashiro /*HD*/ { 0x22, 0, MSG("Illegal function for device type") }, 125*58618Sutashiro /*MO*/ { 0x23, 0, MSG("Illegal function for Medium Type") }, 126*58618Sutashiro { 0x24, 0, MSG("Illegal Field in CDB") }, 127*58618Sutashiro { 0x25, 0, MSG("Invalid LUN") }, 128*58618Sutashiro { 0x26, 0, MSG("Invalid field in Parameter List") }, 129*58618Sutashiro { 0x27, 0, MSG("Write Protected") }, 130*58618Sutashiro { 0x28, 1, MSG("Medium Changed") }, 131*58618Sutashiro { 0x29, 1, MSG("Power On or Reset or Bus Device Reset Occured") }, 132*58618Sutashiro { 0x2a, 1, MSG("Mode Select Parameters Changed") }, 133*58618Sutashiro /*HD*/ { 0x2b, 0, MSG("Host cannot Disconnect") }, 13453901Smckusick 135*58618Sutashiro { 0x31, 0, MSG("Medium Format Corrupted") }, 136*58618Sutashiro { 0x32, 0, MSG("No Defect Spare Location Available") }, 13753901Smckusick 138*58618Sutashiro /*MO*/ { 0x38, 1, MSG("Recovered with Automatic Reallocation") }, 139*58618Sutashiro /*MO*/ { 0x39, 0, MSG("Automatic Reallocation Failure") }, 140*58618Sutashiro /*MO*/ { 0x3a, 1, MSG("Defect List Update Failure") }, 14153901Smckusick 142*58618Sutashiro /*MO*/ { 0x3d, 0, MSG("Defect List Not Available") }, 14353901Smckusick 144*58618Sutashiro /*HD*/ { 0x40, 0, MSG("RAM failure") }, 145*58618Sutashiro /*HD*/ { 0x41, 0, MSG("Data Path diagnostic failure") }, 146*58618Sutashiro { 0x42, 0, MSG("Power On Diagnostic Failure") }, 147*58618Sutashiro { 0x43, 0, MSG("Message Reject Error") }, 148*58618Sutashiro { 0x44, 9, MSG("Internal Controller Error") }, 149*58618Sutashiro /*HD*/ { 0x45, 0, MSG("Selection/Reselection failure") }, 15053901Smckusick 151*58618Sutashiro { 0x47, 0, MSG("SCSI Interface Parity Error") }, 152*58618Sutashiro { 0x48, 0, MSG("Initiator Detected Error") }, 153*58618Sutashiro { 0x49, 0, MSG("Inappropriate/Illegal Message") }, 15453901Smckusick 155*58618Sutashiro { 0x64, 1, MSG("Illegal mode for this track") }, 15653901Smckusick 15753901Smckusick { -1, 0, (caddr_t)0 } 15853901Smckusick }; 159*58618Sutashiro #undef MSG 16053901Smckusick 16153901Smckusick /* 16253901Smckusick * Init a scsi bus. 16353901Smckusick */ 16453901Smckusick scop_init(scn) 16553901Smckusick int scn; 16653901Smckusick { 16753901Smckusick static struct scsi sc; 16853901Smckusick int chan; 16953901Smckusick 17053901Smckusick for (chan = 0; chan < MAXCTLR; chan++) { 17153901Smckusick bzero((caddr_t)&sc, sizeof(struct scsi)); 17253901Smckusick sc.sc_cdb.un_reserved[0] = SCOP_RESET; 17353901Smckusick sc.sc_cdb.un_reserved[1] = SCOP_RESET; 17453901Smckusick 17553901Smckusick if (!sc_busy(chan)) { 17653901Smckusick sc_go(chan, (struct scsi *)&sc, SCSI_INTDIS); 17753901Smckusick 17853901Smckusick chan = (chan / 8 + 1) * 8; 17953901Smckusick } 18053901Smckusick } 18153901Smckusick } 18253901Smckusick 18353901Smckusick /************************************** 18453901Smckusick The multiple scsi bus is NOT suported by following routines. 18553901Smckusick How about use inter like dev_t ( uper is scsi#, lower is inter ) 18653901Smckusick or hb_ctlr. 18753901Smckusick probe() ga futatuarukara unit# ----- udauda. 18853901Smckusick **************************************/ 18953901Smckusick 19053901Smckusick /* 19153901Smckusick * scprobe. probe routine for mass storage controller. 19253901Smckusick */ 19353901Smckusick scprobe(im, ctlrintr, sc) 19453901Smckusick struct iop/**/_ctlr *im; 19553901Smckusick int (*ctlrintr)(); 19653901Smckusick register struct scsi *sc; 19753901Smckusick { 19853901Smckusick register struct scintsw *sci; 19953901Smckusick int s; 20053901Smckusick #ifdef DEBUG_LOSSBSY_HUNG 20153901Smckusick int retry = 0; 20253901Smckusick #endif DEBUG_LOSSBSY_HUNG 20353901Smckusick 20453901Smckusick sci = &scintsw[im->im_intr]; 20553901Smckusick if (sci->sci_inthandler) 20653901Smckusick return (0); 20753901Smckusick 20853901Smckusick #ifdef DEBUG_LOSSBSY_HUNG 20953901Smckusick scprobe_loop: 21053901Smckusick /* s = splsc(); */ 21153901Smckusick scop_inquiry(im->im_intr, sc, 0, SCSI_INTDIS, 4, (caddr_t)0); 21253901Smckusick /* splx(s); */ 21353901Smckusick 21453901Smckusick if (sc->sc_istatus != INST_EP) { 21553901Smckusick if ((sc->sc_tstatus == TGST_BUSY) && (retry++ < PROBE_MAXRETRY)) { 21653901Smckusick goto scprobe_loop; 21753901Smckusick } 21853901Smckusick return (0); 21953901Smckusick } 22053901Smckusick 22153901Smckusick #else /* DEBUG_LOSSBSY_HUNG */ 22253901Smckusick 22353901Smckusick /* s = splsc(); */ 22453901Smckusick scop_inquiry(im->im_intr, sc, 0, SCSI_INTDIS, 4, (caddr_t)0); 22553901Smckusick /* splx(s); */ 22653901Smckusick 22753901Smckusick if (sc->sc_istatus != INST_EP) 22853901Smckusick return (0); 22953901Smckusick 23053901Smckusick #endif /* DEBUG_LOSSBSY_HUNG */ 23153901Smckusick 23253901Smckusick sci->sci_inthandler = ctlrintr; 23353901Smckusick sci->sci_ctlr = im->im_ctlr; 23453901Smckusick return (1); 23553901Smckusick } 23653901Smckusick 23753901Smckusick /* 23853901Smckusick * ssprobe. probe routine for non-mass storage peripherals. 23953901Smckusick */ 24053901Smckusick ssprobe(ii, ctlrintr, sc) 24153901Smckusick struct iop/**/_device *ii; 24253901Smckusick int (*ctlrintr)(); 24353901Smckusick register struct scsi *sc; 24453901Smckusick { 24553901Smckusick register struct scintsw *sci; 24653901Smckusick int s; 24753901Smckusick 24853901Smckusick sci = &scintsw[ii->ii_intr]; 24953901Smckusick if (sci->sci_inthandler) 25053901Smckusick return (0); 25153901Smckusick 25253901Smckusick /* s = splsc(); */ 25353901Smckusick scop_inquiry(ii->ii_intr, sc, 0, SCSI_INTDIS, 4, (caddr_t)0); 25453901Smckusick /* splx(s); */ 25553901Smckusick 25653901Smckusick if (sc->sc_istatus != INST_EP) 25753901Smckusick return (0); 25853901Smckusick 25953901Smckusick sci->sci_inthandler = ctlrintr; 26053901Smckusick sci->sci_ctlr = ii->ii_unit; 26153901Smckusick return (1); 26253901Smckusick } 26353901Smckusick 26453901Smckusick /* 26553901Smckusick * SCOP_TST request 26653901Smckusick */ 26753901Smckusick scop_tst(intr, sc, slave, ie) 26853901Smckusick register int intr; 26953901Smckusick register struct scsi *sc; 27053901Smckusick register int slave; 27153901Smckusick register int ie; 27253901Smckusick { 27353901Smckusick scinit(sc, slave, DEV_BSIZE); 27453901Smckusick 27553901Smckusick /* sc_cdb */ 27653901Smckusick sc->sc_opcode = SCOP_TST; 27753901Smckusick 27853901Smckusick sc_go(intr, (struct scsi *)sc, ie); 27953901Smckusick } 28053901Smckusick 28153901Smckusick /* 28253901Smckusick * SCOP_REZERO request 28353901Smckusick */ 28453901Smckusick scop_rezero(intr, sc, slave, ie) 28553901Smckusick register int intr; 28653901Smckusick register struct scsi *sc; 28753901Smckusick register int slave; 28853901Smckusick register int ie; 28953901Smckusick { 29053901Smckusick scinit(sc, slave, DEV_BSIZE); 29153901Smckusick 29253901Smckusick /* sc_cdb */ 29353901Smckusick sc->sc_opcode = SCOP_REZERO; 29453901Smckusick 29553901Smckusick sc_go(intr, (struct scsi *)sc, ie); 29653901Smckusick } 29753901Smckusick 29853901Smckusick /* 29953901Smckusick * SCOP_REWIND request 30053901Smckusick */ 30153901Smckusick scop_rewind(intr, sc, slave, ie, imme) 30253901Smckusick register int intr; 30353901Smckusick register struct scsi *sc; 30453901Smckusick register int slave; 30553901Smckusick register int ie, imme; 30653901Smckusick { 30753901Smckusick scinit(sc, slave, DEV_BSIZE); 30853901Smckusick 30953901Smckusick /* sc_cdb */ 31053901Smckusick sc->sc_opcode = SCOP_REZERO; 31153901Smckusick sc->sc_tucode = imme; 31253901Smckusick 31353901Smckusick sc_go(intr, (struct scsi *)sc, ie); 31453901Smckusick } 31553901Smckusick 31653901Smckusick /* 31753901Smckusick * SCOP_RSENSE request 31853901Smckusick */ 31953901Smckusick scop_rsense(intr, sc, slave, ie, count, param) 32053901Smckusick register int intr; 32153901Smckusick register struct scsi *sc; 32253901Smckusick register int slave; 32353901Smckusick register int ie; 32453901Smckusick register int count; 32553901Smckusick register caddr_t param; 32653901Smckusick { 32753901Smckusick scinit(sc, slave, DEV_BSIZE); 32853901Smckusick 32953901Smckusick sc->sc_cpoint = (u_char *)param; 33053901Smckusick sc->sc_ctrnscnt = count; 33153901Smckusick 33253901Smckusick /* sc_cdb */ 33353901Smckusick sc->sc_opcode = SCOP_RSENSE; 33453901Smckusick sc->sc_count = count; 33553901Smckusick 33653901Smckusick sc_go(intr, (struct scsi *)sc, ie); 33753901Smckusick } 33853901Smckusick 33953901Smckusick /* 34053901Smckusick * SCOP_RASBLK request 34153901Smckusick */ 34253901Smckusick scop_rasblk(intr, sc, slave, ie, lad) 34353901Smckusick register int intr; 34453901Smckusick register struct scsi *sc; 34553901Smckusick register int slave; 34653901Smckusick register int ie; 34753901Smckusick register int lad; 34853901Smckusick { 34953901Smckusick struct sc_rab *sca = (struct sc_rab *)sc->sc_param; 35053901Smckusick 35153901Smckusick scinit(sc, slave, DEV_BSIZE); 35253901Smckusick 35353901Smckusick sca->sca_dllen = 4; 35453901Smckusick sca->sca_dlad[0] = lad; 35553901Smckusick sc->sc_cpoint = (u_char *)sca; 35653901Smckusick 35753901Smckusick sc->sc_ctrnscnt = 8; 35853901Smckusick 35953901Smckusick /* sc_cdb */ 36053901Smckusick sc->sc_opcode = SCOP_RASBLK; 36153901Smckusick 36253901Smckusick sc_go(intr, (struct scsi *)sc, ie); 36353901Smckusick } 36453901Smckusick 36553901Smckusick /* 36653901Smckusick * SCOP_MERASE request 36753901Smckusick */ 36853901Smckusick scop_merase(intr, sc, slave, ie, count) 36953901Smckusick register int intr; 37053901Smckusick register struct scsi *sc; 37153901Smckusick register int slave; 37253901Smckusick register int ie; 37353901Smckusick register int count; 37453901Smckusick { 37553901Smckusick scinit(sc, slave, DEV_BSIZE); 37653901Smckusick 37753901Smckusick /* sc_cdb */ 37853901Smckusick sc->sc_opcode = SCOP_MERASE; 37953901Smckusick sc->sc_mtcount3 = count; 38053901Smckusick 38153901Smckusick sc_go(intr, (struct scsi *)sc, ie); 38253901Smckusick } 38353901Smckusick 38453901Smckusick /* 38553901Smckusick * SCOP_WFMARK request 38653901Smckusick */ 38753901Smckusick scop_wfmark(intr, sc, slave, ie, count) 38853901Smckusick register int intr; 38953901Smckusick register struct scsi *sc; 39053901Smckusick register int slave; 39153901Smckusick register int ie; 39253901Smckusick register int count; 39353901Smckusick { 39453901Smckusick scinit(sc, slave, DEV_BSIZE); 39553901Smckusick 39653901Smckusick /* sc_cdb */ 39753901Smckusick sc->sc_opcode = SCOP_WFMARK; 39853901Smckusick count &= 0xffffff; 39953901Smckusick sc->sc_tucount3 = count & 0xff; 40053901Smckusick count >>= 8; 40153901Smckusick sc->sc_tucount2 = count & 0xff; 40253901Smckusick count >>= 8; 40353901Smckusick sc->sc_tucount1 = count & 0xff; 40453901Smckusick 40553901Smckusick sc_go(intr, (struct scsi *)sc, ie); 40653901Smckusick } 40753901Smckusick 40853901Smckusick /* 40953901Smckusick * SCOP_SPACE request 41053901Smckusick */ 41153901Smckusick scop_space(intr, sc, slave, ie, count, code) 41253901Smckusick register int intr; 41353901Smckusick register struct scsi *sc; 41453901Smckusick register int slave; 41553901Smckusick register int ie; 41653901Smckusick register int count; 41753901Smckusick register int code; 41853901Smckusick { 41953901Smckusick scinit(sc, slave, DEV_BSIZE); 42053901Smckusick 42153901Smckusick /* sc_cdb */ 42253901Smckusick sc->sc_opcode = SCOP_SPACE; 42353901Smckusick sc->sc_tucode = code; 42453901Smckusick count &= 0xffffff; 42553901Smckusick sc->sc_tucount3 = count & 0xff; 42653901Smckusick count >>= 8; 42753901Smckusick sc->sc_tucount2 = count & 0xff; 42853901Smckusick count >>= 8; 42953901Smckusick sc->sc_tucount1 = count & 0xff; 43053901Smckusick 43153901Smckusick sc_go(intr, (struct scsi *)sc, ie); 43253901Smckusick } 43353901Smckusick 43453901Smckusick /* 43553901Smckusick * SCOP_INQUIRY request 43653901Smckusick */ 43753901Smckusick scop_inquiry(intr, sc, slave, ie, count, param) 43853901Smckusick register int intr; 43953901Smckusick register struct scsi *sc; 44053901Smckusick register int slave; 44153901Smckusick register int ie; 44253901Smckusick register int count; 44353901Smckusick register caddr_t param; 44453901Smckusick { 44553901Smckusick scinit(sc, slave, DEV_BSIZE); 44653901Smckusick 44753901Smckusick sc->sc_cpoint = (u_char *)param; 44853901Smckusick sc->sc_ctrnscnt = count; 44953901Smckusick 45053901Smckusick /* sc_cdb */ 45153901Smckusick sc->sc_opcode = SCOP_INQUIRY; 45253901Smckusick sc->sc_count = count; 45353901Smckusick 45453901Smckusick sc_go(intr, (struct scsi *)sc, ie); 45553901Smckusick } 45653901Smckusick 45753901Smckusick /* 45853901Smckusick * SCOP_STST request 45953901Smckusick */ 46053901Smckusick scop_stst(intr, sc, slave, ie, sw) 46153901Smckusick register int intr; 46253901Smckusick register struct scsi *sc; 46353901Smckusick register int slave; 46453901Smckusick register int ie; 46553901Smckusick register int sw; 46653901Smckusick { 46753901Smckusick scinit(sc, slave, DEV_BSIZE); 46853901Smckusick 46953901Smckusick /* sc_cdb */ 47053901Smckusick sc->sc_opcode = SCOP_STST; 47153901Smckusick sc->sc_switch = sw; 47253901Smckusick 47353901Smckusick sc_go(intr, (struct scsi *)sc, ie); 47453901Smckusick } 47553901Smckusick 47653901Smckusick /* 47753901Smckusick * SCOP_RCAP request 47853901Smckusick */ 47953901Smckusick scop_rcap(intr, sc, slave, ie, count, param) 48053901Smckusick register int intr; 48153901Smckusick register struct scsi *sc; 48253901Smckusick register int slave; 48353901Smckusick register int ie; 48453901Smckusick register int count; 48553901Smckusick register caddr_t param; 48653901Smckusick { 48753901Smckusick scinit(sc, slave, DEV_BSIZE); 48853901Smckusick 48953901Smckusick sc->sc_cpoint = (u_char *)param; 49053901Smckusick sc->sc_ctrnscnt = count; 49153901Smckusick 49253901Smckusick /* sc_cdb */ 49353901Smckusick sc->sc_opcode = SCOP_RCAP; 49453901Smckusick sc->sc_pmi = OFF; 49553901Smckusick 49653901Smckusick sc_go(intr, (struct scsi *)sc, ie); 49753901Smckusick } 49853901Smckusick 49953901Smckusick /* 50053901Smckusick * SCOP_BSSRCH request 50153901Smckusick */ 50253901Smckusick scop_bssrch(intr, sc, slave, ie, count, param) 50353901Smckusick register int intr; 50453901Smckusick register struct scsi *sc; 50553901Smckusick register int slave; 50653901Smckusick register int ie; 50753901Smckusick register int count; 50853901Smckusick register caddr_t param; 50953901Smckusick { 51053901Smckusick scinit(sc, slave, DEV_BSIZE); 51153901Smckusick 51253901Smckusick sc->sc_cpoint = (u_char *)param; 51353901Smckusick sc->sc_ctrnscnt = count; 51453901Smckusick 51553901Smckusick /* sc_cdb */ 51653901Smckusick sc->sc_opcode = SCOP_BSSRCH; 51753901Smckusick sc->sc_ladhi = *(short *)param; 51853901Smckusick sc->sc_ladlo = *(short *)(param + 2); 51953901Smckusick 52053901Smckusick sc_go(intr, (struct scsi *)sc, ie); 52153901Smckusick } 52253901Smckusick 52353901Smckusick /* 52453901Smckusick * SCOP_WSSRCH request 52553901Smckusick */ 52653901Smckusick scop_wssrch(intr, sc, slave, ie, count, param) 52753901Smckusick register int intr; 52853901Smckusick register struct scsi *sc; 52953901Smckusick register int slave; 53053901Smckusick register int ie; 53153901Smckusick register int count; 53253901Smckusick register caddr_t param; 53353901Smckusick { 53453901Smckusick scinit(sc, slave, DEV_BSIZE); 53553901Smckusick 53653901Smckusick sc->sc_cpoint = (u_char *)param; 53753901Smckusick sc->sc_ctrnscnt = count; 53853901Smckusick 53953901Smckusick /* sc_cdb */ 54053901Smckusick sc->sc_opcode = SCOP_WSSRCH; 54153901Smckusick sc->sc_ladhi = *(short *)param; 54253901Smckusick sc->sc_ladlo = *(short *)(param + 2); 54353901Smckusick 54453901Smckusick sc_go(intr, (struct scsi *)sc, ie); 54553901Smckusick } 54653901Smckusick 54753901Smckusick /* 54853901Smckusick * 54953901Smckusick * SCOP_EESENSE request 55053901Smckusick * Enable/Disable Eject Request Sense 55153901Smckusick * Write Once only supported. 55253901Smckusick * 55353901Smckusick */ 55453901Smckusick scop_eesense(intr, sc, slave, ie, sw) 55553901Smckusick register int intr; 55653901Smckusick register struct scsi *sc; 55753901Smckusick register int slave; 55853901Smckusick register int ie; 55953901Smckusick register int sw; 56053901Smckusick { 56153901Smckusick scinit(sc, slave, DEV_BSIZE); 56253901Smckusick 56353901Smckusick /* sc_cdb */ 56453901Smckusick sc->sc_opcode = SCOP_EESENSE; 56553901Smckusick sc->sc_switch = sw; 56653901Smckusick 56753901Smckusick sc_go(intr, (struct scsi *)sc, ie); 56853901Smckusick } 56953901Smckusick 57053901Smckusick /* 57153901Smckusick * SCOP_EJECT 57253901Smckusick */ 57353901Smckusick scop_eject(intr, sc, slave, ie) 57453901Smckusick register int intr; 57553901Smckusick register struct scsi *sc; 57653901Smckusick register int slave; 57753901Smckusick register int ie; 57853901Smckusick { 57953901Smckusick scinit(sc, slave, DEV_BSIZE); 58053901Smckusick 58153901Smckusick /* sc_cdb */ 58253901Smckusick sc->sc_opcode = SCOP_EJECT; 58353901Smckusick 58453901Smckusick sc_go(intr, (struct scsi *)sc, ie); 58553901Smckusick } 58653901Smckusick 58753901Smckusick /* 58853901Smckusick * SCOP_RBLIM request 58953901Smckusick */ 59053901Smckusick scop_rblim(intr, sc, slave, ie, count, param) 59153901Smckusick register int intr; 59253901Smckusick register struct scsi *sc; 59353901Smckusick register int slave; 59453901Smckusick register int ie; 59553901Smckusick register int count; 59653901Smckusick register caddr_t param; 59753901Smckusick { 59853901Smckusick scinit(sc, slave, DEV_BSIZE); 59953901Smckusick 60053901Smckusick sc->sc_cpoint = (u_char *)param; 60153901Smckusick sc->sc_ctrnscnt = count & 0xff; 60253901Smckusick 60353901Smckusick /* sc_cdb */ 60453901Smckusick sc->sc_opcode = SCOP_RBLIM; 60553901Smckusick 60653901Smckusick sc_go(intr, (struct scsi *)sc, ie); 60753901Smckusick } 60853901Smckusick 60953901Smckusick /* 61053901Smckusick * SCOP_MSENSE request 61153901Smckusick */ 61253901Smckusick scop_msense(intr, sc, slave, ie, count, param) 61353901Smckusick register int intr; 61453901Smckusick register struct scsi *sc; 61553901Smckusick register int slave; 61653901Smckusick register int ie; 61753901Smckusick register int count; 61853901Smckusick register caddr_t param; 61953901Smckusick { 62053901Smckusick scinit(sc, slave, DEV_BSIZE); 62153901Smckusick 62253901Smckusick sc->sc_cpoint = (u_char *)param; 62353901Smckusick sc->sc_ctrnscnt = count & 0xff; 62453901Smckusick 62553901Smckusick /* sc_cdb */ 62653901Smckusick sc->sc_opcode = SCOP_MSENSE; 62753901Smckusick sc->sc_lad = count >> 8; 62853901Smckusick sc->sc_count = count & 0xff; 62953901Smckusick 63053901Smckusick sc_go(intr, (struct scsi *)sc, ie); 63153901Smckusick } 63253901Smckusick 63353901Smckusick /* 63453901Smckusick * SCOP_MSELECT request 63553901Smckusick */ 63653901Smckusick scop_mselect(intr, sc, slave, ie, count, param) 63753901Smckusick register int intr; 63853901Smckusick register struct scsi *sc; 63953901Smckusick register int slave; 64053901Smckusick register int ie; 64153901Smckusick register int count; 64253901Smckusick register caddr_t param; 64353901Smckusick { 64453901Smckusick u_char psave[20]; 64553901Smckusick 64653901Smckusick bcopy((caddr_t)sc->sc_param, (caddr_t)psave, 20); 64753901Smckusick scinit(sc, slave, DEV_BSIZE); 64853901Smckusick bcopy((caddr_t)psave, (caddr_t)sc->sc_param, 20); 64953901Smckusick 65053901Smckusick sc->sc_cpoint = (u_char *)param; 65153901Smckusick sc->sc_ctrnscnt = count & 0xff; 65253901Smckusick 65353901Smckusick /* sc_cdb */ 65453901Smckusick sc->sc_opcode = SCOP_MSELECT; 65553901Smckusick sc->sc_lad = count >> 8; 65653901Smckusick sc->sc_count = count & 0xff; 65753901Smckusick 65853901Smckusick sc_go(intr, (struct scsi *)sc, ie); 65953901Smckusick } 66053901Smckusick 66153901Smckusick #ifdef SRD_MSELECT 66253901Smckusick /* 66353901Smckusick * SCOP_MSELECT request 66453901Smckusick */ 66553901Smckusick scop_msense_OTHER_HD(intr, sc, slave, ie, count, param) 66653901Smckusick register int intr; 66753901Smckusick register struct scsi *sc; 66853901Smckusick register int slave; 66953901Smckusick register int ie; 67053901Smckusick register int count; 67153901Smckusick register caddr_t param; 67253901Smckusick { 67353901Smckusick scinit(sc, slave, DEV_BSIZE); 67453901Smckusick 67553901Smckusick sc->sc_cpoint = (u_char *)param; 67653901Smckusick sc->sc_ctrnscnt = count; 67753901Smckusick 67853901Smckusick /* sc_cdb */ 67953901Smckusick sc->sc_opcode = SCOP_MSENSE; 68053901Smckusick sc->sc_count = count; 68153901Smckusick sc->sc_lad = 0x3f00; 68253901Smckusick 68353901Smckusick sc_go(intr, (struct scsi *)sc, ie); 68453901Smckusick } 68553901Smckusick 68653901Smckusick /* 68753901Smckusick * SCOP_MSELECT request 68853901Smckusick */ 68953901Smckusick scop_mselect_OTHER_HD(intr, sc, slave, ie, count, param) 69053901Smckusick register int intr; 69153901Smckusick register struct scsi *sc; 69253901Smckusick register int slave; 69353901Smckusick register int ie; 69453901Smckusick register int count; 69553901Smckusick register caddr_t param; 69653901Smckusick { 69753901Smckusick u_char psave[20]; 69853901Smckusick 69953901Smckusick bcopy((caddr_t)sc->sc_param, (caddr_t)psave, 20); 70053901Smckusick scinit(sc, slave, DEV_BSIZE); 70153901Smckusick bcopy((caddr_t)psave, (caddr_t)sc->sc_param, 20); 70253901Smckusick 70353901Smckusick sc->sc_cpoint = (u_char *)param; 70453901Smckusick sc->sc_ctrnscnt = count; 70553901Smckusick 70653901Smckusick /* sc_cdb */ 70753901Smckusick sc->sc_opcode = SCOP_MSELECT; 70853901Smckusick sc->sc_count = count; 70953901Smckusick sc->sc_lad = 0; 71053901Smckusick 71153901Smckusick sc_go(intr, (struct scsi *)sc, ie); 71253901Smckusick } 71353901Smckusick #endif SRD_MSELECT 71453901Smckusick 71553901Smckusick scop_erase(intr, sc, slave, ie) 71653901Smckusick register int intr; 71753901Smckusick register struct scsi *sc; 71853901Smckusick register int slave; 71953901Smckusick register int ie; 72053901Smckusick { 72153901Smckusick scinit(sc, slave, DEV_BSIZE); 72253901Smckusick 72353901Smckusick /* sc_cdb */ 72453901Smckusick sc->sc_opcode = SCOP_ERASE; 72553901Smckusick sc->sc_tucode = 1; 72653901Smckusick 72753901Smckusick sc_go(intr, (struct scsi *)sc, ie); 72853901Smckusick } 72953901Smckusick 73053901Smckusick /* 73153901Smckusick * One sector programmed I/O 73253901Smckusick */ 73353901Smckusick scop_rdwr(intr, sc, slave, ie, flag, addr, lba, sectsize) 73453901Smckusick int intr; 73553901Smckusick register struct scsi *sc; 73653901Smckusick int slave; 73753901Smckusick int ie; 73853901Smckusick int flag; 73953901Smckusick caddr_t addr; 74053901Smckusick int lba; 74153901Smckusick int sectsize; 74253901Smckusick { 74353901Smckusick scinit(sc, slave, sectsize); 74453901Smckusick 74553901Smckusick sc->sc_cpoint = (u_char *)addr; 74653901Smckusick sc->sc_ctrnscnt = sectsize; 74753901Smckusick 74853901Smckusick /* sc_cdb */ 74953901Smckusick sc->sc_opcode = (flag & B_READ) ? SCOP_READ : SCOP_WRITE; 75053901Smckusick sc->sc_lad = lba; 75153901Smckusick sc->sc_count = 1; 75253901Smckusick 75353901Smckusick sc_go(intr, sc, ie); 75453901Smckusick } 75553901Smckusick 75653901Smckusick /* 75753901Smckusick * Medium allow/prevent removable 75853901Smckusick */ 75953901Smckusick scop_medrmv(intr, sc, slave, ie, sw) 76053901Smckusick register int intr; 76153901Smckusick register struct scsi *sc; 76253901Smckusick register int slave; 76353901Smckusick register int ie; 76453901Smckusick register int sw; 76553901Smckusick { 76653901Smckusick scinit(sc, slave, DEV_BSIZE); 76753901Smckusick 76853901Smckusick /* sc_cdb */ 76953901Smckusick sc->sc_opcode = SCOP_MEDRMV; 77053901Smckusick sc->sc_count = sw; 77153901Smckusick 77253901Smckusick sc_go(intr, (struct scsi *)sc, ie); 77353901Smckusick } 77453901Smckusick 77553901Smckusick /* 77653901Smckusick * initialize struct scsi 77753901Smckusick */ 77853901Smckusick scinit(sc, slave, sectsize) 77953901Smckusick register struct scsi *sc; 78053901Smckusick int slave; 78153901Smckusick int sectsize; 78253901Smckusick { 78353901Smckusick bzero((caddr_t)sc, sizeof(struct scsi)); 78453901Smckusick 78553901Smckusick sc->sc_identify = MSG_IDENT|Scsi_Disconnect|(slave & IDT_DRMASK); 78653901Smckusick sc->sc_bytesec = sectsize; 78753901Smckusick sc->sc_lun = slave; 78853901Smckusick } 78953901Smckusick 79053901Smckusick 79153901Smckusick /* 79253901Smckusick * ABORT MESSAGE 79353901Smckusick */ 79453901Smckusick scms_abort(intr, sc, slave, ie) 79553901Smckusick register int intr; 79653901Smckusick register struct scsi *sc; 79753901Smckusick register int slave; 79853901Smckusick register int ie; 79953901Smckusick { 80053901Smckusick bzero((caddr_t)sc, sizeof(struct scsi)); 80153901Smckusick 80253901Smckusick sc->sc_identify = MSG_ABORT; 80353901Smckusick 80453901Smckusick /* sc_cdb */ 80553901Smckusick sc->sc_opcode = SCOP_TST; 80653901Smckusick sc->sc_lun = slave; 80753901Smckusick 80853901Smckusick sc_go(intr, (struct scsi *)sc, ie); 80953901Smckusick } 81053901Smckusick 81153901Smckusick sc_go(intr, sc, ie) 81253901Smckusick int intr; 81353901Smckusick struct scsi *sc; 81453901Smckusick int ie; 81553901Smckusick { 81653901Smckusick register struct sc_data *scdp; 81753901Smckusick 81853901Smckusick scdp = &sc_data[intr]; 81953901Smckusick 82053901Smckusick if (sc->sc_cpoint) 82153901Smckusick scdp->scd_vaddr = (char *)sc->sc_cpoint; 82253901Smckusick else 82353901Smckusick scdp->scd_vaddr = (char *)sc->sc_param; 82453901Smckusick scdp->scd_procp = curproc; 82553901Smckusick scdp->scd_scaddr = (char *)sc; 82653901Smckusick scdp->scd_count = sc->sc_ctrnscnt; 82753901Smckusick sc->sc_cpoint = (u_char *)ipc_phys(scdp->scd_vaddr); 82853901Smckusick 82953901Smckusick _sc_go(intr, sc, ie); 83053901Smckusick 83153901Smckusick if((ie & SCSI_INTEN) == 0) { 83253901Smckusick #ifdef mips 83353901Smckusick /* if (DATAIN_PHASE_FINISHED) */ 83453901Smckusick MachFlushDCache(scdp->scd_scaddr, sizeof (struct scsi)); 83553901Smckusick if (MACH_IS_USPACE(scdp->scd_vaddr)) 83653901Smckusick panic("sc_go: user address is not supported"); 83753901Smckusick else if (MACH_IS_CACHED(scdp->scd_vaddr)) 83853901Smckusick MachFlushDCache(scdp->scd_vaddr, scdp->scd_count); 83953901Smckusick else if (MACH_IS_MAPPED(scdp->scd_vaddr)) 84053901Smckusick #ifdef notyet /* KU:XXX */ 84153901Smckusick clean_k2dcache(scdp->scd_vaddr, scdp->scd_count); 84253901Smckusick #else 84353901Smckusick MachFlushCache(); /* Flush all caches */ 84453901Smckusick #endif 84553901Smckusick #endif /* mips */ 84653901Smckusick } 84753901Smckusick } 84853901Smckusick 84953901Smckusick #ifdef CPU_SINGLE 85053901Smckusick _sc_go(intr, sc, ie) 85153901Smckusick int intr; 85253901Smckusick struct scsi *sc; 85353901Smckusick int ie; 85453901Smckusick { 85553901Smckusick register int i, s; 85653901Smckusick 85753901Smckusick if((ie & SCSI_INTEN) == 0) { 85853901Smckusick scsend(intr, ie|SCSI_NOTWAIT, sc); 85953901Smckusick while (sc_busy(intr)) { 86053901Smckusick splx(splscon()); /* splsc -1 */ 86153901Smckusick #ifdef mc68030 86253901Smckusick dcia(); 86353901Smckusick #endif 86453901Smckusick } 86553901Smckusick } else { 86653901Smckusick scsend(intr, ie, (caddr_t)sc); 86753901Smckusick } 86853901Smckusick } 86953901Smckusick #endif /* CPU_SINGLE */ 87053901Smckusick 87153901Smckusick screset(chan) 87253901Smckusick int chan; 87353901Smckusick { 87453901Smckusick int i, s; 87553901Smckusick 87653901Smckusick s = splsc(); 87753901Smckusick printf("SCSI: screset() called "); 87853901Smckusick scop_init(chan / 8); 87953901Smckusick splx(s); 88053901Smckusick 88153901Smckusick for (s = 0; s < 10; s++) { 88253901Smckusick DELAY(100000 * 10); 88353901Smckusick } 88453901Smckusick printf("\n"); 88553901Smckusick iop/**/reset(); 88653901Smckusick } 88753901Smckusick 88853901Smckusick scsisetup(bp, map, nmap) 88953901Smckusick struct buf *bp; 89053901Smckusick struct sc_map *map; 89153901Smckusick int nmap; 89253901Smckusick { 89353901Smckusick return (iop/**/setup(bp, map, nmap)); 89453901Smckusick } 89553901Smckusick 89653901Smckusick 89753901Smckusick /* 89853901Smckusick * transrate skey / ecode into message display ON/OFF value 89953901Smckusick * 1 : display message 90053901Smckusick * 0 : silence 90153901Smckusick */ 90253901Smckusick isdispmsg(code, list, count) 90353901Smckusick register int code; 90453901Smckusick register struct msg_list *list; 90553901Smckusick int count; 90653901Smckusick { 90753901Smckusick register int msglvl = 0; 90853901Smckusick 90953901Smckusick while (list->ml_code >= 0) { 91053901Smckusick if (code == list->ml_code) { 91153901Smckusick msglvl = list->ml_msglvl; 91253901Smckusick break; 91353901Smckusick } 91453901Smckusick list++; 91553901Smckusick } 91653901Smckusick return (count >= msglvl); 91753901Smckusick } 91853901Smckusick 91953901Smckusick #ifdef NO_SHRINK_RSENSE_MSG 92053901Smckusick /* 92153901Smckusick * transrate skey / ecode into message 92253901Smckusick */ 92353901Smckusick char * 92453901Smckusick getmsg(code, list, defmsg) 92553901Smckusick int code; 92653901Smckusick struct msg_list *list; 92753901Smckusick char *defmsg; 92853901Smckusick { 92953901Smckusick while (list->ml_code >= 0) { 93053901Smckusick if (code == list->ml_code) 93153901Smckusick return (list->ml_msgstr); 93253901Smckusick list++; 93353901Smckusick } 93453901Smckusick return (defmsg); 93553901Smckusick } 93653901Smckusick #endif /* NO_SHRINK_RSENSE_MSG */ 93753901Smckusick 93853901Smckusick check_chan_busy(intr, sc, slave) 93953901Smckusick register int intr; 94053901Smckusick register struct scsi *sc; 94153901Smckusick register int slave; 94253901Smckusick { 94353901Smckusick register struct sc_extnd *sce = (struct sc_extnd *)sc->sc_param; 94453901Smckusick int i = 0; 94553901Smckusick 94653901Smckusick if (sc->sc_istatus == INST_EP) { 94753901Smckusick switch (sc->sc_tstatus) { 94853901Smckusick 94953901Smckusick case TGST_CC: 95053901Smckusick scop_rsense(intr, sc, slave, SCSI_INTDIS, 18, 0); 95153901Smckusick if (rsense_msg_disp || 95253901Smckusick isdispmsg(sce->sce_skey, skeylist, 0)) { 95353901Smckusick #ifdef NO_SHRINK_RSENSE_MSG 95453901Smckusick if (sce->sce_advalid) { 95553901Smckusick printf("SCSI%d(block %d): %s (sense key = 0x%x)\n", 95653901Smckusick intr, 95753901Smckusick (sce->sce_infob1 << 24) + 95853901Smckusick (sce->sce_infob2 << 16) + 95953901Smckusick (sce->sce_infob3 << 8) + 96053901Smckusick (sce->sce_infob4), 96153901Smckusick getmsg(sce->sce_skey, skeylist, "(reserved)"), 96253901Smckusick sce->sce_skey); 96353901Smckusick } else { 96453901Smckusick printf("SCSI%d(unknown block): %s (sense key = 0x%x)\n", 96553901Smckusick intr, 96653901Smckusick getmsg(sce->sce_skey, skeylist, "(reserved)"), 96753901Smckusick sce->sce_skey); 96853901Smckusick } 96953901Smckusick #else /* NO_SHRINK_RSENSE_MSG */ 97053901Smckusick if (sce->sce_advalid) { 97153901Smckusick printf("SCSI%d(sn %d): skey=0x%x)\n", 97253901Smckusick intr, 97353901Smckusick (sce->sce_infob1 << 24) + 97453901Smckusick (sce->sce_infob2 << 16) + 97553901Smckusick (sce->sce_infob3 << 8) + 97653901Smckusick (sce->sce_infob4), 97753901Smckusick sce->sce_skey); 97853901Smckusick } else { 97953901Smckusick printf("SCSI%d: skey=0x%x)\n", 98053901Smckusick intr, sce->sce_skey); 98153901Smckusick } 98253901Smckusick #endif /* NO_SHRINK_RSENSE_MSG */ 98353901Smckusick printf("sense data = "); 98453901Smckusick for (i = 0; i < 18; i++) 98553901Smckusick printf("%x ", sc->sc_param[i]); 98653901Smckusick printf("\n"); 98753901Smckusick } 98853901Smckusick break; 98953901Smckusick 99053901Smckusick case TGST_GOOD: 99153901Smckusick break; 99253901Smckusick 99353901Smckusick default: 99453901Smckusick printf("SCSI%d: bad target status 0x%x\n", intr, sc->sc_tstatus); 99553901Smckusick break; 99653901Smckusick } 99753901Smckusick } else { 99853901Smckusick printf("SCSI%d: bad initiator status 0x%x\n", intr, sc->sc_istatus); 99953901Smckusick } 100053901Smckusick 100153901Smckusick while (i++ < 100000) { 100253901Smckusick scop_tst(intr, sc, slave, SCSI_INTDIS); 100353901Smckusick if (sc->sc_tstatus != TGST_BUSY) 100453901Smckusick break; 100553901Smckusick } 100653901Smckusick if (i > 100000) 100753901Smckusick printf("SCSI%d: still busy after rasblk.\n", intr); 100853901Smckusick } 100953901Smckusick 101053901Smckusick /***/ 101153901Smckusick struct scsi_berr_bug_table { 101253901Smckusick int model; 101353901Smckusick int serial_l; 101453901Smckusick int serial_h; 101553901Smckusick int value; /* 1:BUG, 0:NOBUG */ 101653901Smckusick }; 101753901Smckusick /***/ 1018