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: sd.c,v 4.300 91/06/27 20:42:56 root Rel41 $ SONY 1153901Smckusick * 12*57612Sutashiro * @(#)sd.c 7.4 (Berkeley) 01/20/93 1353901Smckusick */ 1453901Smckusick #define dkblock(bp) bp->b_blkno 1553901Smckusick 1653901Smckusick /* 1753901Smckusick * Copyright (c) 1987-1991 by SONY Corporation. 1853901Smckusick */ 1953901Smckusick 2053901Smckusick #include "sd.h" 2153901Smckusick #if NSD > 0 2253901Smckusick 2357182Sutashiro #include <machine/fix_machine_type.h> 2453901Smckusick 2557182Sutashiro #include <sys/param.h> 2657182Sutashiro #include <sys/buf.h> 2757182Sutashiro #include <sys/proc.h> 2857182Sutashiro #include <sys/user.h> 2957182Sutashiro #include <sys/dkstat.h> 3057182Sutashiro #include <sys/uio.h> 3157182Sutashiro #include <sys/kernel.h> 3257182Sutashiro #include <sys/reboot.h> 3357182Sutashiro #include <sys/ioctl.h> 3457182Sutashiro #include <sys/systm.h> 3557182Sutashiro #include <sys/mtio.h> 3657182Sutashiro #include <sys/stat.h> 3757182Sutashiro #include <sys/disklabel.h> 3857182Sutashiro #include <vm/vm.h> 3957182Sutashiro #include <sys/syslog.h> 4053901Smckusick 4157182Sutashiro #include <ufs/ffs/fs.h> 4253901Smckusick 4357182Sutashiro # include <machine/cpu.h> 4453901Smckusick 4553901Smckusick #ifdef IPC_MRX 4653901Smckusick # include "../iop/iopvar.h" 4753901Smckusick # include "../ipc/newsipc.h" 4853901Smckusick #endif 4953901Smckusick 5053901Smckusick #ifdef CPU_SINGLE 5157182Sutashiro # include <news3400/hbdev/hbvar.h> 5257182Sutashiro # include <news3400/iodev/ioptohb.h> 5353901Smckusick #endif 5453901Smckusick 5557182Sutashiro #include <news3400/iodev/scsireg.h> 5657182Sutashiro #include <news3400/iodev/scu.h> 5757182Sutashiro #include <news3400/iodev/dkio.h> 5857182Sutashiro #include <news3400/iodev/sdreg.h> 5953901Smckusick /* #ifdef DISKINFO KU:XXX */ 6057182Sutashiro #include <news3400/iodev/diskinfo.h> 6153901Smckusick /* #endif /* DISKINFO */ 6253901Smckusick 6353901Smckusick #define sce_sdecode sce_hdecode 6453901Smckusick 6553901Smckusick #define dev2unit(x) ((minor(x) & ~0x80) >> 3) 6653901Smckusick #define dev2part(x) (minor(x) & 0x7) 6753901Smckusick 6853901Smckusick /* /sys/sys/file.h */ 6953901Smckusick #define FREAD 00001 /* descriptor read/receive'able */ 7053901Smckusick #define FWRITE 00002 /* descriptor write/send'able */ 7153901Smckusick 7253901Smckusick #define PART_A 0 7353901Smckusick #define PART_B 1 7453901Smckusick #define PART_C 2 7553901Smckusick #define PART_D 3 7653901Smckusick #define PART_E 4 7753901Smckusick #define PART_F 5 7853901Smckusick #define PART_G 6 7953901Smckusick #define PART_H 7 8053901Smckusick 8153901Smckusick #define MAXPROBERETRY 100 8253901Smckusick #define NRETRY 10 8353901Smckusick #define MAXHRDERR 100 8453901Smckusick #define MAXRETRYCNT 16 8553901Smckusick 8653901Smckusick #define SDBSIZE1K (DEV_BSIZE * 2) 8753901Smckusick #define MAXSDPHYS ((NSCMAP - 1) * NBPG) 8853901Smckusick 8953901Smckusick #define D100MSEC 100000 9053901Smckusick 9153901Smckusick #if OD_STOPTIME < 1 9253901Smckusick # define OD_STOPTIME 5 9353901Smckusick #endif /* OD_STOPTIME < 1 */ 9453901Smckusick 9553901Smckusick #define FORMAT_MODE_CORRUPTED 0x31 9653901Smckusick #define ONLY_ONE 1 9753901Smckusick 9853901Smckusick /************** PARTITIONS *************************************/ 9953901Smckusick 10053901Smckusick #define PART_UNUSED (0) 10153901Smckusick #define PART_SPEC (-1) 10253901Smckusick #define PART_CALCF (-2) 10353901Smckusick #define PART_CALCG (-3) 10453901Smckusick 10553901Smckusick struct defpart { 10653901Smckusick int range_min; 10753901Smckusick int range_max; 10853901Smckusick int partsize[PNUM]; 10953901Smckusick }; 11053901Smckusick 11153901Smckusick struct defpart defpart_std[] = { 11253901Smckusick { 11353901Smckusick 0, /* range_min */ 11453901Smckusick 20, /* range_max */ 11553901Smckusick 11653901Smckusick PART_SPEC, /* A: */ 11753901Smckusick PART_UNUSED, /* B: */ 11853901Smckusick PART_SPEC, /* C: */ 11953901Smckusick PART_UNUSED, /* D: */ 12053901Smckusick PART_UNUSED, /* E: */ 12153901Smckusick PART_UNUSED, /* F: */ 12253901Smckusick PART_UNUSED, /* G: */ 12353901Smckusick PART_UNUSED, /* H: */ 12453901Smckusick }, 12553901Smckusick { 12653901Smckusick 20, /* range_min */ 12753901Smckusick 61, /* range_max */ 12853901Smckusick 12953901Smckusick 15884, /* A: */ 13053901Smckusick 10032, /* B: */ 13153901Smckusick PART_SPEC, /* C: */ 13253901Smckusick 15884, /* D: */ 13353901Smckusick PART_UNUSED, /* E: */ 13453901Smckusick PART_CALCF, /* F: */ 13553901Smckusick PART_CALCG, /* G: */ 13653901Smckusick PART_UNUSED, /* H: */ 13753901Smckusick }, 13853901Smckusick { 13953901Smckusick 61, /* range_min */ 14053901Smckusick 206, /* range_max */ 14153901Smckusick 14253901Smckusick 15884, /* A: */ 14353901Smckusick 33440, /* B: */ 14453901Smckusick PART_SPEC, /* C: */ 14553901Smckusick 15884, /* D: */ 14653901Smckusick 55936, /* E: */ 14753901Smckusick PART_CALCF, /* F: */ 14853901Smckusick PART_CALCG, /* G: */ 14953901Smckusick PART_UNUSED, /* H: */ 15053901Smckusick }, 15153901Smckusick { 15253901Smckusick 206, /* range_min */ 15353901Smckusick 356, /* range_max */ 15453901Smckusick 15553901Smckusick 15884, /* A: */ 15653901Smckusick 33440, /* B: */ 15753901Smckusick PART_SPEC, /* C: */ 15853901Smckusick 15884, /* D: */ 15953901Smckusick 55936, /* E: */ 16053901Smckusick PART_CALCF, /* F: */ 16153901Smckusick PART_CALCG, /* G: */ 16253901Smckusick 291346, /* H: */ 16353901Smckusick }, 16453901Smckusick { 16553901Smckusick 356, /* range_min */ 16653901Smckusick 99999999, /* range_max */ 16753901Smckusick 16853901Smckusick 15884, /* A: */ 16953901Smckusick 66880, /* B: */ 17053901Smckusick PART_SPEC, /* C: */ 17153901Smckusick 15884, /* D: */ 17253901Smckusick 307200, /* E: */ 17353901Smckusick PART_CALCF, /* F: */ 17453901Smckusick PART_CALCG, /* G: */ 17553901Smckusick 291346, /* H: */ 17653901Smckusick }, 17753901Smckusick { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 17853901Smckusick }; 17953901Smckusick 18053901Smckusick /************* ADDITIONAL SENSE ERROR CODES *************************/ 18153901Smckusick 18253901Smckusick struct msg_list { 18353901Smckusick int ml_code; /* message code */ 18453901Smckusick int ml_msglvl; /* message level */ 18553901Smckusick char *ml_msgstr; /* message string */ 18653901Smckusick }; 18753901Smckusick 18853901Smckusick #define sdskeylist skeylist 18953901Smckusick 19053901Smckusick struct msg_list ecodelist_mo[] = { 19153901Smckusick { 0x80, 0, NULL }, 19253901Smckusick { 0x81, 0, NULL }, 19353901Smckusick { 0x82, 0, NULL }, 19453901Smckusick { 0x83, 0, NULL }, 19553901Smckusick 19653901Smckusick { -1, 0, NULL } 19753901Smckusick }; 19853901Smckusick 19953901Smckusick /************** Ref. sd_var.c ********************************/ 20053901Smckusick 20153901Smckusick extern struct iop/**/_ctlr *sdminfo[]; 20253901Smckusick extern struct iop/**/_device *sddinfo[]; 20353901Smckusick extern struct iop/**/_device *sdip[][MAXSLAVE]; 20453901Smckusick 20553901Smckusick extern struct buf rsdbuf[]; /* buffer for raw I/O */ 20653901Smckusick extern struct buf csdbuf[]; /* buffer for controll */ 20753901Smckusick extern struct buf sdutab[]; /* per drive buffers */ 20853901Smckusick 20953901Smckusick extern struct sdc_softc sdc_softc[]; 21053901Smckusick extern struct sdd_softc sdd_softc[]; 21153901Smckusick extern u_char sd_b_openf[][PNUM]; 21253901Smckusick extern u_char sd_c_openf[][PNUM]; 21353901Smckusick 21453901Smckusick extern struct scsi kernscsi[]; 21553901Smckusick extern struct sdst sdstdrv[]; 21653901Smckusick extern struct disklabel sdlabel[]; 21753901Smckusick extern struct size sdsizedrv[][PNUM]; 21853901Smckusick 21953901Smckusick extern u_char sdc_rsense[][RSEN_CNT]; 22053901Smckusick 22153901Smckusick extern struct sync_param sd_sync_param[]; 22253901Smckusick 22353901Smckusick extern int nsd; 22453901Smckusick extern int nsdc; 22553901Smckusick 22653901Smckusick /************** Ref. sddefs.c *********************************/ 22753901Smckusick 22853901Smckusick extern struct sddevinfo sddevinfo[]; 22953901Smckusick 23053901Smckusick /**************************************************************/ 23153901Smckusick 23253901Smckusick extern struct msg_list skeylist[]; 23353901Smckusick extern struct msg_list ecodelist[]; 23453901Smckusick 23553901Smckusick extern int boothowto; 23653901Smckusick extern int rsense_msg_disp; /* RSENSE-message display flag */ 23753901Smckusick extern int mo_disp_format; /* MO format mode display flag */ 23853901Smckusick 23953901Smckusick int sd_ignore_error; 24053901Smckusick 24153901Smckusick static int re_init_done; 24253901Smckusick 24353901Smckusick static u_char sdwork[2340]; /* buffer for error recovery */ 24453901Smckusick static u_char sdtmp[DEV_BSIZE]; /* buffer for temporary */ 24553901Smckusick #ifdef mips 24653901Smckusick volatile static int sdtmp_stat = 0; /* status of sdtmp */ 24753901Smckusick #else 24853901Smckusick static int sdtmp_stat = 0; /* status of sdtmp */ 24953901Smckusick #endif 25053901Smckusick 25153901Smckusick char pname[] = "abcdefgh"; 25253901Smckusick 25353901Smckusick struct scsi *get_scsi(); 25453901Smckusick struct sc_map *get_sc_map(); 25553901Smckusick struct sc_inq *get_sc_inq(); 25653901Smckusick 25753901Smckusick int sdprobe(), sdslave(), sdattach(), sddgo(), sdintr(); 25853901Smckusick int sdwstart, sdwatch(), sdstop(); /* Have started guardian */ 25953901Smckusick void sdexec(); 26053901Smckusick 26157173Sutashiro static sd_check(), sd_tstdrv(), sd_other_pages(), sd_err_rcv(), sd_synctr_on(); 26257173Sutashiro static disklabel2sdst(), sdst2disklabel(), sd_scu_exec(); 26357173Sutashiro 26453901Smckusick #ifdef CPU_SINGLE 26553901Smckusick struct hb_driver sdcdriver = 26653901Smckusick {sdprobe, sdslave, sdattach, sddgo, sdintr, "sd", sddinfo, "sdc", sdminfo}; 26753901Smckusick #else 26853901Smckusick struct iop_driver sdcdriver = 26953901Smckusick {sdprobe, sdslave, sdattach, sddgo, "sd", sddinfo, "sdc", sdminfo}; 27053901Smckusick #endif 27153901Smckusick 27253901Smckusick /*ARGSUSED*/ 27353901Smckusick sdprobe(im) 27453901Smckusick struct iop/**/_ctlr *im; 27553901Smckusick { 27653901Smckusick static int sdd_init = 0; 27753901Smckusick register struct sc_inq *sci; 27853901Smckusick register int ctlr; 27953901Smckusick register int fw; 28053901Smckusick int i; 28153901Smckusick 28253901Smckusick if (sdd_init == 0) { 28353901Smckusick sdd_init++; 28453901Smckusick for (i = 0; i < nsd; i++) 28553901Smckusick sdd_softc[i].sdd_start = -2; 28653901Smckusick } 28753901Smckusick 28853901Smckusick sci = get_sc_inq(im->im_intr); 28953901Smckusick ctlr = im->im_ctlr; 29053901Smckusick /* 29153901Smckusick * Check device type 29253901Smckusick * 0x00: Direct access device. 29353901Smckusick * 0x01: Sequential access device. 29453901Smckusick * 0x04: Write-once read-multiple device. 29553901Smckusick * 0x05: Read-only Direct-access device. 29653901Smckusick * 0x7f: Specified device is nonexistent. 29753901Smckusick */ 29853901Smckusick fw = sdc_softc[ctlr].sdc_firmware & ~SDCFW_DEVMASK; 29953901Smckusick 30053901Smckusick switch (sci->sci_devtype) { 30153901Smckusick 30253901Smckusick case 0x00: 30353901Smckusick /* 30453901Smckusick * Assumed that the device is HD. 30553901Smckusick * Later, distinguish MO from HD. 30653901Smckusick */ 30753901Smckusick sdc_softc[ctlr].sdc_firmware = fw | SDCFW_HD; 30853901Smckusick break; 30953901Smckusick 31053901Smckusick default: 31153901Smckusick /* 31253901Smckusick * device type mis-match 31353901Smckusick */ 31453901Smckusick return (0); 31553901Smckusick } 31653901Smckusick 31753901Smckusick /* 31853901Smckusick * Set interrupt handler routine 31953901Smckusick */ 32053901Smckusick if (set_inthandler(im, sdintr) == 0) 32153901Smckusick return (0); 32253901Smckusick 32353901Smckusick return (1); 32453901Smckusick } 32553901Smckusick 32653901Smckusick 32753901Smckusick /*ARGSUSED*/ 32853901Smckusick sdslave(ii, reg, intr) 32953901Smckusick register struct iop/**/_device *ii; 33053901Smckusick caddr_t reg; 33153901Smckusick int intr; 33253901Smckusick { 33353901Smckusick register struct scsi *sc; 33453901Smckusick 33553901Smckusick sc = get_scsi(intr); 33653901Smckusick sdip[ii->ii_ctlr][ii->ii_slave] = ii; 33753901Smckusick ii->ii_intr = intr; 33853901Smckusick 33953901Smckusick /* 34053901Smckusick * check what the device is. 34153901Smckusick */ 34253901Smckusick if ((ii->ii_type = sd_check(ii, sc)) < 0) 34353901Smckusick goto bad_slave; 34453901Smckusick 34553901Smckusick /* 34653901Smckusick * set up ERROR RECOVERY PARAMETERS 34753901Smckusick */ 34853901Smckusick if (sd_err_rcv(ii, sc) < 0) 34953901Smckusick goto bad_slave; 35053901Smckusick 35153901Smckusick /* 35253901Smckusick * set up OTHER PARAMETERS 35353901Smckusick */ 35453901Smckusick if (sd_other_pages(ii, sc) < 0) 35553901Smckusick goto bad_slave; 35653901Smckusick 35753901Smckusick /* 35853901Smckusick * set up Synchronous Transfer 35953901Smckusick */ 36053901Smckusick sd_synctr_on(ii, sc); 36153901Smckusick 36253901Smckusick return (1); 36353901Smckusick 36453901Smckusick bad_slave: 36553901Smckusick /* 36653901Smckusick * no such slave 36753901Smckusick */ 36853901Smckusick ii->ii_intr = -1; 36953901Smckusick return (0); 37053901Smckusick } 37153901Smckusick 37253901Smckusick identity_check(sci, capacity, unit) 37353901Smckusick register struct sc_inq *sci; 37453901Smckusick int capacity; 37553901Smckusick int unit; 37653901Smckusick { 37753901Smckusick register struct sddevinfo *sdi; 37853901Smckusick register u_char *id_name; 37953901Smckusick register int index; 38053901Smckusick register int i; 38153901Smckusick int id_pass; 38253901Smckusick 38353901Smckusick id_name = sci->sci_vendid; 38453901Smckusick while (*id_name == ' ') 38553901Smckusick id_name++; 38653901Smckusick 38753901Smckusick index = UNKNOWN_DISK; 38853901Smckusick id_pass = 0; 38953901Smckusick for (sdi = sddevinfo; sdi->id_len >= 0; sdi++) { 39053901Smckusick /* 39153901Smckusick * check vendor & product ID 39253901Smckusick */ 39353901Smckusick if (strncmp(id_name, sdi->id_name, sdi->id_len) != 0) 39453901Smckusick continue; 39553901Smckusick id_pass = sdi - sddevinfo; 39653901Smckusick 39753901Smckusick /* 39853901Smckusick * check revision 39953901Smckusick */ 40053901Smckusick if (strncmp(sdi->revs, sci->sci_revision, 4) == 0) 40153901Smckusick index = id_pass; 40253901Smckusick else { 40353901Smckusick for (i = 0; i < 4; i++) { 40453901Smckusick if (*(sdi->revs + i) == '?') 40553901Smckusick continue; 40653901Smckusick if (*(sdi->revs + i) != sci->sci_revision[i]) 40753901Smckusick break; 40853901Smckusick } 40953901Smckusick if (i < 4) 41053901Smckusick continue; 41153901Smckusick } 41253901Smckusick 41353901Smckusick /* 41453901Smckusick * check capacity 41553901Smckusick */ 41653901Smckusick if (capacity == -1) 41753901Smckusick break; 41853901Smckusick if (sdi->capacity == -1) { 41953901Smckusick printf("sd%d: capacity=0x%x(%d)\n", 42053901Smckusick unit, capacity, capacity); 42153901Smckusick break; 42253901Smckusick } 42353901Smckusick if (capacity == sdi->capacity) 42453901Smckusick break; 42553901Smckusick } 42653901Smckusick if (index == 0) 42753901Smckusick index = id_pass; 42853901Smckusick 42953901Smckusick return (index); 43053901Smckusick } 43153901Smckusick 43253901Smckusick search_index(type) 43353901Smckusick register int type; 43453901Smckusick { 43553901Smckusick register struct sddevinfo *sdi; 43653901Smckusick register int i; 43753901Smckusick int index; 43853901Smckusick 43953901Smckusick index = UNKNOWN_DISK; 44053901Smckusick i = 0; 44153901Smckusick for (sdi = sddevinfo; sdi->id_len > 0; sdi++) { 44253901Smckusick if (sdi->type == type) { 44353901Smckusick index = i; 44453901Smckusick break; 44553901Smckusick } 44653901Smckusick i++; 44753901Smckusick } 44853901Smckusick return (index); 44953901Smckusick } 45053901Smckusick 45153901Smckusick static 45253901Smckusick sd_check(ii, sc) 45353901Smckusick register struct iop/**/_device *ii; 45453901Smckusick register struct scsi *sc; 45553901Smckusick { 45653901Smckusick register struct sc_inq *sci; 45753901Smckusick register struct sc_rcap *scr; 45853901Smckusick register int intr; 45953901Smckusick register int slave; 46053901Smckusick register int unit; 46153901Smckusick struct sdc_softc *sdc; 46253901Smckusick struct sdd_softc *sdd; 46353901Smckusick struct sc_extnd *sce; 46453901Smckusick int retrycnt; 46553901Smckusick int index; 46653901Smckusick int media_in; 46753901Smckusick 46853901Smckusick intr = ii->ii_intr; 46953901Smckusick slave = ii->ii_slave; 47053901Smckusick unit = ii->ii_unit; 47153901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 47253901Smckusick sdd = &sdd_softc[unit]; 47353901Smckusick scr = (struct sc_rcap *)sc->sc_param; 47453901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 47553901Smckusick 47653901Smckusick /* 47753901Smckusick * check if the logical unit is ready. 47853901Smckusick * (by TEST UNIT READY command) 47953901Smckusick */ 48053901Smckusick media_in = sd_tstdrv(ii, sc); 48153901Smckusick if (media_in < 0) 48253901Smckusick return (-3); 48353901Smckusick 48453901Smckusick /* 48553901Smckusick * Get controller and drive information. 48653901Smckusick * (by INQUIRY command) 48753901Smckusick */ 48853901Smckusick retrycnt = 0; 48953901Smckusick sci = get_sc_inq(intr); 49053901Smckusick loop_inq: 49153901Smckusick if (retrycnt++ > MAXPROBERETRY) 49253901Smckusick return (-1); 49353901Smckusick 49453901Smckusick scop_inquiry(intr, sc, slave, SCSI_INTDIS, sizeof(struct sc_inq), sci); 49553901Smckusick sc->sc_tstatus &= TGSTMASK; 49653901Smckusick 49753901Smckusick if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) { 49853901Smckusick 49953901Smckusick bzero((caddr_t)sce, RSEN_CNT); 50053901Smckusick scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT, 50153901Smckusick (caddr_t)sce); 50253901Smckusick sc->sc_tstatus &= TGSTMASK; 50353901Smckusick if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) 50453901Smckusick return (-1); 50553901Smckusick if (sce->sce_extend != 0x70) 50653901Smckusick goto loop_inq; 50753901Smckusick 50853901Smckusick switch (sce->sce_sdecode) { 50953901Smckusick 51053901Smckusick case 0x04: /* Drive Not Ready */ 51153901Smckusick case 0x28: /* Medium Changed */ 51253901Smckusick case 0x29: /* Power On or Reset or Bus Device Reset */ 51353901Smckusick case 0x2a: /* Mode Select Parameter Changed */ 51453901Smckusick break; 51553901Smckusick 51653901Smckusick default: 51753901Smckusick return (-1); 51853901Smckusick } 51953901Smckusick DELAY(D100MSEC); /* wait 100 ms. */ 52053901Smckusick goto loop_inq; 52153901Smckusick } 52253901Smckusick 52353901Smckusick index = identity_check(sci, -1, unit); 52453901Smckusick 52553901Smckusick switch (sddevinfo[index].type) { 52653901Smckusick 52753901Smckusick case SMO_S501: 52853901Smckusick case SMO_S501_ISO: 52953901Smckusick case SMO_S501_ISO2: 53053901Smckusick sdc->sdc_firmware = 53153901Smckusick SDCFW_MO | (sdc->sdc_firmware & ~SDCFW_DEVMASK); 53253901Smckusick break; 53353901Smckusick 53453901Smckusick defaults: 53553901Smckusick break; 53653901Smckusick } 53753901Smckusick 53853901Smckusick if (sci->sci_qual & 0x80) { 53953901Smckusick /* 54053901Smckusick * removable medium device 54153901Smckusick */ 54253901Smckusick sdc->sdc_firmware |= SDCFW_RMB; 54353901Smckusick if ((media_in == 0) || ((sdc->sdc_firmware & SDCFW_MO) == 0)) 54453901Smckusick return (index); 54553901Smckusick } 54653901Smckusick 54753901Smckusick /****************/ 54853901Smckusick /* HD & MO only */ 54953901Smckusick /****************/ 55053901Smckusick /* 55153901Smckusick * Get drive capacity 55253901Smckusick * (by READ CAPACITY command) 55353901Smckusick */ 55453901Smckusick retrycnt = 0; 55553901Smckusick loop_rcap: 55653901Smckusick if (retrycnt++ > MAXPROBERETRY) 55753901Smckusick return (-4); 55853901Smckusick 55953901Smckusick scop_rcap(intr, sc, slave, SCSI_INTDIS, 8, (caddr_t)0); 56053901Smckusick sc->sc_tstatus &= TGSTMASK; 56153901Smckusick if (sc->sc_istatus != INST_EP) 56253901Smckusick return (-5); 56353901Smckusick if (sc->sc_tstatus == TGST_CC) { 56453901Smckusick bzero((caddr_t)sce, RSEN_CNT); 56553901Smckusick scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT, 56653901Smckusick (caddr_t)sce); 56753901Smckusick sc->sc_tstatus &= TGSTMASK; 56853901Smckusick if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) 56953901Smckusick return (-6); 57053901Smckusick if (sderrordisp((caddr_t)sce, ii) == FORMAT_MODE_CORRUPTED) { 57153901Smckusick scr->scr_nblock = 0; 57253901Smckusick scr->scr_blocklen = DEV_BSIZE; 57353901Smckusick sdd->sdd_flags |= SDDF_NONFMT; 57453901Smckusick } else { 57553901Smckusick DELAY(D100MSEC); /* wait 100 ms. */ 57653901Smckusick goto loop_rcap; 57753901Smckusick } 57853901Smckusick } 57953901Smckusick else if (sc->sc_tstatus != TGST_GOOD) { 58053901Smckusick DELAY(D100MSEC); /* wait 100 ms. */ 58153901Smckusick goto loop_rcap; 58253901Smckusick } 58353901Smckusick 58453901Smckusick sdd->sdd_nsect = scr->scr_nblock + 1; 58553901Smckusick sdd->sdd_sectsize = scr->scr_blocklen; 58653901Smckusick 58753901Smckusick index = identity_check(sci, scr->scr_nblock +1, unit); 58853901Smckusick 58953901Smckusick return (index); 59053901Smckusick } 59153901Smckusick 59253901Smckusick static 59353901Smckusick sd_tstdrv(ii, sc) 59453901Smckusick register struct iop/**/_device *ii; 59553901Smckusick register struct scsi *sc; 59653901Smckusick { 59753901Smckusick register struct sc_extnd *sce; 59853901Smckusick register int intr; 59953901Smckusick register int slave; 60053901Smckusick register int retrycnt; 60153901Smckusick struct sdc_softc *sdc; 60253901Smckusick struct sdd_softc *sdd; 60353901Smckusick 60453901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 60553901Smckusick sdd = &sdd_softc[ii->ii_unit]; 60653901Smckusick 60753901Smckusick intr = ii->ii_intr; 60853901Smckusick slave = ii->ii_slave; 60953901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 61053901Smckusick retrycnt = 0; 61153901Smckusick loop_tst: 61253901Smckusick if (retrycnt++ > MAXPROBERETRY) 61353901Smckusick return (-1); 61453901Smckusick 61553901Smckusick scop_tst(intr, sc, slave, SCSI_INTDIS); 61653901Smckusick sc->sc_tstatus &= TGSTMASK; 61753901Smckusick if (sc->sc_istatus != INST_EP) { 61853901Smckusick DELAY(D100MSEC); /* wait 100 ms. */ 61953901Smckusick goto loop_tst; 62053901Smckusick } 62153901Smckusick 62253901Smckusick switch (sc->sc_tstatus) { 62353901Smckusick 62453901Smckusick case TGST_CC: 62553901Smckusick /* Get error code */ 62653901Smckusick bzero((caddr_t)sce, RSEN_CNT); 62753901Smckusick scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT, 62853901Smckusick (caddr_t)sce); 62953901Smckusick sc->sc_tstatus &= TGSTMASK; 63053901Smckusick if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) { 63153901Smckusick DELAY(D100MSEC); /* wait 100 ms. */ 63253901Smckusick goto loop_tst; 63353901Smckusick } 63453901Smckusick 63553901Smckusick if (sce->sce_extend != 0x70) 63653901Smckusick goto loop_tst; 63753901Smckusick 63853901Smckusick switch (sce->sce_skey) { 63953901Smckusick 64053901Smckusick case 0x0: /* No Sense */ 64153901Smckusick case 0x4: /* Hardware error */ 64253901Smckusick case 0x6: /* Unit attention */ 64353901Smckusick goto loop_tst; 64453901Smckusick 64553901Smckusick case 0x2: /* Not ready */ 64653901Smckusick switch (sce->sce_sdecode) { 64753901Smckusick 64853901Smckusick case 0x04: /* Not ready */ 64953901Smckusick /* 65053901Smckusick * Drive not ready... so start.. 65153901Smckusick */ 65253901Smckusick scop_stst(intr, sc, slave, SCSI_INTDIS, SDSS_START); 65353901Smckusick DELAY(D100MSEC * 10); /* wait 1 sec. */ 65453901Smckusick goto loop_tst; 65553901Smckusick 65653901Smckusick case 0x0a: /* No Disk *//*MO*/ 65753901Smckusick default: 65853901Smckusick DELAY(D100MSEC); 65953901Smckusick goto loop_tst; 66053901Smckusick } 66153901Smckusick break; 66253901Smckusick 66353901Smckusick case 0x03: 66453901Smckusick if (sce->sce_sdecode == FORMAT_MODE_CORRUPTED) 66553901Smckusick return (1); /* ignore error */ 66653901Smckusick /* fall through */ 66753901Smckusick 66853901Smckusick default: 66953901Smckusick return (-2); 67053901Smckusick } 67153901Smckusick break; 67253901Smckusick 67353901Smckusick case TGST_BUSY: 67453901Smckusick goto loop_tst; 67553901Smckusick 67653901Smckusick case TGST_GOOD: 67753901Smckusick break; 67853901Smckusick 67953901Smckusick default: 68053901Smckusick return (-3); 68153901Smckusick } 68253901Smckusick 68353901Smckusick return (1); 68453901Smckusick } 68553901Smckusick 68653901Smckusick #ifdef NEWSOS4 68753901Smckusick static 68853901Smckusick sd_setup_cmds(ii, sc) 68953901Smckusick register struct iop/**/_device *ii; 69053901Smckusick register struct scsi *sc; 69153901Smckusick { 69253901Smckusick register struct sddevinfo *sdi; 69353901Smckusick register struct sc_extnd *sce; 69453901Smckusick struct sc_ureq **p; 69553901Smckusick struct sc_ureq *scu; 69653901Smckusick int error; 69753901Smckusick extern struct sc_ureq scu_rsense; 69853901Smckusick 69953901Smckusick if ((p = sddevinfo[ii->ii_type].setup_cmds) == NULL) 70053901Smckusick return (0); 70153901Smckusick 70253901Smckusick /* 70353901Smckusick * Do setup commands 70453901Smckusick */ 70553901Smckusick while (scu = *p) { 70653901Smckusick bcopy((caddr_t)scu, sdtmp, sizeof(struct sc_ureq)); 70753901Smckusick scu = (struct sc_ureq *)sdtmp; 70853901Smckusick scu->scu_cdb[1] |= (ii->ii_slave & 0x07) << 5; 70953901Smckusick error = sd_scu_exec((ii->ii_unit << 3), scu, sc); 71053901Smckusick if (error != 0) 71153901Smckusick return (-1); 71253901Smckusick if ((scu->scu_istatus != INST_EP) 71353901Smckusick || (scu->scu_tstatus != TGST_GOOD)) { 71453901Smckusick bcopy((caddr_t)&scu_rsense, sdtmp, sizeof(struct sc_ureq)); 71553901Smckusick scu = (struct sc_ureq *)sdtmp; 71653901Smckusick scu->scu_cdb[1] |= (ii->ii_slave & 0x07) << 5; 71753901Smckusick sce = (scu->scu_addr == NULL) ? 71853901Smckusick (struct sc_extnd *)scu->scu_param : 71953901Smckusick (struct sc_extnd *)scu->scu_addr; 72053901Smckusick if (sd_scu_exec((ii->ii_unit << 3), scu, sc) == 0) { 72153901Smckusick /* UNIT ATTENTION */ 72253901Smckusick /* retry same command */ 72353901Smckusick if (sce->sce_skey == 0x06) 72453901Smckusick continue; 72553901Smckusick } 72653901Smckusick } 72753901Smckusick p++; 72853901Smckusick } 72953901Smckusick return (1); 73053901Smckusick } 73153901Smckusick #endif /* NEWSOS4 */ 73253901Smckusick 73353901Smckusick static 73453901Smckusick sd_other_pages(ii, sc) 73553901Smckusick register struct iop/**/_device *ii; 73653901Smckusick register struct scsi *sc; 73753901Smckusick { 73853901Smckusick register struct sddevinfo *sdi; 73953901Smckusick char **p; 74053901Smckusick char *page; 74153901Smckusick int length; 74253901Smckusick int retrycnt; 74353901Smckusick int len; 74453901Smckusick 74553901Smckusick sdi = &sddevinfo[ii->ii_type]; 74653901Smckusick if ((p = sdi->other_pages) == NULL) 74753901Smckusick return (0); 74853901Smckusick 74953901Smckusick /* 75053901Smckusick * set other parameters 75153901Smckusick */ 75253901Smckusick while (page = *p++) { 75353901Smckusick retrycnt = 0; 75453901Smckusick loop_other_pages: 75553901Smckusick bzero((caddr_t)sdtmp, 4); 75653901Smckusick length = *(page + 1) + 2; 75753901Smckusick bcopy(page, &sdtmp[4], length); 75853901Smckusick if (retrycnt++ > MAXPROBERETRY) 75953901Smckusick return (-1); 76053901Smckusick 76153901Smckusick scop_mselect(ii->ii_intr, sc, ii->ii_slave, SCSI_INTDIS, 76253901Smckusick (SDM_PF<<24) + length +4, (caddr_t)sdtmp); 76353901Smckusick sc->sc_tstatus &= TGSTMASK; 76453901Smckusick if ((sc->sc_istatus != INST_EP) 76553901Smckusick || (sc->sc_tstatus != TGST_GOOD)) { 76653901Smckusick struct sc_extnd *sce; 76753901Smckusick 76853901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 76953901Smckusick scop_rsense(ii->ii_intr, sc, ii->ii_slave, SCSI_INTDIS, 77053901Smckusick RSEN_CNT, (caddr_t)sce); 77153901Smckusick switch (sce->sce_skey) { 77253901Smckusick 77353901Smckusick case 0x00: 77453901Smckusick case 0x02: 77553901Smckusick case 0x04: 77653901Smckusick case 0x06: 77753901Smckusick DELAY(D100MSEC); /* 100 ms. */ 77853901Smckusick goto loop_other_pages; 77953901Smckusick 78053901Smckusick default: 78153901Smckusick return (-1); 78253901Smckusick } 78353901Smckusick } 78453901Smckusick } 78553901Smckusick 78653901Smckusick if (sdi->firm_flags & FIRM_CACHE_ON) 78753901Smckusick sdc_softc[ii->ii_ctlr].sdc_firmware |= SDCFW_CACHE; 78853901Smckusick else 78953901Smckusick sdc_softc[ii->ii_ctlr].sdc_firmware &= ~SDCFW_CACHE; 79053901Smckusick 79153901Smckusick return (1); 79253901Smckusick } 79353901Smckusick 79453901Smckusick static 79553901Smckusick sd_err_rcv(ii, sc) 79653901Smckusick register struct iop/**/_device *ii; 79753901Smckusick register struct scsi *sc; 79853901Smckusick { 79953901Smckusick register struct sdc_softc *sdc; 80053901Smckusick register int intr; 80153901Smckusick register int slave; 80253901Smckusick register int len; 80353901Smckusick struct sc_extnd *sce; 80453901Smckusick struct sdd_softc *sdd; 80553901Smckusick struct sddevinfo *sdi; 80653901Smckusick int retrycnt; 80753901Smckusick char *erp_page; 80853901Smckusick 80953901Smckusick intr = ii->ii_intr; 81053901Smckusick slave = ii->ii_slave; 81153901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 81253901Smckusick sdd = &sdd_softc[ii->ii_unit]; 81353901Smckusick sdi = &sddevinfo[ii->ii_type]; 81453901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 81553901Smckusick 81653901Smckusick /* 81753901Smckusick * set Default DISK sector size 81853901Smckusick */ 81953901Smckusick if (sdd->sdd_sectsize == 0) 82053901Smckusick sdd->sdd_sectsize = DEV_BSIZE; 82153901Smckusick 82253901Smckusick 82353901Smckusick if (sdi->ERP_page == NULL) { 82453901Smckusick /* 82553901Smckusick * use default error recovery parameters 82653901Smckusick */ 82753901Smckusick sdc->sdc_firmware |= SDCFW_DEFMODE; 82853901Smckusick return (0); 82953901Smckusick } 83053901Smckusick 83153901Smckusick if (sdi->firm_flags & FIRM_AWRE) 83253901Smckusick sdc->sdc_firmware |= SDCFW_AWRE; 83353901Smckusick if (sdi->firm_flags & FIRM_ARRE) 83453901Smckusick sdc->sdc_firmware |= SDCFW_ARRE; 83553901Smckusick /* 83653901Smckusick * set ERROR RECOVERY PARAMETERS 83753901Smckusick */ 83853901Smckusick loop_err_rcv: 83953901Smckusick bzero((caddr_t)sdtmp, 4); 84053901Smckusick erp_page = sdi->ERP_page; 84153901Smckusick len = *(erp_page + 1) + 2; 84253901Smckusick bcopy(erp_page, &sdtmp[4], len); 84353901Smckusick 84453901Smckusick scop_mselect(intr, sc, slave, SCSI_INTDIS, 84553901Smckusick (SDM_PF<<24) + len +4, (caddr_t)sdtmp); 84653901Smckusick sc->sc_tstatus &= TGSTMASK; 84753901Smckusick if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) { 84853901Smckusick if (sc->sc_tstatus == TGST_CC) { 84953901Smckusick bzero((caddr_t)sce, RSEN_CNT); 85053901Smckusick scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT, 85153901Smckusick (caddr_t)sce); 85253901Smckusick if (sce->sce_sdecode == 0x2a) { 85353901Smckusick /* mode select parameter changed */ 85453901Smckusick goto ercv_done; 85553901Smckusick } else if (sce->sce_skey == 0x6) { 85653901Smckusick /* unit attention */ 85753901Smckusick goto loop_err_rcv; 85853901Smckusick } 85953901Smckusick } 86053901Smckusick /* 86153901Smckusick * use default ERROR RECOVERY mode 86253901Smckusick */ 86353901Smckusick sdc->sdc_firmware |= SDCFW_DEFMODE; 86453901Smckusick sdc->sdc_firmware &= ~(SDCFW_AWRE|SDCFW_ARRE); 86553901Smckusick } 86653901Smckusick 86753901Smckusick ercv_done: 86853901Smckusick 86953901Smckusick return (1); 87053901Smckusick } 87153901Smckusick 87253901Smckusick static 87353901Smckusick sd_synctr_on(ii, sc) 87453901Smckusick register struct iop/**/_device *ii; 87553901Smckusick register struct scsi *sc; 87653901Smckusick { 87753901Smckusick register struct sddevinfo *sdi; 87853901Smckusick register struct sync_param *syncp; 87953901Smckusick 88053901Smckusick sdi = &sddevinfo[ii->ii_type]; 88153901Smckusick 88253901Smckusick if (sdi->firm_flags & FIRM_SYNCTR) { 88353901Smckusick scinit(sc, ii->ii_slave, DEV_BSIZE); 88453901Smckusick sc->sc_opcode = SCOP_TST; 88553901Smckusick sc->sc_message = MSG_EXTND; /* extended message */ 88653901Smckusick sc->sc_param[0] = MSG_EXTND; 88753901Smckusick sc->sc_param[1] = 0x03; 88853901Smckusick sc->sc_param[2] = 0x01; /* synchronous transfer */ 88953901Smckusick sc->sc_param[3] = sdi->tr_period; /* transfer period */ 89053901Smckusick sc->sc_param[4] = sdi->tr_offset; /* REQ offset */ 89153901Smckusick 89253901Smckusick if (sdc_softc[ii->ii_ctlr].sdc_firmware & SDCFW_CACHE) 89353901Smckusick sc->sc_tstatus |= TS_CONTR_ON; /* contiguous TR ON */ 89453901Smckusick else 89553901Smckusick sc->sc_tstatus |= TS_CONTR_OFF; /* contiguous TR OFF */ 89653901Smckusick 89753901Smckusick #ifdef news1800 89853901Smckusick if (scsi_berr_bug() != 0) { 89953901Smckusick sc->sc_tstatus &= ~TS_CONTR_ON; 90053901Smckusick sc->sc_tstatus |= TS_CONTR_OFF; 90153901Smckusick } 90253901Smckusick #endif 90353901Smckusick 90453901Smckusick if (sc->sc_tstatus & TS_CONTR_OFF) 90553901Smckusick sdc_softc[ii->ii_ctlr].sdc_firmware &= ~SDCFW_CONTR; 90653901Smckusick else 90753901Smckusick sdc_softc[ii->ii_ctlr].sdc_firmware |= SDCFW_CONTR; 90853901Smckusick 90953901Smckusick sc_go(ii->ii_intr, sc, SCSI_INTDIS); 91053901Smckusick 91153901Smckusick syncp = &sd_sync_param[ii->ii_unit]; 91253901Smckusick syncp->tr_period = sc->sc_param[3]; 91353901Smckusick syncp->tr_offset = sc->sc_param[4]; 91453901Smckusick if (sc->sc_param[4]) 91553901Smckusick sdd_softc[ii->ii_unit].sdd_flags |= SDDF_SYNCTR; 91653901Smckusick } 91753901Smckusick } 91853901Smckusick 91953901Smckusick 92053901Smckusick sdattach(ii) 92153901Smckusick register struct iop/**/_device *ii; 92253901Smckusick { 92353901Smckusick register int unit; 92453901Smckusick register int i; 92553901Smckusick struct sdc_softc *sdc; 92653901Smckusick struct sdd_softc *sdd; 92753901Smckusick int dummy; 92853901Smckusick 92953901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 93053901Smckusick sdc->sdc_timeo = 60; /* timeout 60 sec */ 93153901Smckusick 93253901Smckusick unit = ii->ii_unit; 93353901Smckusick sdd = &sdd_softc[unit]; 93453901Smckusick sdd->sdd_stoptime = OD_STOPTIME; /* REMOVABLE MEDIA */ 93553901Smckusick sdd->sdd_start = -2; 93653901Smckusick 93753901Smckusick sdmaptype(ii); 93853901Smckusick 93953901Smckusick if (sdwstart == 0) { 94053901Smckusick sdwstart++; 94153901Smckusick timeout(sdwatch, (caddr_t)0, hz); 94253901Smckusick timeout(sdstop, (caddr_t)0, hz); 94353901Smckusick } 94453901Smckusick 94553901Smckusick #ifdef NEWSOS4 94653901Smckusick /* 94753901Smckusick * Do setup commands 94853901Smckusick */ 94953901Smckusick if (sd_setup_cmds(ii, get_scsi(ii->ii_intr)) < 0) 95053901Smckusick printf("sd%d: setup failure\n", ii->ii_unit); 95153901Smckusick #endif 95253901Smckusick 95353901Smckusick /* 95453901Smckusick * initialize open flag 95553901Smckusick */ 95653901Smckusick for (i = 0; i < PNUM; i++) { 95753901Smckusick sd_b_openf[unit][i] = 0; 95853901Smckusick sd_c_openf[unit][i] = 0; 95953901Smckusick } 96053901Smckusick 96153901Smckusick if (re_init_done > 0) 96253901Smckusick return; 96353901Smckusick 96453901Smckusick if (sdc->sdc_firmware & SDCFW_HD) { 96553901Smckusick /* 96653901Smckusick * If device is Hard Disk, 96753901Smckusick * then get partition information. 96853901Smckusick */ 96953901Smckusick sdrpartinfo(ii); 97053901Smckusick dummy = DEV_BSIZE * sdstdrv[unit].rps * sdstdrv[unit].nsect; 97153901Smckusick } else 97253901Smckusick dummy = DEV_BSIZE * 40 * 31; 97353901Smckusick 97453901Smckusick if (ii->ii_dk >= 0 && dummy) 97553901Smckusick dk_wpms[ii->ii_dk] = dummy / (2 * 1000000); 97653901Smckusick } 97753901Smckusick 97853901Smckusick sdmaptype(ii) 97953901Smckusick register struct iop/**/_device *ii; 98053901Smckusick { 98153901Smckusick printf("sd%d: %s\n", ii->ii_unit, sddevinfo[ii->ii_type].call_name); 98253901Smckusick } 98353901Smckusick 98453901Smckusick int sd_b_major = -1; 98553901Smckusick 98653901Smckusick sd_b_open(dev, flag) 98753901Smckusick dev_t dev; 98853901Smckusick int flag; 98953901Smckusick { 99053901Smckusick sd_b_major = major(dev); 99153901Smckusick return (_sdopen(dev, flag, S_IFBLK)); 99253901Smckusick } 99353901Smckusick 99453901Smckusick int sd_c_major = -1; 99553901Smckusick 99653901Smckusick sd_c_open(dev, flag) 99753901Smckusick dev_t dev; 99853901Smckusick int flag; 99953901Smckusick { 100053901Smckusick sd_c_major = major(dev); 100153901Smckusick return (_sdopen(dev, flag, S_IFCHR)); 100253901Smckusick } 100353901Smckusick 100453901Smckusick _sdopen(dev, flag, fmt) 100553901Smckusick register dev_t dev; 100653901Smckusick int flag; 100753901Smckusick int fmt; 100853901Smckusick { 100953901Smckusick register struct iop/**/_device *ii; 101053901Smckusick register struct sdd_softc *sdd; 101153901Smckusick register struct sdc_softc *sdc; 101253901Smckusick register struct sddevinfo *sdi; 101353901Smckusick register int unit; 101453901Smckusick register int i; 101553901Smckusick u_char *sdopfp; 101653901Smckusick u_char old_sdopf; 101753901Smckusick int media_changed; 101853901Smckusick int s; 101953901Smckusick int stat; 102053901Smckusick struct scsi uscsi; 102153901Smckusick 102253901Smckusick unit = dev2unit(dev); 102353901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) 102453901Smckusick return (ENXIO); 102553901Smckusick 102653901Smckusick sdd = &sdd_softc[unit]; 102753901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 102853901Smckusick sdi = &sddevinfo[ii->ii_type]; 102953901Smckusick 103053901Smckusick if (sdd->sdd_flags & SDDF_XUSE) 103153901Smckusick return (EBUSY); 103253901Smckusick 103353901Smckusick /* 103453901Smckusick * LOCK while sdstop() running. 103553901Smckusick */ 103653901Smckusick s = splclock(); 103753901Smckusick while (sdc->sdc_state & SDCS_SCUNLOCK) { 103853901Smckusick sdc->sdc_state |= SDCS_OPEN_WAIT; 103953901Smckusick sleep((caddr_t)sdc, PRIBIO); 104053901Smckusick } 104153901Smckusick splx(s); 104253901Smckusick 104353901Smckusick /* 104453901Smckusick * LOCK sdtmp buffer 104553901Smckusick */ 104653901Smckusick s = splclock(); 104753901Smckusick while (sdtmp_stat & B_BUSY) { 104853901Smckusick sdtmp_stat |= B_WANTED; 104953901Smckusick sleep((caddr_t)sdtmp, PRIBIO); 105053901Smckusick } 105153901Smckusick sdtmp_stat |= B_BUSY; 105253901Smckusick splx(s); 105353901Smckusick sdd->sdd_flags |= SDDF_GETTMP; 105453901Smckusick 105553901Smckusick if ((fmt & S_IFMT) == S_IFBLK) 105653901Smckusick sdopfp = &sd_b_openf[unit][dev2part(dev)]; 105753901Smckusick else 105853901Smckusick sdopfp = &sd_c_openf[unit][dev2part(dev)]; 105953901Smckusick old_sdopf = *sdopfp; 106053901Smckusick if (old_sdopf <= 1) 106153901Smckusick *sdopfp += 1; /* 1: 1st open (ONLY_ONE) */ 106253901Smckusick /* 2: already opened */ 106353901Smckusick stat = 0; 106453901Smckusick media_changed = 0; 106553901Smckusick 106653901Smckusick /* 106753901Smckusick * From here on until pre_open_done is only for removable devices 106853901Smckusick */ 106953901Smckusick if ((sdc->sdc_firmware & SDCFW_RMB) == 0) 107053901Smckusick goto pre_open_done; 107153901Smckusick 107253901Smckusick if ((minor(dev) & 0x80) || (dev == rootdev)) 107353901Smckusick sdd->sdd_stoptime = 0x7fffffff; /*XXX*/ 107453901Smckusick 107553901Smckusick /* 107653901Smckusick * Start Unit 107753901Smckusick */ 107853901Smckusick s = splclock(); /* inhibit clock interrupt */ 107953901Smckusick i = sdd->sdd_start; 108053901Smckusick sdd->sdd_start = sdd->sdd_stoptime; 108153901Smckusick splx(s); 108253901Smckusick if (i <= 0) { 108353901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 108453901Smckusick uscsi.sc_opcode = SCOP_STST; 108553901Smckusick uscsi.sc_count = SDSS_START; 108653901Smckusick 108753901Smckusick if (sdcmd(dev, &uscsi)) { 108853901Smckusick sdd->sdd_start = i; 108953901Smckusick if ((flag & FWRITE) == 0) 109053901Smckusick goto sdopen_setup; 109153901Smckusick stat = EIO; 109253901Smckusick goto pre_open_done; 109353901Smckusick } 109453901Smckusick } 109553901Smckusick 109653901Smckusick /* 109753901Smckusick * prevent medium removal 109853901Smckusick */ 109953901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 110053901Smckusick uscsi.sc_opcode = SCOP_MEDRMV; 110153901Smckusick uscsi.sc_count = SDRMV_PREV; 110253901Smckusick if (sdcmd(dev, &uscsi)) { 110353901Smckusick stat = EIO; 110453901Smckusick goto pre_open_done; 110553901Smckusick } 110653901Smckusick sdd->sdd_flags |= SDDF_INHRMV; 110753901Smckusick 110853901Smckusick sdopen_setup: 110953901Smckusick if ((sdd->sdd_flags & SDDF_SAMEDSK) == SDDF_DSKCHGD) { 111053901Smckusick sdd->sdd_flags |= SDDF_SAMEDSK; 111153901Smckusick media_changed = 1; 111253901Smckusick 111353901Smckusick /* 111453901Smckusick * From here on until mo_check_done is only for MO device 111553901Smckusick */ 111653901Smckusick if ((sdc->sdc_firmware & SDCFW_MO) == 0) 111753901Smckusick goto mo_check_done; 111853901Smckusick 111953901Smckusick /* 112053901Smckusick * Mode Sense 112153901Smckusick */ 112253901Smckusick bzero(sdtmp, 36); 112353901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 112453901Smckusick uscsi.sc_cpoint = sdtmp; 112553901Smckusick uscsi.sc_ctrnscnt = 36; 112653901Smckusick uscsi.sc_opcode = SCOP_MSENSE; 112753901Smckusick uscsi.sc_lad = (SDM_PF << 16)|((SDM_PC_CUR|SDM_PCODE_ALL) << 8); 112853901Smckusick uscsi.sc_count = 36; 112953901Smckusick 113053901Smckusick if (sdcmd(dev, &uscsi) == 0) { 113153901Smckusick /* 113253901Smckusick * check Write Protect mode 113353901Smckusick */ 113453901Smckusick if (sdtmp[2] & 0x80) 113553901Smckusick sdd->sdd_flags |= SDDF_WPROTECT; 113653901Smckusick else 113753901Smckusick sdd->sdd_flags &= ~SDDF_WPROTECT; 113853901Smckusick /* 113953901Smckusick * check Format Mode 114053901Smckusick */ 114153901Smckusick if (sdtmp[26] == 2) { 114253901Smckusick ii->ii_type = search_index(SMO_S501); 114353901Smckusick if (mo_disp_format) 114453901Smckusick printf("sd%d: format mode 2 (original format)\n", unit); 114553901Smckusick } else if (sdtmp[26] == 3) { 114653901Smckusick int spare; 114753901Smckusick 114853901Smckusick spare = *(short *)&sdtmp[32]; 114953901Smckusick if (spare == 2048) 115053901Smckusick ii->ii_type = 115153901Smckusick search_index(SMO_S501_ISO2); 115253901Smckusick else 115353901Smckusick ii->ii_type = 115453901Smckusick search_index(SMO_S501_ISO); 115553901Smckusick if (mo_disp_format) 115653901Smckusick printf("sd%d: format mode 3 (ISO format) spare=%d\n", unit, spare); 115753901Smckusick } else { 115853901Smckusick sdd->sdd_flags |= SDDF_NONFMT; 115953901Smckusick if (mo_disp_format) 116053901Smckusick printf("sd%d: Non format\n", unit); 116153901Smckusick } 116253901Smckusick sdi = &sddevinfo[ii->ii_type]; 116353901Smckusick } 116453901Smckusick 116553901Smckusick /* 116653901Smckusick * Mode Select 116753901Smckusick * Error Recovery Parameters set 116853901Smckusick */ 116953901Smckusick i = *(sdi->ERP_page +1) + 2; /* page length */ 117053901Smckusick bzero(sdtmp, i + 4); 117153901Smckusick bcopy(sdi->ERP_page, (caddr_t)&sdtmp[4], i); 117253901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 117353901Smckusick uscsi.sc_cpoint = sdtmp; 117453901Smckusick uscsi.sc_ctrnscnt = i + 4; 117553901Smckusick uscsi.sc_opcode = SCOP_MSELECT; 117653901Smckusick uscsi.sc_lad = (SDM_PF << 16); 117753901Smckusick uscsi.sc_count = i + 4; 117853901Smckusick 117953901Smckusick (void) sdcmd(dev, &uscsi); 118053901Smckusick 118153901Smckusick /* 118253901Smckusick * Read Grown Defect list 118353901Smckusick */ 118453901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 118553901Smckusick uscsi.sc_cpoint = sdtmp; 118653901Smckusick uscsi.sc_ctrnscnt = 4; 118753901Smckusick uscsi.sc_opcode = SCOP_RDL; 118853901Smckusick uscsi.sc_cdb.un_type1.t1_ladhi = (SDDL_GLIST|SDDL_PHYSFMT) << 8; 118953901Smckusick uscsi.sc_cdb.un_type1.t1_p3 = 4; 119053901Smckusick 119153901Smckusick (void) sdcmd(dev, &uscsi); 119253901Smckusick i = *(short *)&sdtmp[2] / 8; 119353901Smckusick if (i > (1024*9/10)) 119453901Smckusick printf("sd%d: WARNING: DEFECT SPARE LOCATION < 10%\n", 119553901Smckusick unit); 119653901Smckusick mo_check_done: 119753901Smckusick /* 119853901Smckusick * Read Capacity 119953901Smckusick */ 120053901Smckusick bzero((caddr_t)sdtmp, 8); 120153901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 120253901Smckusick uscsi.sc_cpoint = sdtmp; 120353901Smckusick uscsi.sc_ctrnscnt = 8; 120453901Smckusick uscsi.sc_opcode = SCOP_RCAP; 120553901Smckusick 120653901Smckusick (void) sdcmd(dev, &uscsi); 120753901Smckusick sdd->sdd_nsect = *(int *)&sdtmp[0] + 1; 120853901Smckusick sdd->sdd_sectsize = *(int *)&sdtmp[4]; 120953901Smckusick 121053901Smckusick if ((sdd->sdd_sectsize != DEV_BSIZE) 121153901Smckusick && (sdd->sdd_sectsize != SDBSIZE1K)) 121253901Smckusick sdd->sdd_sectsize = DEV_BSIZE; 121353901Smckusick } 121453901Smckusick 121553901Smckusick if ((sdd->sdd_flags & SDDF_WPROTECT) && (flag & FWRITE)) 121653901Smckusick stat = EROFS; 121753901Smckusick 121853901Smckusick pre_open_done: 121953901Smckusick 122053901Smckusick if (stat == 0) { 122153901Smckusick if ((isalone(unit) == ONLY_ONE) || media_changed) { 122253901Smckusick /* 122353901Smckusick * read partition information from sector zero. 122453901Smckusick */ 122553901Smckusick sdrpartinfo(ii); 122653901Smckusick if (ii->ii_dk >= 0) { 122753901Smckusick dk_wpms[ii->ii_dk] = 122853901Smckusick sdd->sdd_sectsize * sdstdrv[unit].rps 122953901Smckusick * sdstdrv[unit].nsect / (2 * 1000000); 123053901Smckusick } 123153901Smckusick } 123253901Smckusick } else { 123353901Smckusick /* 123453901Smckusick * open error 123553901Smckusick */ 123653901Smckusick *sdopfp = old_sdopf; 123753901Smckusick if ((sdd->sdd_flags & SDDF_INHRMV) && (isalone(unit) == 0)) { 123853901Smckusick sdd->sdd_flags &= ~SDDF_INHRMV; 123953901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 124053901Smckusick uscsi.sc_opcode = SCOP_MEDRMV; 124153901Smckusick uscsi.sc_count = SDRMV_ALLOW; 124253901Smckusick (void) sdcmd(dev, &uscsi); 124353901Smckusick } 124453901Smckusick } 124553901Smckusick 124653901Smckusick /* 124753901Smckusick * UNLOCK open 124853901Smckusick */ 124953901Smckusick s = splclock(); 125053901Smckusick sdd->sdd_flags &= ~SDDF_GETTMP; 125153901Smckusick if (sdtmp_stat & B_WANTED) 125253901Smckusick wakeup((caddr_t)sdtmp); 125353901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 125453901Smckusick splx(s); 125553901Smckusick return (stat); 125653901Smckusick } 125753901Smckusick 125853901Smckusick int sd_access_check_on; /* Common flags for sd_access_check() */ 125953901Smckusick 126053901Smckusick sd_access_check(bp) 126153901Smckusick register struct buf *bp; 126253901Smckusick { 126353901Smckusick register struct iop/**/_device *ii; 126453901Smckusick register struct sdd_softc *sdd; 126553901Smckusick int unit; 126653901Smckusick int check_part; 126753901Smckusick int limit; 126853901Smckusick int over; 126953901Smckusick register struct size *sizes; 127053901Smckusick register int lba; /* logical block address */ 127153901Smckusick register int sz; 127253901Smckusick register int i; 127353901Smckusick 127453901Smckusick check_part = 0; 127553901Smckusick unit = dev2unit(bp->b_dev); 127653901Smckusick ii = sddinfo[unit]; 127753901Smckusick sdd = &sdd_softc[unit]; 127853901Smckusick sizes = sdstdrv[unit].sizes; 127953901Smckusick 128053901Smckusick lba = sizes[dev2part(bp->b_dev)].sd_blkoff + dkblock(bp); 128153901Smckusick sz = howmany(bp->b_bcount, sdd->sdd_sectsize); 128253901Smckusick 128353901Smckusick /* 128453901Smckusick * When block device is used, 128553901Smckusick * inhibit raw device write operation. 128653901Smckusick */ 128753901Smckusick if ((major(bp->b_dev) == sd_c_major) /* RAW I/O */ 128853901Smckusick && ((bp->b_flags & B_READ) == 0) /* WRITE */ 128953901Smckusick && ((ii->ii_flags & SD_F_ENW) == 0) /* INHIBIT */ 129053901Smckusick && ((sd_access_check_on & SD_F_ENW) == 0)) { 129153901Smckusick 129253901Smckusick for (i = 0; i < PNUM; i++) { 129353901Smckusick if (sd_b_openf[unit][i] == 0) 129453901Smckusick continue; 129553901Smckusick /* 129653901Smckusick * |----|========|---|======|-------| 129753901Smckusick * 1 |---+++--------------------------| CUT OFF 129853901Smckusick * 2 |---++++++++++++-----------------| CUT OFF 129953901Smckusick * 3 |---++++++++++++++++-------------| CUT OFF 130053901Smckusick * 4 |---++++++++++++++++++++++++-----| CUT OFF 130153901Smckusick * 5 |-------+++----------------------| ERROR 130253901Smckusick * 6 |------------+++-----------------| ERROR 130353901Smckusick * 7 |------------+++++++-------------| ERROR 130453901Smckusick * 8 |------------+++++++++++++++-----| ERROR 130553901Smckusick */ 130653901Smckusick if ((lba < (sizes[i].sd_blkoff + sizes[i].sd_nblocks)) 130753901Smckusick && ((lba + sz) > sizes[i].sd_blkoff)) 130853901Smckusick check_part |= (1 << i); 130953901Smckusick } 131053901Smckusick } 131153901Smckusick 131253901Smckusick if (check_part) { 131353901Smckusick limit = 0x7fffffff; /* XXX */ 131453901Smckusick for (i = 0; i < PNUM; i++) { 131553901Smckusick if ((check_part & (1 << i)) == 0) 131653901Smckusick continue; 131753901Smckusick 131853901Smckusick if (lba >= sizes[i].sd_blkoff) { 131953901Smckusick bp->b_flags |= B_ERROR; 132053901Smckusick bp->b_error = EIO; 132153901Smckusick bp->b_resid = bp->b_bcount; 132253901Smckusick 132353901Smckusick printf("sd%d%c: RAW DEVICE WRITE PROTECTED: ", 132453901Smckusick unit, pname[dev2part(bp->b_dev)]); 132553901Smckusick printf("sn = 0x%x(%d), off = 0x%x(%d)\n", 132653901Smckusick dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize, 132753901Smckusick dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize, 132853901Smckusick sizes[dev2part(bp->b_dev)].sd_blkoff, 132953901Smckusick sizes[dev2part(bp->b_dev)].sd_blkoff); 133053901Smckusick 133153901Smckusick return (-1); 133253901Smckusick } 133353901Smckusick 133453901Smckusick if (sizes[i].sd_blkoff < limit) 133553901Smckusick limit = sizes[i].sd_blkoff; 133653901Smckusick } 133753901Smckusick } else { 133853901Smckusick limit = sizes[dev2part(bp->b_dev)].sd_blkoff 133953901Smckusick + sizes[dev2part(bp->b_dev)].sd_nblocks; 134053901Smckusick } 134153901Smckusick 134253901Smckusick if ((over = (lba + sz) - limit) > 0) { 134353901Smckusick /* 134453901Smckusick * Logical Block Address is outside the valid area. 134553901Smckusick */ 134653901Smckusick if (((ii->ii_flags & SD_F_EOLBA) != 0) 134753901Smckusick || ((sd_access_check_on & SD_F_EOLBA) != 0)) { 134853901Smckusick /* 134953901Smckusick * error if outside LBA 135053901Smckusick */ 135153901Smckusick return(-1); 135253901Smckusick } 135353901Smckusick bp->b_resid = bp->b_bcount - (sz - over) * sdd->sdd_sectsize; 135453901Smckusick if (bp->b_resid >= bp->b_bcount) { 135553901Smckusick bp->b_resid = bp->b_bcount; 135653901Smckusick return(-1); 135753901Smckusick } 135853901Smckusick } 135953901Smckusick 136053901Smckusick return (0); 136153901Smckusick } 136253901Smckusick 136353901Smckusick sd_b_close(dev, flag) 136453901Smckusick dev_t dev; 136553901Smckusick int flag; 136653901Smckusick { 136753901Smckusick return (_sdclose(dev, flag, S_IFBLK)); 136853901Smckusick } 136953901Smckusick 137053901Smckusick sd_c_close(dev, flag) 137153901Smckusick dev_t dev; 137253901Smckusick int flag; 137353901Smckusick { 137453901Smckusick return (_sdclose(dev, flag, S_IFCHR)); 137553901Smckusick } 137653901Smckusick 137753901Smckusick _sdclose(dev, flag, fmt) 137853901Smckusick register dev_t dev; 137953901Smckusick int flag; 138053901Smckusick int fmt; 138153901Smckusick { 138253901Smckusick register struct iop/**/_device *ii; 138353901Smckusick register struct sdd_softc *sdd; 138453901Smckusick register int unit; 138553901Smckusick struct sdc_softc *sdc; 138653901Smckusick struct scsi uscsi; 138753901Smckusick struct sc_extnd *sce; 138853901Smckusick 138953901Smckusick unit = dev2unit(dev); 139053901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) 139153901Smckusick return (ENXIO); 139253901Smckusick 139353901Smckusick sdd = &sdd_softc[unit]; 139453901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 139553901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 139653901Smckusick 139753901Smckusick /* 139853901Smckusick * still remain jobs 139953901Smckusick * sleep about 10ms -> 1sec 140053901Smckusick */ 140153901Smckusick while (ii->ii_mi->im_tab.b_actf != NULL) 140253901Smckusick sleep((caddr_t)&lbolt, PRIBIO); 140353901Smckusick 140453901Smckusick if ((fmt & S_IFMT) == S_IFBLK) 140553901Smckusick sd_b_openf[unit][dev2part(dev)] = 0; 140653901Smckusick else 140753901Smckusick sd_c_openf[unit][dev2part(dev)] = 0; 140853901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 140953901Smckusick 141053901Smckusick if ((sdc->sdc_firmware & SDCFW_RMB) && (isalone(unit) == 0)) { 141153901Smckusick sdd->sdd_flags &= ~SDDF_INHRMV; 141253901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 141353901Smckusick uscsi.sc_opcode = SCOP_MEDRMV; 141453901Smckusick uscsi.sc_count = SDRMV_ALLOW; 141553901Smckusick (void) sdcmd(dev, &uscsi); 141653901Smckusick } 141753901Smckusick return (0); 141853901Smckusick } 141953901Smckusick 142053901Smckusick sdcmd(dev, usc) 142153901Smckusick dev_t dev; 142253901Smckusick struct scsi *usc; 142353901Smckusick { 142453901Smckusick register struct buf *bp; 142553901Smckusick register struct scsi *ksc; 142653901Smckusick register u_char *point; 142753901Smckusick register int unit; 142853901Smckusick int error; 142953901Smckusick int s; 143053901Smckusick int cnt; 143153901Smckusick 143253901Smckusick if (usc == 0) 143353901Smckusick return (ENXIO); 143453901Smckusick 143553901Smckusick error = 0; 143653901Smckusick unit = dev2unit(dev); 143753901Smckusick bp = &csdbuf[unit]; 143853901Smckusick 143953901Smckusick /* 144053901Smckusick * LOCK csdbuf 144153901Smckusick */ 144253901Smckusick s = splclock(); 144353901Smckusick while (bp->b_flags & B_BUSY) { 144453901Smckusick bp->b_flags |= B_WANTED; 144553901Smckusick sleep((caddr_t)bp, PRIBIO); 144653901Smckusick } 144753901Smckusick bzero((caddr_t)bp, sizeof(struct buf)); 144853901Smckusick bp->b_flags = B_BUSY|B_READ; 144953901Smckusick splx(s); 145053901Smckusick 145153901Smckusick ksc = &kernscsi[unit]; 145253901Smckusick bcopy((caddr_t)usc, (caddr_t)ksc, sizeof(struct scsi)); 145353901Smckusick /* 145453901Smckusick * setup command buffer 145553901Smckusick */ 145653901Smckusick bp->b_dev = dev; 145753901Smckusick bp->b_proc = curproc; 145853901Smckusick cnt = ksc->sc_ctrnscnt; 145953901Smckusick bp->b_bcount = cnt; 146053901Smckusick 146153901Smckusick point = ksc->sc_cpoint; 146253901Smckusick bp->b_un.b_addr = (caddr_t)point; 146353901Smckusick if (cnt > 0) { 146453901Smckusick if (point == NULL) { 146553901Smckusick ksc->sc_cpoint = point = get_scsi(unit)->sc_param; 146653901Smckusick if (cnt > 20) { 146753901Smckusick error = EFAULT; 146853901Smckusick goto done; 146953901Smckusick } 147053901Smckusick } 147153901Smckusick if (point < (u_char *)KERNBASE) { 147253901Smckusick if (useracc(point, cnt, B_WRITE) == NULL) { 147353901Smckusick error = EFAULT; 147453901Smckusick goto done; 147553901Smckusick } 147653901Smckusick curproc->p_flag |= SPHYSIO; 147753901Smckusick vslock(point, cnt); 147853901Smckusick bp->b_flags |= B_PHYS; 147953901Smckusick } 148053901Smckusick #ifndef mips 148153901Smckusick else { 148253901Smckusick if (kernacc(point, cnt, B_WRITE) == NULL) { 148353901Smckusick error = EFAULT; 148453901Smckusick goto done; 148553901Smckusick } 148653901Smckusick } 148753901Smckusick #endif 148853901Smckusick ksc->sc_tstatus = TS_MAPPED_PIO; /* XXX */ 148953901Smckusick } 149053901Smckusick 149153901Smckusick /* 149253901Smckusick * call strategy entry, and wait command done. 149353901Smckusick */ 149453901Smckusick sdstrategy(bp); 149553901Smckusick iowait(bp); 149653901Smckusick 149753901Smckusick if ((cnt > 0) && (point < (u_char *)KERNBASE)) { 149853901Smckusick vsunlock(point, cnt, B_READ); 149953901Smckusick curproc->p_flag &= ~SPHYSIO; 150053901Smckusick } 150153901Smckusick if ((bp->b_flags & B_ERROR) == 0) 150253901Smckusick error = 0; 150353901Smckusick else { 150453901Smckusick if (bp->b_error) 150553901Smckusick error = bp->b_error; 150653901Smckusick else 150753901Smckusick error = EIO; 150853901Smckusick } 150953901Smckusick bcopy((caddr_t)ksc, (caddr_t)usc, sizeof(struct scsi)); 151053901Smckusick 151153901Smckusick done: 151253901Smckusick /* 151353901Smckusick * UNLOCK csdbuf 151453901Smckusick */ 151553901Smckusick s = splclock(); 151653901Smckusick if (bp->b_flags & B_WANTED) 151753901Smckusick wakeup((caddr_t)bp); 151853901Smckusick bp->b_flags = 0; 151953901Smckusick splx(s); 152053901Smckusick return (error); 152153901Smckusick } 152253901Smckusick 152353901Smckusick /* 152453901Smckusick * read partition information from sector zero. 152553901Smckusick */ 152653901Smckusick sdrpartinfo(ii) 152753901Smckusick register struct iop/**/_device *ii; 152853901Smckusick { 152953901Smckusick register struct disklabel *dlp; 153053901Smckusick register struct sdst *hsp; 153153901Smckusick register struct sdst *st; 153253901Smckusick register int unit; 153353901Smckusick register int i; 153453901Smckusick struct firstsector *fsp; 153553901Smckusick struct sdc_softc *sdc; 153653901Smckusick struct sdd_softc *sdd; 153753901Smckusick struct sddevinfo *sdi; 153853901Smckusick #ifdef DISKINFO 153953901Smckusick struct diskinfo *dip; 154053901Smckusick #endif 154153901Smckusick struct scsi uscsi; 154253901Smckusick int s; 154353901Smckusick 154453901Smckusick sdi = &sddevinfo[ii->ii_type]; 154553901Smckusick unit = ii->ii_unit; 154653901Smckusick 154753901Smckusick sdd = &sdd_softc[unit]; 154853901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 154953901Smckusick 155053901Smckusick if ((sdd->sdd_flags & (SDDF_NONFMT|SDDF_FMTDONE)) == 0) { 155153901Smckusick register struct sc_rcap *scr = (struct sc_rcap *)sdtmp; 155253901Smckusick 155353901Smckusick sdd->sdd_flags |= SDDF_FMTDONE; 155453901Smckusick 155553901Smckusick bzero((caddr_t)sdtmp, 8); 155653901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 155753901Smckusick uscsi.sc_cpoint = (u_char *)scr; 155853901Smckusick uscsi.sc_ctrnscnt = 8; 155953901Smckusick uscsi.sc_opcode = SCOP_RCAP; 156053901Smckusick (void) sdcmd(unit << 3, &uscsi); 156153901Smckusick 156253901Smckusick sdd->sdd_nsect = scr->scr_nblock + 1; 156353901Smckusick sdd->sdd_sectsize = scr->scr_blocklen; 156453901Smckusick if (sdd->sdd_sectsize == 0) 156553901Smckusick sdd->sdd_sectsize = SDBSIZE1K; 156653901Smckusick } 156753901Smckusick 156853901Smckusick bzero(sdtmp, DEV_BSIZE); 156953901Smckusick 157053901Smckusick if ((sdd->sdd_flags & SDDF_NONFMT) == 0) { 157153901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 157253901Smckusick uscsi.sc_cpoint = sdtmp; 157353901Smckusick uscsi.sc_ctrnscnt = DEV_BSIZE; 157453901Smckusick uscsi.sc_opcode = SCOP_READ; 157553901Smckusick uscsi.sc_lad = 0; 157653901Smckusick uscsi.sc_count = 1; 157753901Smckusick 157853901Smckusick (void) sdcmd(unit << 3, &uscsi); 157953901Smckusick sdd->sdd_flags &= ~SDDF_SKIPCHECK; 158053901Smckusick } 158153901Smckusick 158253901Smckusick fsp = (struct firstsector *)sdtmp; 158353901Smckusick dlp = (struct disklabel *)(sdtmp + LABELOFFSET); 158453901Smckusick #ifdef DISKINFO 158553901Smckusick dip = &fsp->diskinfo; 158653901Smckusick #endif 158753901Smckusick 158853901Smckusick s = splclock(); 158953901Smckusick hsp = &sdstdrv[unit]; 159053901Smckusick bzero((caddr_t)hsp, sizeof (struct sdst)); 159153901Smckusick bzero(&sdlabel[unit], sizeof (struct disklabel)); 159253901Smckusick 159353901Smckusick if ((dlp->d_magic == DISKMAGIC) 159453901Smckusick && ((ii->ii_flags & SD_F_IGNLABEL) == 0)) { 159553901Smckusick sdlabel[unit] = *dlp; 159653901Smckusick disklabel2sdst(unit, dlp, hsp); 159753901Smckusick #ifdef DISKINFO 159853901Smckusick } else if ((dip->di_magic == DISKINFO_MAGIC) 159953901Smckusick && ((ii->ii_flags & SD_F_IGNLABEL) == 0)) { 160053901Smckusick diskinfo2sdst(unit, dip, hsp); 160153901Smckusick diskinfo2disklabel(unit, dip, &sdlabel[unit]); 160253901Smckusick #endif 160353901Smckusick } else { 160453901Smckusick if ((ii->ii_type == UNKNOWN_DISK) 160553901Smckusick || (sdi->sdstp->sizes == calc_disk_sizes)) { 160653901Smckusick /* 160753901Smckusick * If device is UNKNOWN PARTITION SIZE, 160853901Smckusick * calculate default partition from capacity. 160953901Smckusick */ 161053901Smckusick st = sdi->sdstp; 161153901Smckusick hsp->nsect = st->nsect; /* # sectors/track */ 161253901Smckusick hsp->ntrak = st->ntrak; /* # tracks/cylinder */ 161353901Smckusick hsp->nspc = st->nspc; /* # sectors/cylinder */ 161453901Smckusick hsp->ncyl = st->ncyl; /* # cylinders */ 161553901Smckusick hsp->rps = st->rps; /* # revolutions/sec */ 161653901Smckusick hsp->sizes = sdsizedrv[unit]; /* partition table */ 161753901Smckusick 161853901Smckusick sd_calcpart(ii, hsp->sizes, 161953901Smckusick sdd->sdd_nsect, sdd->sdd_sectsize); 162053901Smckusick sdst2disklabel(unit, hsp, &sdlabel[unit]); 162153901Smckusick } else { 162253901Smckusick /* 162353901Smckusick * If device is support disk, 162453901Smckusick * copy default partition from size table. 162553901Smckusick */ 162653901Smckusick st = sdi->sdstp; 162753901Smckusick 162853901Smckusick hsp->nsect = st->nsect; /* # sectors/track */ 162953901Smckusick hsp->ntrak = st->ntrak; /* # tracks/cylinder */ 163053901Smckusick hsp->nspc = st->nspc; /* # sectors/cylinder */ 163153901Smckusick hsp->ncyl = st->ncyl; /* # cylinders */ 163253901Smckusick hsp->rps = st->rps; /* # revolutions / second */ 163353901Smckusick hsp->sizes = sdsizedrv[unit]; /* partition table */ 163453901Smckusick 163553901Smckusick for (i = 0; i < PNUM; i++) { 163653901Smckusick hsp->sizes[i].sd_nblocks = st->sizes[i].sd_nblocks; 163753901Smckusick hsp->sizes[i].sd_blkoff = st->sizes[i].sd_blkoff; 163853901Smckusick } 163953901Smckusick sdst2disklabel(unit, hsp, &sdlabel[unit]); 164053901Smckusick } 164153901Smckusick } 164253901Smckusick 164353901Smckusick /* BEGIN XXX*/ 164453901Smckusick if (hsp->rps == 0) { 164553901Smckusick /* 164653901Smckusick * If device is support disk, 164753901Smckusick * copy default partition from size table. 164853901Smckusick */ 164953901Smckusick st = sdi->sdstp; 165053901Smckusick 165153901Smckusick hsp->nsect = st->nsect; /* # sectors/track */ 165253901Smckusick hsp->ntrak = st->ntrak; /* # tracks/cylinder */ 165353901Smckusick hsp->nspc = st->nspc; /* # sectors/cylinder */ 165453901Smckusick hsp->ncyl = st->ncyl; /* # cylinders */ 165553901Smckusick hsp->rps = st->rps; /* # revolutions / second */ 165653901Smckusick sdst2disklabel(unit, hsp, &sdlabel[unit]); 165753901Smckusick } 165853901Smckusick /* END XXX*/ 165953901Smckusick (void)splx(s); 166053901Smckusick } 166153901Smckusick 166253901Smckusick static char Warn_Part[] = "sd%d: PARTITION TABLE CHANGED\n"; 166353901Smckusick static char Pr_Part_Fmt[] = "sd%d%c: nblk=%d, off=%d\n"; 166453901Smckusick 166553901Smckusick #define stsz(N) st->sizes[(N)].sd_nblocks 166653901Smckusick #define stof(N) st->sizes[(N)].sd_blkoff 166753901Smckusick #define dlsz(N) dlp->d_partitions[(N)].p_size 166853901Smckusick #define dlof(N) dlp->d_partitions[(N)].p_offset 166953901Smckusick #define disz(N) dip->di_part[(N)].dp_nblocks 167053901Smckusick #define diof(N) dip->di_part[(N)].dp_blkoff 167153901Smckusick 167253901Smckusick #ifndef BBSIZE 167353901Smckusick #define BBSIZE 8192 167453901Smckusick #endif 167553901Smckusick 167653901Smckusick static 167753901Smckusick check_sdst(unit, st) 167853901Smckusick int unit; 167953901Smckusick struct sdst *st; 168053901Smckusick { 168153901Smckusick if (st->nsect == 0) { 168253901Smckusick st->nsect = 1; 168353901Smckusick printf("sd%d: nsect SHOULD BE != 0, 1 assumed\n", unit); 168453901Smckusick } 168553901Smckusick 168653901Smckusick if (st->rps == 0) { 168753901Smckusick st->rps = 60; 168853901Smckusick printf("sd%d: rps SHOULD BE != 0, 60 assumed\n", unit); 168953901Smckusick } 169053901Smckusick } 169153901Smckusick 169253901Smckusick static 169353901Smckusick disklabel2sdst(unit, dlp, st) 169453901Smckusick int unit; 169553901Smckusick register struct disklabel *dlp; 169653901Smckusick register struct sdst *st; 169753901Smckusick { 169853901Smckusick register int i; 169953901Smckusick int msg_header_printed; 170053901Smckusick 170153901Smckusick msg_header_printed = 0; 170253901Smckusick 170353901Smckusick st->nsect = dlp->d_nsectors; /* # sectors/track */ 170453901Smckusick st->ntrak = dlp->d_ntracks; /* # tracks/cylinder */ 170553901Smckusick st->nspc = dlp->d_secpercyl; /* # sectors/cylinder */ 170653901Smckusick st->ncyl = dlp->d_ncylinders; /* # cylinders */ 170753901Smckusick st->rps = dlp->d_rpm / 60; /* # revolutions / second */ 170853901Smckusick st->sizes = sdsizedrv[unit]; /* partition table */ 170953901Smckusick 171053901Smckusick check_sdst(unit, st); 171153901Smckusick 171253901Smckusick for (i = 0; i < PNUM; i++) { 171353901Smckusick if (msg_header_printed == 0) { 171453901Smckusick if (((stsz(i) != 0) || (stof(i) != 0)) 171553901Smckusick && ((stsz(i) != dlsz(i)) || (stof(i) != dlof(i)))) { 171653901Smckusick msg_header_printed = 1; 171753901Smckusick } 171853901Smckusick } 171953901Smckusick } 172053901Smckusick 172153901Smckusick for (i = 0; i < PNUM; i++) { 172253901Smckusick stsz(i) = dlsz(i); 172353901Smckusick stof(i) = dlof(i); 172453901Smckusick } 172553901Smckusick 172653901Smckusick if (msg_header_printed) { 172753901Smckusick printf(Warn_Part, unit); 172853901Smckusick for (i = 0; i < PNUM; i++) 172953901Smckusick printf(Pr_Part_Fmt, unit, pname[i], stsz(i), stof(i)); 173053901Smckusick } 173153901Smckusick } 173253901Smckusick 173353901Smckusick #ifdef DISKINFO 173453901Smckusick static 173553901Smckusick diskinfo2sdst(unit, dip, st) 173653901Smckusick int unit; 173753901Smckusick register struct diskinfo *dip; 173853901Smckusick register struct sdst *st; 173953901Smckusick { 174053901Smckusick register int i; 174153901Smckusick int msg_header_printed; 174253901Smckusick 174353901Smckusick msg_header_printed = 0; 174453901Smckusick 174553901Smckusick st->nsect = dip->di_dkst.dks_nsect; /* # sectors/track */ 174653901Smckusick st->ntrak = dip->di_dkst.dks_ntrak; /* # tracks/cylinder */ 174753901Smckusick st->nspc = dip->di_dkst.dks_nsect * dip->di_dkst.dks_ntrak; 174853901Smckusick /* # sectors/cylinder */ 174953901Smckusick st->ncyl = dip->di_dkst.dks_ncyl; /* # cylinders */ 175053901Smckusick st->rps = dip->di_dkst.dks_rps; /* # revolutions / second */ 175153901Smckusick st->sizes = sdsizedrv[unit]; /* partition table */ 175253901Smckusick 175353901Smckusick check_sdst(unit, st); 175453901Smckusick 175553901Smckusick for (i = 0; i < PNUM; i++) { 175653901Smckusick if (msg_header_printed == 0) { 175753901Smckusick if (((stsz(i) != 0) || (stof(i) != 0)) 175853901Smckusick && ((stsz(i) != disz(i)) || (stof(i) != diof(i)))) { 175953901Smckusick msg_header_printed = 1; 176053901Smckusick } 176153901Smckusick } 176253901Smckusick } 176353901Smckusick 176453901Smckusick for (i = 0; i < PNUM; i++) { 176553901Smckusick stsz(i) = disz(i); 176653901Smckusick stof(i) = diof(i); 176753901Smckusick } 176853901Smckusick 176953901Smckusick if (msg_header_printed) { 177053901Smckusick printf(Warn_Part, unit); 177153901Smckusick for (i = 0; i < PNUM; i++) 177253901Smckusick printf(Pr_Part_Fmt, unit, pname[i], stsz(i), stof(i)); 177353901Smckusick } 177453901Smckusick } 177553901Smckusick 177653901Smckusick static 177753901Smckusick diskinfo2disklabel(unit, dip, dlp) 177853901Smckusick int unit; 177953901Smckusick register struct diskinfo *dip; 178053901Smckusick register struct disklabel *dlp; 178153901Smckusick { 178253901Smckusick register int i; 178353901Smckusick 178453901Smckusick dlp->d_type = DTYPE_SCSI; /* drive type */ 178553901Smckusick dlp->d_secsize = sdd_softc[unit].sdd_sectsize; /* # of bytes per sector */ 178653901Smckusick dlp->d_nsectors = dip->di_dkst.dks_nsect; /* # sectors/track */ 178753901Smckusick dlp->d_ntracks = dip->di_dkst.dks_ntrak; /* # tracks/cylinder */ 178853901Smckusick dlp->d_ncylinders = dip->di_dkst.dks_ncyl; /* # cylinders */ 178953901Smckusick dlp->d_secpercyl = dip->di_dkst.dks_nsect * dip->di_dkst.dks_ntrak; 179053901Smckusick /* # sectors/cylinder */ 179153901Smckusick dlp->d_rpm = dip->di_dkst.dks_rps * 60; /* # revolutions / second */ 179253901Smckusick dlp->d_bbsize = BBSIZE; /*XXX*/ /* size of boot area at sn0, bytes */ 179353901Smckusick dlp->d_sbsize = SBSIZE; /*XXX*/ /* max size of fs superblock, bytes */ 179453901Smckusick 179553901Smckusick for (i = 0; i < PNUM; i++) { 179653901Smckusick dlsz(i) = disz(i); 179753901Smckusick dlof(i) = diof(i); 179853901Smckusick } 179953901Smckusick } 180053901Smckusick #endif /* DISKINFO */ 180153901Smckusick 180253901Smckusick /* #ifdef DISKINFO KU:XXX */ 180353901Smckusick static 180453901Smckusick disklabel2diskinfo(unit, dlp, dip) 180553901Smckusick int unit; 180653901Smckusick register struct disklabel *dlp; 180753901Smckusick register struct diskinfo *dip; 180853901Smckusick { 180953901Smckusick register int i; 181053901Smckusick 181153901Smckusick dip->di_magic = DISKINFO_MAGIC; 181253901Smckusick dip->di_dkst.dks_nsect = dlp->d_nsectors; /* # sectors/track */ 181353901Smckusick dip->di_dkst.dks_ntrak = dlp->d_ntracks; /* # tracks/cylinder */ 181453901Smckusick dip->di_dkst.dks_ncyl = dlp->d_ncylinders; /* # cylinders */ 181553901Smckusick dip->di_dkst.dks_rps = dlp->d_rpm / 60; /* # revolutions/second */ 181653901Smckusick 181753901Smckusick for (i = 0; i < PNUM; i++) { 181853901Smckusick disz(i) = dlsz(i); 181953901Smckusick diof(i) = dlof(i); 182053901Smckusick } 182153901Smckusick } 182253901Smckusick /* #endif /* DISKINFO */ 182353901Smckusick 182453901Smckusick static 182553901Smckusick sdst2disklabel(unit, st, dlp) 182653901Smckusick int unit; /*XXX*/ 182753901Smckusick register struct sdst *st; 182853901Smckusick register struct disklabel *dlp; 182953901Smckusick { 183053901Smckusick register int i; 183153901Smckusick 183253901Smckusick dlp->d_type = DTYPE_SCSI; /* drive type */ 183353901Smckusick dlp->d_secsize = sdd_softc[unit].sdd_sectsize; /* # of bytes per sector */ 183453901Smckusick dlp->d_nsectors = st->nsect; /* # sectors/track */ 183553901Smckusick dlp->d_ntracks = st->ntrak; /* # tracks/cylinder */ 183653901Smckusick dlp->d_ncylinders = st->ncyl; /* # cylinders */ 183753901Smckusick dlp->d_secpercyl = st->nspc; /* # sectors/cylinder */ 183853901Smckusick dlp->d_rpm = st->rps * 60; /* # revolutions / minute */ 183953901Smckusick dlp->d_bbsize = BBSIZE; /*XXX*/ /* size of boot area at sn0, bytes */ 184053901Smckusick dlp->d_sbsize = SBSIZE; /*XXX*/ /* max size of fs superblock, bytes */ 184153901Smckusick 184253901Smckusick for (i = 0; i < PNUM; i++) { 184353901Smckusick dlsz(i) = stsz(i); 184453901Smckusick dlof(i) = stof(i); 184553901Smckusick } 184653901Smckusick } 184753901Smckusick 184853901Smckusick #undef stsz 184953901Smckusick #undef stof 185053901Smckusick #undef dlsz 185153901Smckusick #undef dlof 185253901Smckusick #undef disz 185353901Smckusick #undef diof 185453901Smckusick 185553901Smckusick sd_calcpart(ii, disk_sizes, nsect, sectsize) 185653901Smckusick register struct iop/**/_device *ii; 185753901Smckusick register struct size disk_sizes[]; 185853901Smckusick int nsect; 185953901Smckusick int sectsize; 186053901Smckusick { 186153901Smckusick register struct defpart *dp; 186253901Smckusick register int size_mb; 186353901Smckusick register int i; 186453901Smckusick int psize; 186553901Smckusick 186653901Smckusick size_mb = nsect * sectsize / (1024 * 1024); 186753901Smckusick 186853901Smckusick for (dp = defpart_std; dp->range_max; dp++) 186953901Smckusick if ((dp->range_min <= size_mb) && (size_mb < dp->range_max)) 187053901Smckusick break; 187153901Smckusick 187253901Smckusick /* PASS1 */ 187353901Smckusick for (i = 0; i < PNUM; i++) { 187453901Smckusick psize = dp->partsize[i]; 187553901Smckusick 187653901Smckusick switch (psize) { 187753901Smckusick 187853901Smckusick case PART_UNUSED: 187953901Smckusick disk_sizes[i].sd_nblocks = 0; 188053901Smckusick break; 188153901Smckusick 188253901Smckusick case PART_SPEC: 188353901Smckusick disk_sizes[i].sd_nblocks = nsect * sectsize / DEV_BSIZE; 188453901Smckusick break; 188553901Smckusick 188653901Smckusick case PART_CALCF: 188753901Smckusick case PART_CALCG: 188853901Smckusick break; 188953901Smckusick 189053901Smckusick default: 189153901Smckusick disk_sizes[i].sd_nblocks = psize; 189253901Smckusick break; 189353901Smckusick } 189453901Smckusick } 189553901Smckusick 189653901Smckusick /* PASS2 */ 189753901Smckusick for (i = 0; i < PNUM; i++) { 189853901Smckusick psize = dp->partsize[i]; 189953901Smckusick 190053901Smckusick switch (psize) { 190153901Smckusick 190253901Smckusick case PART_UNUSED: 190353901Smckusick case PART_SPEC: 190453901Smckusick break; 190553901Smckusick 190653901Smckusick case PART_CALCF: 190753901Smckusick disk_sizes[i].sd_nblocks = 190853901Smckusick disk_sizes[PART_C].sd_nblocks - 190953901Smckusick (disk_sizes[PART_A].sd_nblocks + 191053901Smckusick disk_sizes[PART_B].sd_nblocks + 191153901Smckusick disk_sizes[PART_D].sd_nblocks + 191253901Smckusick disk_sizes[PART_E].sd_nblocks + 191353901Smckusick disk_sizes[PART_H].sd_nblocks); 191453901Smckusick break; 191553901Smckusick 191653901Smckusick case PART_CALCG: 191753901Smckusick disk_sizes[i].sd_nblocks = 191853901Smckusick disk_sizes[PART_C].sd_nblocks - 191953901Smckusick (disk_sizes[PART_A].sd_nblocks + 192053901Smckusick disk_sizes[PART_B].sd_nblocks + 192153901Smckusick disk_sizes[PART_H].sd_nblocks); 192253901Smckusick break; 192353901Smckusick 192453901Smckusick default: 192553901Smckusick break; 192653901Smckusick } 192753901Smckusick } 192853901Smckusick 192953901Smckusick /* OFFSET */ 193053901Smckusick disk_sizes[PART_A].sd_blkoff = 0; 193153901Smckusick disk_sizes[PART_B].sd_blkoff = disk_sizes[PART_A].sd_nblocks; 193253901Smckusick disk_sizes[PART_C].sd_blkoff = 0; 193353901Smckusick disk_sizes[PART_D].sd_blkoff = disk_sizes[PART_A].sd_nblocks 193453901Smckusick + disk_sizes[PART_B].sd_nblocks 193553901Smckusick + disk_sizes[PART_H].sd_nblocks; 193653901Smckusick disk_sizes[PART_E].sd_blkoff = disk_sizes[PART_D].sd_blkoff 193753901Smckusick + disk_sizes[PART_D].sd_nblocks; 193853901Smckusick disk_sizes[PART_F].sd_blkoff = disk_sizes[PART_E].sd_blkoff 193953901Smckusick + disk_sizes[PART_E].sd_nblocks; 194053901Smckusick disk_sizes[PART_G].sd_blkoff = disk_sizes[PART_D].sd_blkoff; 194153901Smckusick 194253901Smckusick if (disk_sizes[PART_H].sd_nblocks == 0) 194353901Smckusick disk_sizes[PART_H].sd_blkoff = 0; 194453901Smckusick else { 194553901Smckusick disk_sizes[PART_H].sd_blkoff = 194653901Smckusick disk_sizes[PART_A].sd_nblocks + 194753901Smckusick disk_sizes[PART_B].sd_nblocks; 194853901Smckusick } 194953901Smckusick 195053901Smckusick for (i = 0; i < PNUM; i++) 195153901Smckusick if (disk_sizes[i].sd_nblocks == 0) 195253901Smckusick disk_sizes[i].sd_blkoff = 0; 195353901Smckusick } 195453901Smckusick 195553901Smckusick int sd_str_pr = 0; 195653901Smckusick 195753901Smckusick sdstrategy(bp) 195853901Smckusick register struct buf *bp; 195953901Smckusick { 196053901Smckusick register struct iop/**/_device *ii; 196153901Smckusick register struct sdst *st; 196253901Smckusick register struct buf *dp; 196353901Smckusick register int unit; 196453901Smckusick register int ssize; 196553901Smckusick struct sdd_softc *sdd; 196653901Smckusick struct sdc_softc *sdc; 196753901Smckusick long bn; 196853901Smckusick int xunit; 196953901Smckusick int s; 197053901Smckusick 197153901Smckusick xunit = dev2part(bp->b_dev); 197253901Smckusick unit = dev2unit(bp->b_dev); 197353901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) 197453901Smckusick goto bad; 197553901Smckusick 197653901Smckusick if (bp != &csdbuf[unit]) { 197753901Smckusick /* 197853901Smckusick * READ / WRITE command 197953901Smckusick */ 198053901Smckusick sdd = &sdd_softc[unit]; 198153901Smckusick if (sdd->sdd_flags & SDDF_NONFMT) 198253901Smckusick goto bad; 198353901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 198453901Smckusick ssize = sdd->sdd_sectsize; 198553901Smckusick if ((ssize != DEV_BSIZE) 198653901Smckusick && ((((dkblock(bp) * DEV_BSIZE) % ssize) != 0) 198753901Smckusick || (((bp->b_flags & B_READ) == 0) && 198853901Smckusick ((bp->b_bcount % ssize) != 0)))) { 198953901Smckusick goto bad; 199053901Smckusick } 199153901Smckusick 199253901Smckusick st = &sdstdrv[unit]; 199353901Smckusick bn = dkblock(bp); 199453901Smckusick bp->b_resid = 0; 199553901Smckusick if ((bn < 0) || (bn >= st->sizes[xunit].sd_nblocks)) 199653901Smckusick goto bad2; 199753901Smckusick if (sd_access_check(bp) < 0) 199853901Smckusick goto bad2; 199953901Smckusick 200053901Smckusick #ifdef notdef /* KU: XXX */ 200153901Smckusick bp->b_cylin = (bn + st->sizes[xunit].sd_blkoff) / st->nspc; 200253901Smckusick } else { 200353901Smckusick bp->b_cylin = 0; 200453901Smckusick #endif 200553901Smckusick } 200653901Smckusick 200753901Smckusick s = splsc(); 200853901Smckusick dp = &sdutab[ii->ii_unit]; 200953901Smckusick disksort(dp, bp); 201053901Smckusick if (dp->b_active == 0) { 201153901Smckusick sdustart(ii); 201253901Smckusick bp = &ii->ii_mi->im_tab; 201353901Smckusick if (bp->b_actf && bp->b_active == 0) 201453901Smckusick sdstart(ii->ii_mi); 201553901Smckusick } 201653901Smckusick splx(s); 201753901Smckusick return; 201853901Smckusick 201953901Smckusick bad: 202053901Smckusick bp->b_flags |= B_ERROR; 202153901Smckusick goto done; 202253901Smckusick bad2: 202353901Smckusick bp->b_resid = bp->b_bcount; 202453901Smckusick done: 202553901Smckusick iodone(bp); 202653901Smckusick } 202753901Smckusick 202853901Smckusick /* 202953901Smckusick * Unit start routine. 203053901Smckusick */ 203153901Smckusick sdustart(ii) 203253901Smckusick register struct iop/**/_device *ii; 203353901Smckusick { 203453901Smckusick register struct iop/**/_ctlr *im; 203553901Smckusick register struct buf *dp; 203653901Smckusick 203753901Smckusick if (ii == NULL) 203853901Smckusick return; 203953901Smckusick im = ii->ii_mi; 204053901Smckusick dk_busy &= ~(1 << ii->ii_dk); 204153901Smckusick dp = &sdutab[ii->ii_unit]; 204253901Smckusick if (dp->b_actf == NULL) 204353901Smckusick return; 204453901Smckusick /* 204553901Smckusick * If the controller is active, just remember 204653901Smckusick * that this device would like to be positioned ... 204753901Smckusick * if we tried to position now we would confuse the SD. 204853901Smckusick */ 204953901Smckusick if (im->im_tab.b_active) { 205053901Smckusick sdc_softc[im->im_ctlr].sdc_softas |= (1 << ii->ii_slave); 205153901Smckusick return; 205253901Smckusick } 205353901Smckusick /* 205453901Smckusick * If we have already positioned this drive, 205553901Smckusick * then just put it on the ready queue. 205653901Smckusick */ 205753901Smckusick if (dp->b_active == 0) 205853901Smckusick dp->b_active = 1; 205953901Smckusick /* 206053901Smckusick * Device is ready to go 206153901Smckusick * put it on the ready queue for the controller 206253901Smckusick * (unless its already there.) 206353901Smckusick */ 206453901Smckusick if (dp->b_active != 2) { 2065*57612Sutashiro im->im_tab.b_actf = dp; 206653901Smckusick dp->b_active = 2; 206753901Smckusick } 206853901Smckusick } 206953901Smckusick 207053901Smckusick /* 207153901Smckusick * Start up a transfer on a drive. 207253901Smckusick */ 207353901Smckusick sdstart(im) 207453901Smckusick register struct iop/**/_ctlr *im; 207553901Smckusick { 207653901Smckusick register struct buf *bp; 207753901Smckusick register struct buf *dp; 207853901Smckusick register struct sdc_softc *sdc; 207953901Smckusick 208053901Smckusick loop: 208153901Smckusick /* 208253901Smckusick * Pull a request off the controller queue. 208353901Smckusick */ 208453901Smckusick if ((dp = im->im_tab.b_actf) == NULL) 208553901Smckusick return; 2086*57612Sutashiro if ((bp = dp->b_actf) == NULL) 2087*57612Sutashiro return; 208853901Smckusick /* 208953901Smckusick * Mark controller busy, and 209053901Smckusick * determine destination of this request. 209153901Smckusick */ 209253901Smckusick im->im_tab.b_active++; 209353901Smckusick 209453901Smckusick sdexec(bp); 209553901Smckusick } 209653901Smckusick 209753901Smckusick void 209853901Smckusick sdexec(bp) 209953901Smckusick register struct buf *bp; 210053901Smckusick { 210153901Smckusick register struct iop/**/_device *ii; 210253901Smckusick register struct buf_stat *bs; 210353901Smckusick register struct scsi *sc; 210453901Smckusick register int ssize; 210553901Smckusick register int unit; 210653901Smckusick register int intr; 210753901Smckusick register int bn; 210853901Smckusick struct sdc_softc *sdc; 210953901Smckusick struct sdd_softc *sdd; 211053901Smckusick struct sdst *st; 211153901Smckusick int sz; 211253901Smckusick int over; 211353901Smckusick struct sc_map *map; 211453901Smckusick 211553901Smckusick unit = dev2unit(bp->b_dev); 2116*57612Sutashiro ii = sddinfo[unit]; 211753901Smckusick intr = ii->ii_intr; 211853901Smckusick sdd = &sdd_softc[unit]; 211953901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 212053901Smckusick 212153901Smckusick sc = get_scsi(intr); 212253901Smckusick 212353901Smckusick if (bp == &csdbuf[unit]) { /* do sdcmd() */ 212453901Smckusick bcopy((caddr_t)&kernscsi[unit], 212553901Smckusick (caddr_t)sc, sizeof(struct scsi)); 212653901Smckusick if (bp->b_un.b_addr == NULL) { 212753901Smckusick map = 0; 212853901Smckusick } else { 212953901Smckusick map = get_sc_map(intr); 213053901Smckusick sc->sc_map = (struct sc_map *)ipc_phys(map); 213153901Smckusick } 213253901Smckusick } else { /* R/W */ 213353901Smckusick ssize = sdd->sdd_sectsize; 213453901Smckusick 213553901Smckusick st = &sdstdrv[unit]; 213653901Smckusick bn = dkblock(bp); 213753901Smckusick if (sdd->sdd_lastblk / st->nspc != bn / st->nspc) 213853901Smckusick dk_seek[ii->ii_dk]++; 213953901Smckusick 214053901Smckusick st = &sdstdrv[unit]; 214153901Smckusick bn = dkblock(bp); 214253901Smckusick 214353901Smckusick /* 214453901Smckusick * Setup for the transfer, and get in the IOP queue. 214553901Smckusick */ 214653901Smckusick scinit(sc, ii->ii_slave, ssize); 214753901Smckusick sc->sc_ctrnscnt = bp->b_bcount - bp->b_resid; 214853901Smckusick map = get_sc_map(intr); 214953901Smckusick sc->sc_map = (struct sc_map *)ipc_phys(map); 215053901Smckusick 215153901Smckusick /* cdb */ 215253901Smckusick sc->sc_cdb.un_type1.t1_opcode = 215353901Smckusick (bp->b_flags & B_READ) ? SCOP_EREAD : 215453901Smckusick (ii->ii_flags & SD_F_WRTVRFY) ? SCOP_WRTVRFY : 215553901Smckusick SCOP_EWRITE; 215653901Smckusick #ifdef mips 215753901Smckusick { 215853901Smckusick int v; 215953901Smckusick 216053901Smckusick v = (bn + st->sizes[dev2part(bp->b_dev)].sd_blkoff) 216153901Smckusick * DEV_BSIZE / sdd->sdd_sectsize; 216253901Smckusick sc->sc_ladhi = v >> 16; 216353901Smckusick sc->sc_ladlo = v; 216453901Smckusick 216553901Smckusick v = (sc->sc_ctrnscnt + ssize - 1) / ssize; 216653901Smckusick sc->sc_cdb.un_type1.t1_p2 = v >> 8; 216753901Smckusick sc->sc_cdb.un_type1.t1_p3 = v; 216853901Smckusick } 216953901Smckusick #else 217053901Smckusick *(u_int *)(&sc->sc_cdb.un_type1.t1_ladhi) = 217153901Smckusick (bn + st->sizes[dev2part(bp->b_dev)].sd_blkoff) 217253901Smckusick * DEV_BSIZE / sdd->sdd_sectsize; 217353901Smckusick *(u_short *)(&sc->sc_cdb.un_type1.t1_p2) = 217453901Smckusick (sc->sc_ctrnscnt + ssize -1) / ssize; 217553901Smckusick #endif 217653901Smckusick if ((sdd->sdd_flags & SDDF_ERASEOFF) 217753901Smckusick && ((bp->b_flags & B_READ) == 0)) { 217853901Smckusick sc->sc_ctrl = 0x40; 217953901Smckusick } 218053901Smckusick } 218153901Smckusick 218253901Smckusick sdc->sdc_firmware |= SDCFW_BUSY; 218353901Smckusick iop/**/go(ii, map); 218453901Smckusick } 218553901Smckusick 218653901Smckusick /* 218753901Smckusick * Now all ready to go. 218853901Smckusick */ 218953901Smckusick sddgo(im) 219053901Smckusick register struct iop/**/_ctlr *im; 219153901Smckusick { 219253901Smckusick register int intr; 219353901Smckusick 219453901Smckusick im->im_tab.b_active = 2; 219553901Smckusick intr = im->im_intr; 219653901Smckusick 219753901Smckusick sc_go(intr, get_scsi(intr), SCSI_INTEN); 219853901Smckusick } 219953901Smckusick 220053901Smckusick /* 220153901Smckusick * copyin(), copyout() can't use in the interrupt routine. 220253901Smckusick * because user process is changed. 220353901Smckusick */ 220453901Smckusick /* 220553901Smckusick * Handle a disk interrupt. 220653901Smckusick * d: controller number 220753901Smckusick */ 220853901Smckusick sdintr(d) 220953901Smckusick int d; 221053901Smckusick { 221153901Smckusick register struct iop/**/_ctlr *im; 221253901Smckusick register struct sdc_softc *sdc; 221353901Smckusick register struct sdd_softc *sdd; 221453901Smckusick register struct scsi *sc; 221553901Smckusick register int intr; 221653901Smckusick register int unit; 221753901Smckusick register int slave; 221853901Smckusick register int as; 221953901Smckusick struct iop/**/_device *ii; 222053901Smckusick struct sddevinfo *sdi; 222153901Smckusick struct sc_extnd *sce; 222253901Smckusick struct sdst *st; 222353901Smckusick struct buf *bp; 222453901Smckusick struct buf *dp; 222553901Smckusick char *erp_page; 222653901Smckusick int code; 222753901Smckusick int len; 222853901Smckusick int tstatus; 222953901Smckusick int delay_start(); 223053901Smckusick int delay_medrmv(); 223153901Smckusick int wait_re_init_done(); 223253901Smckusick 223353901Smckusick im = sdminfo[d]; 223453901Smckusick sdc = &sdc_softc[im->im_ctlr]; 223553901Smckusick intr = im->im_intr; 223653901Smckusick as = sdc->sdc_softas; 223753901Smckusick 223853901Smckusick sdc->sdc_wticks = 0; 223953901Smckusick sc = get_scsi(intr); 224053901Smckusick /* 224153901Smckusick * If SDCS_IOCTL bit is set, then don't check error. 224253901Smckusick */ 224353901Smckusick if (sdc->sdc_state & SDCS_IOCTL) { 224453901Smckusick sdc->sdc_state &= ~SDCS_IOCTL; 224553901Smckusick sdd = &sdd_softc[(sdip[d][sc->sc_identify & IDT_DRMASK])->ii_unit]; 224653901Smckusick 224753901Smckusick if (sdc->sdc_state & SDCS_SCUNLOCK) { 224853901Smckusick int s; 224953901Smckusick 225053901Smckusick sdc->sdc_state &= ~SDCS_SCUNLOCK; 225153901Smckusick s = splclock(); 225253901Smckusick if (sdc->sdc_state & SDCS_OPEN_WAIT) { 225353901Smckusick sdc->sdc_state &= ~SDCS_OPEN_WAIT; 225453901Smckusick wakeup((caddr_t)sdc); 225553901Smckusick } 225653901Smckusick splx(s); 225753901Smckusick /* 225853901Smckusick * UNLOCK SCSI access 225953901Smckusick */ 226053901Smckusick sdc->sdc_firmware &= ~SDCFW_BUSY; 226153901Smckusick } 226253901Smckusick return; 226353901Smckusick } 226453901Smckusick 226553901Smckusick im->im_tab.b_active = 1; 226653901Smckusick /* 226753901Smckusick * Get device and block structures, and a pointer 226853901Smckusick * to the iop_device for the drive. 226953901Smckusick */ 227053901Smckusick dp = im->im_tab.b_actf; 227153901Smckusick bp = dp->b_actf; 227253901Smckusick unit = dev2unit(bp->b_dev); 227353901Smckusick 227453901Smckusick ii = sddinfo[unit]; 227553901Smckusick slave = ii->ii_slave; 227653901Smckusick st = &sdstdrv[unit]; 227753901Smckusick dk_busy &= ~(1 << ii->ii_dk); 227853901Smckusick sdd = &sdd_softc[unit]; 227953901Smckusick sdi = &sddevinfo[ii->ii_type]; 228053901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 228153901Smckusick 228253901Smckusick /* 228353901Smckusick * Check error on the drive. 228453901Smckusick */ 228553901Smckusick tstatus = sc->sc_tstatus & TGSTMASK; 228653901Smckusick if (sc->sc_istatus != INST_EP) { 228753901Smckusick /* 228853901Smckusick * initiator status is bad. 228953901Smckusick * check & retry !! 229053901Smckusick */ 229153901Smckusick if ((sc->sc_istatus&(INST_EP|INST_PRE)) == (INST_EP|INST_PRE)) { 229253901Smckusick /* detect parity error or abnormal terminate */ 229353901Smckusick if ((sc->sc_istatus & INST_LB) == 0) 229453901Smckusick printf("sd%d: SCSI bus parity error\n", unit); 229553901Smckusick sdc->sdc_countcc--; 229653901Smckusick goto sdintr_exec; 229753901Smckusick } 229853901Smckusick if ((sc->sc_istatus & INST_EP) == 0) { 229953901Smckusick if (sc->sc_istatus & (INST_WAIT | INST_IP | INST_WR)) { 230053901Smckusick if (++sdc->sdc_retrycnt < NRETRY) { 230153901Smckusick im->im_tab.b_active = 2; 230253901Smckusick /* 230353901Smckusick * Konomama return sitemo, 230453901Smckusick * lost interrupt ni narudake deha 230553901Smckusick * naidarou ka ? 230653901Smckusick * Isso error ni sitahou ga 230753901Smckusick * ii nodeha naidarou ka ? 230853901Smckusick */ 230953901Smckusick return; 231053901Smckusick } 231153901Smckusick } 231253901Smckusick printf("SCSI%d: abnormal termination\n", intr); 231353901Smckusick printf("ISTAT = 0x%x, TSTAT = 0x%x\n", 231453901Smckusick sc->sc_istatus, sc->sc_tstatus); 231553901Smckusick if (++sdc->sdc_nhrderr >= MAXHRDERR) { 231653901Smckusick printf("SCSI%d: too many hard errors\n", intr); 231753901Smckusick sdc->sdc_nhrderr = 0; 231853901Smckusick goto sdintr_error; 231953901Smckusick } 232053901Smckusick screset(intr); 232153901Smckusick goto sdintr_exec; 232253901Smckusick } 232353901Smckusick if ((sc->sc_istatus & (INST_TO|INST_HE)) != 0) { 232453901Smckusick if (sc->sc_istatus & INST_HE) { 232553901Smckusick /* 232653901Smckusick * SCSI bus reset is occured. 232753901Smckusick * to be continue --> hdreset() 232853901Smckusick */ 232953901Smckusick re_init_done = 0; 233053901Smckusick timeout(wait_re_init_done, bp, 10*hz); 233153901Smckusick return; 233253901Smckusick } 233353901Smckusick if (++sdc->sdc_nhrderr >= MAXHRDERR) { 233453901Smckusick printf("SCSI%d: too many hard errors (ISTAT=0x%x)\n", 233553901Smckusick intr, sc->sc_istatus); 233653901Smckusick sdc->sdc_nhrderr = 0; 233753901Smckusick goto sdintr_error; 233853901Smckusick } 233953901Smckusick if (++sdc->sdc_retrycnt >= NRETRY) { 234053901Smckusick printf("SCSI%d: too many initiator errors (ISTAT=0x%x)\n", 234153901Smckusick intr, sc->sc_istatus); 234253901Smckusick goto sdintr_error; 234353901Smckusick } 234453901Smckusick DELAY(D100MSEC * 10); 234553901Smckusick goto sdintr_exec; 234653901Smckusick } 234753901Smckusick } 234853901Smckusick 234953901Smckusick if (sdd->sdd_flags & SDDF_SKIPCHECK) 235053901Smckusick goto sdintr_done; 235153901Smckusick 235253901Smckusick check_target_status: 235353901Smckusick /* 235453901Smckusick * check target status 235553901Smckusick */ 235653901Smckusick switch (sdc->sdc_state) { 235753901Smckusick 235853901Smckusick /********************************/ 235953901Smckusick /* */ 236053901Smckusick /* NORMAL OPERATION */ 236153901Smckusick /* */ 236253901Smckusick /********************************/ 236353901Smckusick case SDCS_NORMAL: 236453901Smckusick switch (tstatus) { 236553901Smckusick 236653901Smckusick case TGST_GOOD: 236753901Smckusick break; 236853901Smckusick 236953901Smckusick case TGST_CC: 237053901Smckusick sdc->sdc_state |= SDCS_RSENSE; 237153901Smckusick sdintr_rsense: 237253901Smckusick im->im_tab.b_active = 2; 237353901Smckusick bzero((caddr_t)sce, RSEN_CNT); 237453901Smckusick scop_rsense(intr, sc, slave, 237553901Smckusick SCSI_INTEN, RSEN_CNT, (caddr_t)sce); 237653901Smckusick return; 237753901Smckusick 237853901Smckusick case TGST_BUSY: 237953901Smckusick if (++sdc->sdc_retrycnt > MAXRETRYCNT) { 238053901Smckusick goto sdintr_error; 238153901Smckusick } 238253901Smckusick timeout(sdexec, (caddr_t)bp, hz); 238353901Smckusick return; 238453901Smckusick 238553901Smckusick default: 238653901Smckusick printf("sd%d: bad target status 0x%x\n", 238753901Smckusick unit, sc->sc_tstatus); 238853901Smckusick goto sdintr_error; 238953901Smckusick } 239053901Smckusick break; 239153901Smckusick 239253901Smckusick /****************************************/ 239353901Smckusick /* */ 239453901Smckusick /* REQUEST SENSE analysis */ 239553901Smckusick /* */ 239653901Smckusick /****************************************/ 239753901Smckusick case SDCS_RSENSE: 239853901Smckusick case SDCS_PREVRMB|SDCS_RSENSE: 239953901Smckusick case SDCS_ECC|SDCS_RASREAD|SDCS_RSENSE: 240053901Smckusick case SDCS_ECC|SDCS_RASWRITE|SDCS_RSENSE: 240153901Smckusick case SDCS_ECCOFF|SDCS_RSENSE: 240253901Smckusick case SDCS_ECCOFF|SDCS_RASBLK|SDCS_RSENSE: 240353901Smckusick case SDCS_ECCOFF|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE: 240453901Smckusick case SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE: 240553901Smckusick case SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE: 240653901Smckusick if (tstatus != TGST_GOOD) { 240753901Smckusick printf("sd%d: bad target status 0x%x\n", 240853901Smckusick unit, sc->sc_tstatus); 240953901Smckusick goto sdintr_error; 241053901Smckusick } 241153901Smckusick /* 241253901Smckusick * error message print out 241353901Smckusick */ 241453901Smckusick code = sderrordisp(sce, ii); 241553901Smckusick 241653901Smckusick 241753901Smckusick if ((sdc->sdc_state == (SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE)) || 241853901Smckusick (sdc->sdc_state == (SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE))) { 241953901Smckusick printf("sd%d: cannot reassign block %d\n", 242053901Smckusick unit, sdd->sdd_badsect); 242153901Smckusick goto sdintr_error; 242253901Smckusick } 242353901Smckusick if (sdc->sdc_state == (SDCS_PREVRMB|SDCS_RSENSE)) { 242453901Smckusick if (sce->sce_skey == 0x2) { 242553901Smckusick /* 242653901Smckusick * Not ready 242753901Smckusick */ 242853901Smckusick sdc->sdc_state = SDCS_PREVRMB; 242953901Smckusick timeout(delay_medrmv, (caddr_t)ii, hz); 243053901Smckusick return; 243153901Smckusick } 243253901Smckusick } 243353901Smckusick 243453901Smckusick /* */ 243553901Smckusick /* RSENSE error handler */ 243653901Smckusick /* */ 243753901Smckusick switch (code) { 243853901Smckusick 243953901Smckusick /********************************/ 244053901Smckusick /* continue */ 244153901Smckusick /********************************/ 244253901Smckusick /* NO SENSE */ 244353901Smckusick case 0x00: /* No Additional Sense Information */ 244453901Smckusick /* RECOVERED ERROR */ 244553901Smckusick case 0x38: /* Recovered with Auto-Reallocation */ 244653901Smckusick sdc->sdc_state &= ~SDCS_RSENSE; 244753901Smckusick goto check_target_status; 244853901Smckusick 244953901Smckusick /********************************/ 245053901Smckusick /* continue or error */ 245153901Smckusick /********************************/ 245253901Smckusick /* ILLEGAL REQUEST */ 245353901Smckusick 245453901Smckusick case 0x21: /* illegal Logical Block Address */ 245553901Smckusick if (&st->sizes[dev2part(bp->b_dev)] == NULL) 245653901Smckusick goto sdintr_error; 245753901Smckusick if (bp->b_bcount > 0) { 245853901Smckusick bp->b_resid = bp->b_bcount 245953901Smckusick - (sdd->sdd_badsect * sdd->sdd_sectsize 246053901Smckusick - (st->sizes[dev2part(bp->b_dev)].sd_blkoff 246153901Smckusick + dkblock(bp)) * DEV_BSIZE); 246253901Smckusick } 246353901Smckusick if (bp->b_resid >= bp->b_bcount || bp->b_resid <= 0) { 246453901Smckusick /* 246553901Smckusick * all I/O failure 246653901Smckusick */ 246753901Smckusick bp->b_resid = bp->b_bcount; 246853901Smckusick goto sdintr_error; 246953901Smckusick } 247053901Smckusick /* Ignore error */ 247153901Smckusick break; 247253901Smckusick 247353901Smckusick /* MEDIUM ERROR */ 247453901Smckusick case 0x31: /* Medium Format Corrupted */ 247553901Smckusick sdd->sdd_flags |= SDDF_NONFMT; 247653901Smckusick /* Ignore error */ 247753901Smckusick break; 247853901Smckusick 247953901Smckusick /********************************/ 248053901Smckusick /* more retry */ 248153901Smckusick /********************************/ 248253901Smckusick /* MEDIUM or RECOVERED ERROR */ 248353901Smckusick case 0x10: /* ID CRC Error */ 248453901Smckusick case 0x12: /* No Address Mark found in ID field */ 248553901Smckusick case 0x13: /* No Address Mark found in Data field */ 248653901Smckusick case 0x14: /* No recode found */ 248753901Smckusick /* H/W or MEDIUM or RECOVERED ERROR */ 248853901Smckusick case 0x15: /* Seek Positioning Error */ 248953901Smckusick if (sd_ignore_error) { 249053901Smckusick sdc->sdc_state = SDCS_NORMAL; 249153901Smckusick goto check_target_status; 249253901Smckusick } 249353901Smckusick /* fall through */ 249453901Smckusick 249553901Smckusick /* H/W ERROR */ 249653901Smckusick case 0x01: /* No Index/Address Mark Found signal */ 249753901Smckusick case 0x02: /* No Seek Complete */ 249853901Smckusick case 0x06: /* No Track Zero found */ 249953901Smckusick /* H/W ERROR or RECOVERED ERROR */ 250053901Smckusick case 0x03: /* Write Fault */ 250153901Smckusick case 0x08: /* Logical Unit Communication Failure */ 250253901Smckusick case 0x09: /* Track Following Error */ 250353901Smckusick case 0x0b: /* Load/Unload Failure */ 250453901Smckusick case 0x0c: /* Spindle Failure */ 250553901Smckusick case 0x0d: /* Focus Failure */ 250653901Smckusick case 0x0e: /* Tracking Failure */ 250753901Smckusick case 0x0f: /* Drive Initialization Failure */ 250853901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_REZERO; 250953901Smckusick 251053901Smckusick scinit(sc, slave, sdd->sdd_sectsize); 251153901Smckusick /* sc_cdb */ 251253901Smckusick sc->sc_opcode = SCOP_REZERO; 251353901Smckusick 251453901Smckusick sddgo(im); 251553901Smckusick return; 251653901Smckusick 251753901Smckusick /********************************/ 251853901Smckusick /* re-allocate & retry */ 251953901Smckusick /********************************/ 252053901Smckusick /* MEDIUM or RECOVERED ERROR */ 252153901Smckusick case 0x11: /* Unrecovered Read Error */ 252253901Smckusick if (sdc->sdc_state & SDCS_RASREAD) { 252353901Smckusick sdintr_lostdata: 252453901Smckusick sdc->sdc_state = 252553901Smckusick SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA; 252653901Smckusick im->im_tab.b_active = 2; 252753901Smckusick scop_rasblk(intr, sc, slave, 252853901Smckusick SCSI_INTEN, sdd->sdd_badsect); 252953901Smckusick sdd->sdd_flags &= ~SDDF_VBADSECT; 253053901Smckusick return; 253153901Smckusick } 253253901Smckusick /* fall through */ 253353901Smckusick 253453901Smckusick /* RECOVERED ERROR */ 253553901Smckusick case 0x17: /* Recovered read data with retries */ 253653901Smckusick case 0x18: /* Recovered read data with ECC */ 253753901Smckusick /* 253853901Smckusick * set ECC ON & more retry 253953901Smckusick */ 254053901Smckusick if (sdc->sdc_firmware & SDCFW_DEFMODE) 254153901Smckusick goto sdintr_ecc; 254253901Smckusick 254353901Smckusick if (sdc->sdc_state & SDCS_RASREAD) 254453901Smckusick goto sdintr_rasblk; 254553901Smckusick 254653901Smckusick sdc->sdc_state = SDCS_ECC; 254753901Smckusick goto sdintr_msel_set; 254853901Smckusick 254953901Smckusick /********************************/ 255053901Smckusick /* unit start & retry */ 255153901Smckusick /********************************/ 255253901Smckusick /* NOT READY */ 255353901Smckusick case 0x04: /* Drive Not Ready */ 255453901Smckusick if (sdc->sdc_state & SDCS_ECC) 255553901Smckusick sdc->sdc_state = SDCS_ECCOFF|SDCS_RETRY; 255653901Smckusick else 255753901Smckusick sdc->sdc_state = SDCS_RETRY; 255853901Smckusick goto sdintr_stst; 255953901Smckusick 256053901Smckusick /********************************/ 256153901Smckusick /* retry */ 256253901Smckusick /********************************/ 256353901Smckusick /* UNIT ATTENTION */ 256453901Smckusick case 0x28: /* Medium Changed */ 256553901Smckusick sdd->sdd_flags &= ~(SDDF_NONFMT 256653901Smckusick |SDDF_SAMEDSK 256753901Smckusick |SDDF_REQ_EJECT 256853901Smckusick |SDDF_XUSE 256953901Smckusick |SDDF_INHRMV 257053901Smckusick |SDDF_ERASEOFF); 257153901Smckusick /* fall through */ 257253901Smckusick 257353901Smckusick case 0x29: /* Power On or Reset or Bus Device Reset */ 257453901Smckusick if (sdc->sdc_firmware & SDCFW_RMB) { 257553901Smckusick /***************************/ 257653901Smckusick /* medium removable device */ 257753901Smckusick /***************************/ 257853901Smckusick sdc->sdc_state = SDCS_PREVRMB; 257953901Smckusick im->im_tab.b_active = 2; 258053901Smckusick scop_medrmv(intr, sc, slave, 258153901Smckusick SCSI_INTEN, SDRMV_PREV); 258253901Smckusick return; 258353901Smckusick } 258453901Smckusick 258553901Smckusick case 0x2a: /* Mode Select Parameter Changed */ 258653901Smckusick case 0x47: /* SCSI interface bus parity error */ 258753901Smckusick if (sdc->sdc_state & SDCS_ECC) { 258853901Smckusick sdc->sdc_state = SDCS_RETRY; 258953901Smckusick goto sdintr_msel_reset; 259053901Smckusick } 259153901Smckusick sdc->sdc_state = SDCS_NORMAL; 259253901Smckusick goto sdintr_exec; 259353901Smckusick 259453901Smckusick /********************************/ 259553901Smckusick /* set error flag */ 259653901Smckusick /********************************/ 259753901Smckusick case 0x40: /* RAM failure */ 259853901Smckusick case 0x41: /* Data Path diagnostic failure */ 259953901Smckusick case 0x42: /* Power On diagnostic failure */ 260053901Smckusick 260153901Smckusick case 0xb2: /* Caddy load/eject failed */ 260253901Smckusick case 0xb4: /* Focus servo failure */ 260353901Smckusick case 0xb5: /* Spindle servo failure */ 260453901Smckusick case 0xb6: /* Caddy load mechanism failed */ 260553901Smckusick goto sdintr_error; 260653901Smckusick 260753901Smckusick /*MO*/ case 0x80: /* Limit Laser Life */ 260853901Smckusick /*MO*/ case 0x81: /* Focus Coil Over-current Failure */ 260953901Smckusick /*MO*/ case 0x82: /* Tracking Coil Over-current Failure */ 261053901Smckusick /*MO*/ case 0x83: /* Temperature Alarm */ 261153901Smckusick /*CD*/ /* case 0x80: */ /* Prevent bit is set */ 261253901Smckusick /*CD*/ /* case 0x81: */ /* Logical unit is reserved */ 261353901Smckusick /*CD*/ /* case 0x82: */ /* End of usr area encountered */ 261453901Smckusick /*CD*/ /* case 0x83: */ /* Overlapped commands attempted */ 261553901Smckusick goto sdintr_error; 261653901Smckusick 261753901Smckusick default: 261853901Smckusick /* 261953901Smckusick * error detect, but what shall we do ? 262053901Smckusick */ 262153901Smckusick /* case 0x05: */ /* Drive Not Selected */ 262253901Smckusick /* case 0x07: */ /* Multiple Drives Selected */ 262353901Smckusick /* case 0x0a: */ /* No disk */ 262453901Smckusick /* case 0x1a: */ /* Parameter overrun */ 262553901Smckusick /* case 0x1b: */ /* Synchronous transfer error */ 262653901Smckusick /* case 0x1d: */ /* Compare error */ 262753901Smckusick /* case 0x22: */ /* Illegal function for device type */ 262853901Smckusick /* case 0x23: */ /* Illegal function for Medium type */ 262953901Smckusick /* case 0x25: */ /* Illegal LUN */ 263053901Smckusick /* case 0x27: */ /* Write Protected */ 263153901Smckusick /* case 0x2b: */ /* Firmware has been downloaded */ 263253901Smckusick /* case 0x39: */ /* Automatic Reallocation Failure */ 263353901Smckusick /* case 0x43: */ /* Message Reject Error */ 263453901Smckusick /* case 0x45: */ /* Selection/Reselection failure */ 263553901Smckusick /* case 0x48: */ /* Initiator detected error */ 263653901Smckusick /* case 0x49: */ /* Inappropriate/illegal message */ 263753901Smckusick /* case 0x60: */ /* COPY: STATUS error */ 263853901Smckusick /* case 0x85: */ /* Audio address not valid */ 263953901Smckusick /* case 0xb0: */ /* Caddy not inserted in drive */ 264053901Smckusick /* case 0xb1: */ /* Unable to recover TOC */ 264153901Smckusick /* case 0xb3: */ /* CIRC unrecovered data error(L-EC off) */ 264253901Smckusick /* case 0xc3: */ /* COPY: Illegale CDB length */ 264353901Smckusick /* case 0xc5: */ /* COPY: Catastrophic error */ 264453901Smckusick /* case 0xc6: */ /* COPY: Illegal phase change */ 264553901Smckusick /* case 0xfc: */ /* COPY: MODE SENSE failed */ 264653901Smckusick 264753901Smckusick /* 264853901Smckusick * medium error 264953901Smckusick */ 265053901Smckusick /* case 0x19: */ /* Defect list error */ 265153901Smckusick /* case 0x1c: */ /* Primary Defect List not found */ 265253901Smckusick /* case 0x30: */ /* Incompatible Cartridge */ 265353901Smckusick /* case 0x32: */ /* No Spare Defect Location Available */ 265453901Smckusick /* case 0x3a: */ /* Defect List Update Failure */ 265553901Smckusick /* case 0x3d: */ /* Defect List Not Available */ 265653901Smckusick goto sdintr_error; 265753901Smckusick } 265853901Smckusick /* 265953901Smckusick * No error detected or ignored. 266053901Smckusick */ 266153901Smckusick break; 266253901Smckusick 266353901Smckusick /************************************************/ 266453901Smckusick /* */ 266553901Smckusick /* PREVENT MEDIUM REMOVABLE COMMAND */ 266653901Smckusick /* */ 266753901Smckusick /************************************************/ 266853901Smckusick case SDCS_PREVRMB: 266953901Smckusick if (tstatus == TGST_CC) { 267053901Smckusick sdc->sdc_state = SDCS_PREVRMB|SDCS_RSENSE; 267153901Smckusick goto sdintr_rsense; 267253901Smckusick } 267353901Smckusick sdd->sdd_flags |= SDDF_INHRMV; 267453901Smckusick if (sdc->sdc_state & SDCS_ECC) { 267553901Smckusick sdc->sdc_state = SDCS_RETRY; 267653901Smckusick goto sdintr_msel_reset; 267753901Smckusick } 267853901Smckusick sdc->sdc_state = SDCS_NORMAL; 267953901Smckusick goto sdintr_exec; 268053901Smckusick break; 268153901Smckusick 268253901Smckusick /****************************************/ 268353901Smckusick /* */ 268453901Smckusick /* REZERO done & RETRY COMMAND */ 268553901Smckusick /* */ 268653901Smckusick /****************************************/ 268753901Smckusick case SDCS_ECC|SDCS_ECC_HOLD|SDCS_REZERO: 268853901Smckusick if (sdc->sdc_firmware & SDCFW_DEFMODE) { 268953901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY; 269053901Smckusick goto sdintr_stst; 269153901Smckusick } 269253901Smckusick 269353901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD; 269453901Smckusick goto sdintr_msel_set; 269553901Smckusick 269653901Smckusick /********************************/ 269753901Smckusick /* */ 269853901Smckusick /* RETRY COMMAND */ 269953901Smckusick /* */ 270053901Smckusick /********************************/ 270153901Smckusick case SDCS_RETRY: 270253901Smckusick sdc->sdc_state = SDCS_NORMAL; 270353901Smckusick goto sdintr_exec; 270453901Smckusick 270553901Smckusick /************************************************/ 270653901Smckusick /* */ 270753901Smckusick /* ERROR CORRECTION ON MODE SELECT result */ 270853901Smckusick /* */ 270953901Smckusick /************************************************/ 271053901Smckusick case SDCS_ECC: 271153901Smckusick if (tstatus != TGST_GOOD) { 271253901Smckusick printf("sd%d: bad target status 0x%x\n", 271353901Smckusick unit, sc->sc_tstatus); 271453901Smckusick goto sdintr_error; 271553901Smckusick } 271653901Smckusick sdintr_ecc: 271753901Smckusick if (bp->b_flags & B_READ) { 271853901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASREAD; 271953901Smckusick im->im_tab.b_active = 2; 272053901Smckusick scop_rdwr(intr, sc, slave, SCSI_INTEN, 272153901Smckusick B_READ, sdwork, 272253901Smckusick sdd->sdd_badsect, sdd->sdd_sectsize); 272353901Smckusick return; 272453901Smckusick } 272553901Smckusick goto sdintr_rasblk; 272653901Smckusick 272753901Smckusick /************************************************/ 272853901Smckusick /* */ 272953901Smckusick /* READ DATA from BAD BLOCK result */ 273053901Smckusick /* */ 273153901Smckusick /************************************************/ 273253901Smckusick case SDCS_ECC|SDCS_RASREAD: 273353901Smckusick if (tstatus == TGST_CC) { 273453901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASREAD|SDCS_RSENSE; 273553901Smckusick goto sdintr_rsense; 273653901Smckusick } else if (tstatus != TGST_GOOD) { 273753901Smckusick printf("sd%d: bad target status 0x%x\n", 273853901Smckusick unit, sc->sc_tstatus); 273953901Smckusick printf("sd%d: cannot read block\n", unit); 274053901Smckusick goto sdintr_error; 274153901Smckusick } 274253901Smckusick sdintr_rasblk: 274353901Smckusick if (sdd->sdd_flags & SDDF_WPROTECT) 274453901Smckusick goto sdintr_error; 274553901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASBLK; 274653901Smckusick im->im_tab.b_active = 2; 274753901Smckusick scop_rasblk(intr, sc, slave, SCSI_INTEN, sdd->sdd_badsect); 274853901Smckusick sdd->sdd_flags &= ~SDDF_VBADSECT; 274953901Smckusick return; 275053901Smckusick 275153901Smckusick /****************************************/ 275253901Smckusick /* */ 275353901Smckusick /* REASSIGN BLOCK result */ 275453901Smckusick /* */ 275553901Smckusick /****************************************/ 275653901Smckusick case SDCS_ECC|SDCS_RASBLK: 275753901Smckusick if (tstatus == TGST_CC) { 275853901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE; 275953901Smckusick goto sdintr_rsense; 276053901Smckusick } else if (tstatus != TGST_GOOD) { 276153901Smckusick printf("sd%d: bad target status 0x%x\n", 276253901Smckusick unit, sc->sc_tstatus); 276353901Smckusick goto sdintr_error; 276453901Smckusick } 276553901Smckusick printf("sd%d: block %d is reassigned\n", 276653901Smckusick unit, sdd->sdd_badsect); 276753901Smckusick if (bp->b_flags & B_READ) { 276853901Smckusick sdintr_raswrite: 276953901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASWRITE; 277053901Smckusick im->im_tab.b_active = 2; 277153901Smckusick scop_rdwr(intr, sc, slave, SCSI_INTEN, 277253901Smckusick B_WRITE, sdwork, 277353901Smckusick sdd->sdd_badsect, sdd->sdd_sectsize); 277453901Smckusick return; 277553901Smckusick } 277653901Smckusick sdc->sdc_state = SDCS_RETRY; 277753901Smckusick goto sdintr_msel_reset; 277853901Smckusick 277953901Smckusick /************************************************/ 278053901Smckusick /* */ 278153901Smckusick /* WRITE DATA to REASSIGNED BLOCK result */ 278253901Smckusick /* */ 278353901Smckusick /************************************************/ 278453901Smckusick case SDCS_ECC|SDCS_RASWRITE: 278553901Smckusick if (tstatus == TGST_CC) { 278653901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASWRITE|SDCS_RSENSE; 278753901Smckusick goto sdintr_rsense; 278853901Smckusick } else if (tstatus != TGST_GOOD) { 278953901Smckusick printf("sd%d: bad target status 0x%x\n", 279053901Smckusick unit, sc->sc_tstatus); 279153901Smckusick goto sdintr_error; 279253901Smckusick } 279353901Smckusick sdc->sdc_state = SDCS_RETRY; 279453901Smckusick goto sdintr_msel_reset; 279553901Smckusick 279653901Smckusick /****************************************/ 279753901Smckusick /* */ 279853901Smckusick /* reset ECC & RETRY TIMES */ 279953901Smckusick /* */ 280053901Smckusick /****************************************/ 280153901Smckusick case SDCS_ECCOFF|SDCS_RETRY: 280253901Smckusick sdc->sdc_state = SDCS_RETRY; 280353901Smckusick goto sdintr_msel_reset; 280453901Smckusick 280553901Smckusick /********************************************************/ 280653901Smckusick /* */ 280753901Smckusick /* READ DATA from BAD BLOCK result in faliure */ 280853901Smckusick /* */ 280953901Smckusick /********************************************************/ 281053901Smckusick case SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA: 281153901Smckusick if (tstatus == TGST_CC) { 281253901Smckusick sdc->sdc_state = 281353901Smckusick SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE; 281453901Smckusick goto sdintr_rsense; 281553901Smckusick } else if (tstatus != TGST_GOOD) { 281653901Smckusick printf("sd%d: rasblk: bad target status 0x%x\n", 281753901Smckusick unit, sc->sc_tstatus); 281853901Smckusick goto sdintr_error; 281953901Smckusick } 282053901Smckusick bzero(sdwork, sdd->sdd_sectsize); 282153901Smckusick scop_rdwr(intr, sc, slave, SCSI_INTDIS, 282253901Smckusick B_WRITE, sdwork, sdd->sdd_badsect, sdd->sdd_sectsize); 282353901Smckusick printf("sd%d: block %d is reassigned (lost data)\n", 282453901Smckusick unit, sdd->sdd_badsect); 282553901Smckusick goto sdintr_error; 282653901Smckusick 282753901Smckusick /****************************************/ 282853901Smckusick /* */ 282953901Smckusick /* issue START UNIT command */ 283053901Smckusick /* */ 283153901Smckusick /****************************************/ 283253901Smckusick case SDCS_ECC|SDCS_ECC_HOLD: 283353901Smckusick /* 283453901Smckusick * Drive not ready... so start.. 283553901Smckusick */ 283653901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY; 283753901Smckusick sdintr_stst: 283853901Smckusick timeout(delay_start, (caddr_t)ii, hz); 283953901Smckusick return; 284053901Smckusick 284153901Smckusick /****************************************/ 284253901Smckusick /* */ 284353901Smckusick /* RETRY with ECC & more RETRYS */ 284453901Smckusick /* */ 284553901Smckusick /****************************************/ 284653901Smckusick case SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY: 284753901Smckusick sdc->sdc_state = SDCS_ECCOFF; 284853901Smckusick sdintr_exec: 284953901Smckusick if (sdc->sdc_countcc++ > MAXRETRYCNT) 285053901Smckusick goto sdintr_error; 285153901Smckusick sdexec(bp); 285253901Smckusick return; 285353901Smckusick 285453901Smckusick /****************************************/ 285553901Smckusick /* */ 285653901Smckusick /* reset ECC & RETRY TIMES */ 285753901Smckusick /* */ 285853901Smckusick /****************************************/ 285953901Smckusick case SDCS_ECCOFF: 286053901Smckusick if (tstatus == TGST_CC) { 286153901Smckusick sdc->sdc_state = SDCS_ECCOFF|SDCS_RSENSE; 286253901Smckusick goto sdintr_rsense; 286353901Smckusick } else if (tstatus != TGST_GOOD) { 286453901Smckusick printf("sd%d: bad target status 0x%x\n", 286553901Smckusick unit, sc->sc_tstatus); 286653901Smckusick goto sdintr_error; 286753901Smckusick } 286853901Smckusick sdc->sdc_state = SDCS_NORMAL; 286953901Smckusick goto sdintr_msel_reset; 287053901Smckusick 287153901Smckusick sdintr_msel_set: 287253901Smckusick /* 287353901Smckusick * set more ERROR RECOVERY PARAMETERS 287453901Smckusick */ 287553901Smckusick if ((erp_page = sdi->max_ERP_page) == NULL) 287653901Smckusick goto check_target_status; 287753901Smckusick bzero((caddr_t)sc->sc_param, 4); 287853901Smckusick len = *(erp_page + 1) + 2; 287953901Smckusick bcopy(erp_page, &sc->sc_param[4], len); 288053901Smckusick 288153901Smckusick im->im_tab.b_active = 2; 288253901Smckusick scop_mselect(intr, sc, slave, SCSI_INTEN, 288353901Smckusick (SDM_PF<<24) + len +4, (caddr_t)0); 288453901Smckusick return; 288553901Smckusick 288653901Smckusick sdintr_msel_reset: 288753901Smckusick if (sdc->sdc_firmware & SDCFW_DEFMODE) 288853901Smckusick goto sdintr_exec; 288953901Smckusick 289053901Smckusick /* 289153901Smckusick * set normal ERROR RECOVERY PARAMETERS 289253901Smckusick */ 289353901Smckusick erp_page = sdi->ERP_page; 289453901Smckusick bzero((caddr_t)sc->sc_param, 4); 289553901Smckusick len = *(erp_page + 1) + 2; 289653901Smckusick bcopy(erp_page, &sc->sc_param[4], len); 289753901Smckusick 289853901Smckusick im->im_tab.b_active = 2; 289953901Smckusick scop_mselect(intr, sc, slave, SCSI_INTEN, 290053901Smckusick (SDM_PF<<24) + len +4, (caddr_t)0); 290153901Smckusick return; 290253901Smckusick 290353901Smckusick sdintr_error: 290453901Smckusick bp->b_flags |= B_ERROR; 290553901Smckusick if (sdc->sdc_state & SDCS_ECC) { 290653901Smckusick sdc->sdc_state = SDCS_NORMAL; 290753901Smckusick goto sdintr_msel_reset; 290853901Smckusick } 290953901Smckusick break; 291053901Smckusick 291153901Smckusick /* 291253901Smckusick * UNKNOWN STATUS 291353901Smckusick */ 291453901Smckusick default: 291553901Smckusick printf("sd%d: unknown status (0x%x)\n", unit, sdc->sdc_state); 291653901Smckusick goto sdintr_error; 291753901Smckusick } 291853901Smckusick 291953901Smckusick sdintr_done: 292053901Smckusick 292153901Smckusick if (bp->b_flags & B_ERROR) { 292253901Smckusick printf("%s%d%c: hard error sn%d ", "sd", 292353901Smckusick minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 292453901Smckusick printf("\n"); 292553901Smckusick } 292653901Smckusick sdd->sdd_lastblk = dkblock(bp) + btodb(bp->b_bcount - bp->b_resid); 292753901Smckusick sdc->sdc_countcc = 0; 292853901Smckusick sdc->sdc_retrycnt = 0; 292953901Smckusick sdd->sdd_flags &= ~SDDF_VBADSECT; 293053901Smckusick 293153901Smckusick if (im->im_tab.b_active) { 293253901Smckusick im->im_tab.b_active = 0; 293353901Smckusick im->im_tab.b_errcnt = 0; 2934*57612Sutashiro im->im_tab.b_actf = 0; 293553901Smckusick dp->b_active = 0; 293653901Smckusick dp->b_errcnt = 0; 2937*57612Sutashiro dp->b_actf = bp->b_actf; 293853901Smckusick if (bp == &csdbuf[unit]) { 293953901Smckusick register struct scsi *ksc = &kernscsi[unit]; 294053901Smckusick /* copy result */ 294153901Smckusick bcopy((caddr_t)sc, (caddr_t)ksc, sizeof(struct scsi)); 294253901Smckusick } 294353901Smckusick 294453901Smckusick iodone(bp); 294553901Smckusick 294653901Smckusick /* 294753901Smckusick * If this unit has more work to do, 294853901Smckusick * then start it up right away. 294953901Smckusick */ 295053901Smckusick if (dp->b_actf) 295153901Smckusick sdustart(ii); 295253901Smckusick } 295353901Smckusick as &= ~(1 << slave); 295453901Smckusick 295553901Smckusick sdc->sdc_state = SDCS_NORMAL; 295653901Smckusick 295753901Smckusick /* 295853901Smckusick * UNLOCK SCSI access 295953901Smckusick */ 296053901Smckusick sdc->sdc_firmware &= ~SDCFW_BUSY; 296153901Smckusick 296253901Smckusick start: 296353901Smckusick /* 296453901Smckusick * Process other units which need attention. 296553901Smckusick * For each unit which needs attention, call 296653901Smckusick * the unit start routine to place the slave 296753901Smckusick * on the controller device queue. 296853901Smckusick */ 296953901Smckusick sdc->sdc_softas = 0; 297053901Smckusick while (unit = ffs(as)) { 297153901Smckusick unit--; 297253901Smckusick as &= ~(1 << unit); 297353901Smckusick sdustart(sdip[im->im_ctlr][unit]); 297453901Smckusick } 297553901Smckusick /* 297653901Smckusick * If the controller is not transferring, 297753901Smckusick * but there are devices ready to transfer, 297853901Smckusick * start the controller. 297953901Smckusick */ 298053901Smckusick if (im->im_tab.b_actf && im->im_tab.b_active == 0) 298153901Smckusick (void) sdstart(im); 298253901Smckusick } 298353901Smckusick 298453901Smckusick wait_re_init_done(bp) 298553901Smckusick register struct buf *bp; 298653901Smckusick { 298753901Smckusick if (re_init_done >= 2) 298853901Smckusick sdexec(bp); 298953901Smckusick else 299053901Smckusick timeout(wait_re_init_done, bp, 10*hz); 299153901Smckusick } 299253901Smckusick 299353901Smckusick delay_start(ii) 299453901Smckusick struct iop/**/_device *ii; 299553901Smckusick { 299653901Smckusick ii->ii_mi->im_tab.b_active = 2; 299753901Smckusick scop_stst(ii->ii_intr, get_scsi(ii->ii_intr), ii->ii_slave, 299853901Smckusick SCSI_INTEN, SDSS_START); 299953901Smckusick } 300053901Smckusick 300153901Smckusick delay_medrmv(ii) 300253901Smckusick struct iop/**/_device *ii; 300353901Smckusick { 300453901Smckusick ii->ii_mi->im_tab.b_active = 2; 300553901Smckusick scop_medrmv(ii->ii_intr, get_scsi(ii->ii_intr), ii->ii_slave, 300653901Smckusick SCSI_INTEN, SDRMV_PREV); 300753901Smckusick } 300853901Smckusick 300953901Smckusick sderrordisp(rsen_data, ii) 301053901Smckusick u_char *rsen_data; 301153901Smckusick struct iop/**/_device *ii; 301253901Smckusick { 301353901Smckusick register struct sc_extnd *sce; 301453901Smckusick register struct sdc_softc *sdc; 301553901Smckusick register struct sdd_softc *sdd; 301653901Smckusick register int unit; 301753901Smckusick register int code; 301853901Smckusick struct sc_nextnd *scn; 301953901Smckusick struct msg_list *ml; 302053901Smckusick 302153901Smckusick unit = ii->ii_unit; 302253901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 302353901Smckusick sdd = &sdd_softc[unit]; 302453901Smckusick 302553901Smckusick sce = (struct sc_extnd *)rsen_data; 302653901Smckusick 302753901Smckusick if (sce->sce_extend == 0x70) { 302853901Smckusick /* 302953901Smckusick * Extended Sense data 303053901Smckusick */ 303153901Smckusick code = sce->sce_sdecode; 303253901Smckusick 303353901Smckusick if (code & 0x80) 303453901Smckusick ml = ecodelist_mo; 303553901Smckusick else 303653901Smckusick ml = ecodelist; 303753901Smckusick 303853901Smckusick if (sce->sce_advalid) { 303953901Smckusick if ((sdd->sdd_flags & SDDF_VBADSECT) == 0) { 304053901Smckusick #ifdef mips 304153901Smckusick sdd->sdd_badsect = (sce->sce_infob1 << 24) + 304253901Smckusick (sce->sce_infob2 << 16) + 304353901Smckusick (sce->sce_infob3 << 8) + 304453901Smckusick (sce->sce_infob4); 304553901Smckusick #else 304653901Smckusick sdd->sdd_badsect = *((int *)&sce->sce_infob1); 304753901Smckusick #endif 304853901Smckusick sdd->sdd_flags |= SDDF_VBADSECT; 304953901Smckusick } 305053901Smckusick } 305153901Smckusick 305253901Smckusick if (!rsense_msg_disp && !isdispmsg(code, ml, sdc->sdc_countcc)) 305353901Smckusick return (code); 305453901Smckusick 305553901Smckusick if (sce->sce_advalid) { 305653901Smckusick int sn; 305753901Smckusick #ifdef mips 305853901Smckusick sn = (sce->sce_infob1 << 24) + 305953901Smckusick (sce->sce_infob2 << 16) + 306053901Smckusick (sce->sce_infob3 << 8) + 306153901Smckusick (sce->sce_infob4); 306253901Smckusick #else 306353901Smckusick sn = *((int *)&sce->sce_infob1); 306453901Smckusick #endif 306553901Smckusick if (sce->sce_addlen >= 5) { 306653901Smckusick printf("sd%d(sn %d): skey=0x%x, code=0x%x\n", 306753901Smckusick unit, sn, sce->sce_skey, code); 306853901Smckusick } else { 306953901Smckusick printf("sd%d(sn %d): skey=0x%x\n", 307053901Smckusick unit, sn, sce->sce_skey); 307153901Smckusick } 307253901Smckusick } else { 307353901Smckusick if (sce->sce_addlen >= 5) 307453901Smckusick printf("sd%d: skey=0x%x, code=0x%x\n", 307553901Smckusick unit, sce->sce_skey, code); 307653901Smckusick else 307753901Smckusick printf("sd%d: skey=0x%x\n", 307853901Smckusick unit, sce->sce_skey); 307953901Smckusick } 308053901Smckusick if (sce->sce_addlen >= 6) 308153901Smckusick printf("sd%d: ASCQ=0x%x\n", unit, sce->sce_ascq); 308253901Smckusick { 308353901Smckusick u_char *p; 308453901Smckusick int len; 308553901Smckusick 308653901Smckusick len = 8 + sce->sce_addlen; 308753901Smckusick if (len > RSEN_CNT) 308853901Smckusick len = RSEN_CNT; 308953901Smckusick p = (u_char *)sce; 309053901Smckusick printf("sd%d: ", unit); 309153901Smckusick while (len--) 309253901Smckusick printf("%x ", *p++); 309353901Smckusick printf("\n"); 309453901Smckusick } 309553901Smckusick } else { 309653901Smckusick /* 309753901Smckusick * Non-extended Sense data 309853901Smckusick */ 309953901Smckusick scn = (struct sc_nextnd *)rsen_data; 310053901Smckusick 310153901Smckusick code = scn->scn_ecode; 310253901Smckusick ml = ecodelist; 310353901Smckusick if (sce->sce_advalid) { 310453901Smckusick if ((sdd->sdd_flags & SDDF_VBADSECT) == 0) { 310553901Smckusick sdd->sdd_badsect = scn->scn_secno; 310653901Smckusick sdd->sdd_flags |= SDDF_VBADSECT; 310753901Smckusick } 310853901Smckusick } 310953901Smckusick if (rsense_msg_disp || isdispmsg(code, ml, sdc->sdc_countcc)) { 311053901Smckusick if (sce->sce_advalid) 311153901Smckusick printf("sd%d(sn %d): code=0x%x\n", 311253901Smckusick unit, scn->scn_secno, code); 311353901Smckusick else 311453901Smckusick printf("sd%d: code=0x%x\n", unit, code); 311553901Smckusick } 311653901Smckusick } 311753901Smckusick return (code); 311853901Smckusick } 311953901Smckusick 312053901Smckusick void 312153901Smckusick sdminphys(bp) 312253901Smckusick struct buf *bp; 312353901Smckusick { 312453901Smckusick if (bp->b_bcount > MAXSDPHYS) 312553901Smckusick bp->b_bcount = MAXSDPHYS; 312653901Smckusick } 312753901Smckusick 312853901Smckusick 312953901Smckusick #define sdphysio physio 313053901Smckusick 313153901Smckusick sdread(dev, uio, flag) 313253901Smckusick register dev_t dev; 313353901Smckusick struct uio *uio; 313453901Smckusick int flag; 313553901Smckusick { 313653901Smckusick register struct iop/**/_device *ii; 313753901Smckusick register int unit; 313853901Smckusick 313953901Smckusick unit = dev2unit(dev); 314053901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0) 314153901Smckusick return (ENXIO); 314253901Smckusick 314353901Smckusick return (sdphysio(sdstrategy, &rsdbuf[unit], dev, B_READ, sdminphys, uio)); 314453901Smckusick } 314553901Smckusick 314653901Smckusick sdwrite(dev, uio, flag) 314753901Smckusick register dev_t dev; 314853901Smckusick struct uio *uio; 314953901Smckusick int flag; 315053901Smckusick { 315153901Smckusick register struct iop/**/_device *ii; 315253901Smckusick register int unit; 315353901Smckusick 315453901Smckusick unit = dev2unit(dev); 315553901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0) 315653901Smckusick return (ENXIO); 315753901Smckusick 315853901Smckusick return (sdphysio(sdstrategy, &rsdbuf[unit], dev, B_WRITE, sdminphys, uio)); 315953901Smckusick } 316053901Smckusick 316153901Smckusick #define MAXBL 256 316253901Smckusick 316353901Smckusick /*ARGSUSED*/ 316453901Smckusick sdioctl(dev, cmd, data, flag) 316553901Smckusick dev_t dev; 316653901Smckusick int cmd; 316753901Smckusick caddr_t data; 316853901Smckusick int flag; 316953901Smckusick { 317053901Smckusick register struct iop/**/_device *ii; 317153901Smckusick register struct sc_ureq *scu; 317253901Smckusick register struct sdst *st; 317353901Smckusick register struct scsi *sc; 317453901Smckusick register int unit; 317553901Smckusick register int ctlr; 317653901Smckusick register int slave; 317753901Smckusick struct sdc_softc *sdc; 317853901Smckusick struct sdd_softc *sdd; 317953901Smckusick struct Partinfo *pi; 318053901Smckusick struct dkst *di; 318153901Smckusick struct buf *bp; 318253901Smckusick struct sddevinfo *sdi; 318353901Smckusick struct sdst *stp; 318453901Smckusick struct scsi uscsi; 318553901Smckusick int error; 318653901Smckusick int i; 318753901Smckusick int s; 318853901Smckusick int tstatus; 318953901Smckusick char *p; 319053901Smckusick int blkno, count; 319153901Smckusick 319253901Smckusick unit = dev2unit(dev); 319353901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) 319453901Smckusick return (ENXIO); 319553901Smckusick 319653901Smckusick slave = ii->ii_slave; 319753901Smckusick ctlr = ii->ii_ctlr; 319853901Smckusick sdc = &sdc_softc[ctlr]; 319953901Smckusick sdd = &sdd_softc[unit]; 320053901Smckusick sc = &uscsi; 320153901Smckusick 320253901Smckusick error = 0; 320353901Smckusick switch (cmd) { 320453901Smckusick 320553901Smckusick case DIOCWLABEL: 320653901Smckusick if (*(int *)data & SD_F_ENW) 320753901Smckusick ii->ii_flags |= SD_F_ENW; 320853901Smckusick else 320953901Smckusick ii->ii_flags &= ~SD_F_ENW; 321053901Smckusick break; 321153901Smckusick 321253901Smckusick case DIOCGDINFO: 321353901Smckusick *(struct disklabel *)data = sdlabel[unit]; 321453901Smckusick break; 321553901Smckusick 321653901Smckusick case DIOCSDINFO: 321753901Smckusick sdlabel[unit] = *(struct disklabel *)data; 321853901Smckusick disklabel2sdst(unit, &sdlabel[unit], &sdstdrv[unit]); 321953901Smckusick break; 322053901Smckusick 322153901Smckusick case DIOCWDINFO: 322253901Smckusick case DKIOCRGEOM: 322353901Smckusick switch (cmd) { 322453901Smckusick case DKIOCRGEOM: 322553901Smckusick st = &sdstdrv[unit]; 322653901Smckusick sdi = &sddevinfo[ii->ii_type]; 322753901Smckusick stp = sdi->sdstp; 322853901Smckusick 322953901Smckusick st->ncyl = stp->ncyl; /* # cylinders / drive */ 323053901Smckusick st->ntrak = stp->ntrak; /* # tracks / cylinder */ 323153901Smckusick st->nsect = stp->nsect; /* # sectors / track */ 323253901Smckusick st->rps = stp->rps; /* # revolutions / second */ 323353901Smckusick 323453901Smckusick sdst2disklabel(unit, st, &sdlabel[unit]); 323553901Smckusick 323653901Smckusick if (*(int *)data == RGEOM_SDINFO) 323753901Smckusick goto done; 323853901Smckusick 323953901Smckusick break; 324053901Smckusick 324153901Smckusick case DIOCWDINFO: 324253901Smckusick sdlabel[unit] = *(struct disklabel *)data; 324353901Smckusick 324453901Smckusick break; 324553901Smckusick } 324653901Smckusick 324753901Smckusick /* 324853901Smckusick * Common code for DIOCWDINFO and DKIOCRGEOM 324953901Smckusick */ 325053901Smckusick 325153901Smckusick /**** READ sector 0 ****/ 325253901Smckusick /* 325353901Smckusick * LOCK sdtmp buffer 325453901Smckusick */ 325553901Smckusick s = splclock(); 325653901Smckusick while (sdtmp_stat & B_BUSY) { 325753901Smckusick sdtmp_stat |= B_WANTED; 325853901Smckusick sleep((caddr_t)sdtmp, PRIBIO); 325953901Smckusick } 326053901Smckusick sdtmp_stat |= B_BUSY; 326153901Smckusick splx(s); 326253901Smckusick 326353901Smckusick bzero(sdtmp, DEV_BSIZE); 326453901Smckusick 326553901Smckusick if ((sdd->sdd_flags & SDDF_NONFMT) == 0) { 326653901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 326753901Smckusick uscsi.sc_cpoint = sdtmp; 326853901Smckusick uscsi.sc_ctrnscnt = DEV_BSIZE; 326953901Smckusick uscsi.sc_opcode = SCOP_READ; 327053901Smckusick uscsi.sc_lad = 0; 327153901Smckusick uscsi.sc_count = 1; 327253901Smckusick error = sdcmd(dev, &uscsi); 327353901Smckusick } else { 327453901Smckusick error = EIO; 327553901Smckusick } 327653901Smckusick 327753901Smckusick if (error) { 327853901Smckusick /* 327953901Smckusick * UNLOCK sdtmp buffer 328053901Smckusick */ 328153901Smckusick s = splclock(); 328253901Smckusick if (sdtmp_stat & B_WANTED) 328353901Smckusick wakeup((caddr_t)sdtmp); 328453901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 328553901Smckusick splx(s); 328653901Smckusick 328753901Smckusick break; 328853901Smckusick } 328953901Smckusick 329053901Smckusick *(struct disklabel *)(sdtmp + LABELOFFSET) = sdlabel[unit]; 329153901Smckusick disklabel2diskinfo(unit, &sdlabel[unit], 329253901Smckusick &((struct firstsector *)sdtmp)->diskinfo); 329353901Smckusick 329453901Smckusick /**** WRITE sector 0 ****/ 329553901Smckusick 329653901Smckusick if (error == 0) { 329753901Smckusick if ((sdd->sdd_flags & SDDF_NONFMT) == 0) { 329853901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 329953901Smckusick uscsi.sc_cpoint = sdtmp; 330053901Smckusick uscsi.sc_ctrnscnt = DEV_BSIZE; 330153901Smckusick uscsi.sc_opcode = SCOP_WRITE; 330253901Smckusick 330353901Smckusick uscsi.sc_lad = 0; 330453901Smckusick uscsi.sc_count = 1; 330553901Smckusick 330653901Smckusick error = sdcmd(dev, &uscsi); 330753901Smckusick } else 330853901Smckusick error = EIO; 330953901Smckusick } 331053901Smckusick 331153901Smckusick /* 331253901Smckusick * UNLOCK sdtmp buffer 331353901Smckusick */ 331453901Smckusick s = splclock(); 331553901Smckusick if (sdtmp_stat & B_WANTED) 331653901Smckusick wakeup((caddr_t)sdtmp); 331753901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 331853901Smckusick splx(s); 331953901Smckusick 332053901Smckusick disklabel2sdst(unit, &sdlabel[unit], &sdstdrv[unit]); 332153901Smckusick 332253901Smckusick break; 332353901Smckusick 332453901Smckusick case DKIOCGGEOM: 332553901Smckusick st = &sdstdrv[unit]; 332653901Smckusick di = (struct dkst *)data; 332753901Smckusick 332853901Smckusick di->dks_ncyl = st->ncyl; /* # cylinders / drive */ 332953901Smckusick di->dks_ntrak = st->ntrak; /* # tracks / cylinder */ 333053901Smckusick di->dks_nsect = st->nsect; /* # sectors / track */ 333153901Smckusick di->dks_rps = st->rps; /* # revolutions / second */ 333253901Smckusick 333353901Smckusick break; 333453901Smckusick 333553901Smckusick case DKIOCSGEOM: 333653901Smckusick st = &sdstdrv[unit]; 333753901Smckusick di = (struct dkst *)data; 333853901Smckusick 333953901Smckusick st->ncyl = di->dks_ncyl; /* # cylinders / drive */ 334053901Smckusick st->ntrak = di->dks_ntrak; /* # tracks / cylinder */ 334153901Smckusick st->nsect = di->dks_nsect; /* # sectors / track */ 334253901Smckusick st->rps = di->dks_rps; /* # revolutions / second */ 334353901Smckusick 334453901Smckusick sdst2disklabel(unit, st, &sdlabel[unit]); 334553901Smckusick break; 334653901Smckusick 334753901Smckusick case DKIOCGPART: 334853901Smckusick case DKIOCSPART: 334953901Smckusick /* 335053901Smckusick * partition information 335153901Smckusick */ 335253901Smckusick st = &sdstdrv[unit]; 335353901Smckusick pi = (struct Partinfo *)data; 335453901Smckusick 335553901Smckusick if (cmd == DKIOCGPART) { 335653901Smckusick pi->dp_nblocks = st->sizes[dev2part(dev)].sd_nblocks; 335753901Smckusick pi->dp_blkoff = st->sizes[dev2part(dev)].sd_blkoff; 335853901Smckusick } else { 335953901Smckusick st->sizes[dev2part(dev)].sd_nblocks = pi->dp_nblocks; 336053901Smckusick st->sizes[dev2part(dev)].sd_blkoff = pi->dp_blkoff; 336153901Smckusick 336253901Smckusick sdst2disklabel(unit, st, &sdlabel[unit]); 336353901Smckusick } 336453901Smckusick break; 336553901Smckusick 336653901Smckusick case DKIOCGUNIT: 336753901Smckusick *(int *)data = slave; 336853901Smckusick break; 336953901Smckusick 337053901Smckusick case DKIOCGCHAN: 337153901Smckusick *(int *)data = ii->ii_intr; 337253901Smckusick break; 337353901Smckusick 337453901Smckusick case DKIOCSEEK: 337553901Smckusick scinit(sc, slave, sdd->sdd_sectsize); 337653901Smckusick sc->sc_opcode = SCOP_SEEK; 337753901Smckusick sc->sc_lad = *(int *)data; 337853901Smckusick 337953901Smckusick (void) sdcmd(dev, sc); 338053901Smckusick tstatus = sc->sc_tstatus & TGSTMASK; 338153901Smckusick if ((sc->sc_istatus != INST_EP) || (tstatus != TGST_GOOD)) 338253901Smckusick error = ESPIPE; 338353901Smckusick break; 338453901Smckusick 338553901Smckusick case DKIOCRSEC0: 338653901Smckusick case DKIOCRBOOT1: 338753901Smckusick case DKIOCRBOOT: 338853901Smckusick if (sdd->sdd_flags & SDDF_NONFMT) { 338953901Smckusick error = EIO; 339053901Smckusick break; 339153901Smckusick } 339253901Smckusick switch (cmd) { 339353901Smckusick 339453901Smckusick case DKIOCRSEC0: 339553901Smckusick blkno = 0; 339653901Smckusick count = 1; 339753901Smckusick break; 339853901Smckusick 339953901Smckusick case DKIOCRBOOT1: 340053901Smckusick blkno = 1; 340153901Smckusick count = 15; 340253901Smckusick break; 340353901Smckusick 340453901Smckusick default: 340553901Smckusick blkno = 0; 340653901Smckusick count = 16; 340753901Smckusick } 340853901Smckusick p = (char *)*(int *)data; 340953901Smckusick for (i = 0; !error && i < count; i++) { 341053901Smckusick s = splclock(); 341153901Smckusick while (sdtmp_stat & B_BUSY) { 341253901Smckusick sdtmp_stat |= B_WANTED; 341353901Smckusick sleep((caddr_t)sdtmp, PRIBIO); 341453901Smckusick } 341553901Smckusick sdtmp_stat |= B_BUSY; 341653901Smckusick splx(s); 341753901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 341853901Smckusick uscsi.sc_cpoint = sdtmp; 341953901Smckusick uscsi.sc_ctrnscnt = DEV_BSIZE; 342053901Smckusick uscsi.sc_opcode = SCOP_READ; 342153901Smckusick uscsi.sc_lad = blkno; 342253901Smckusick uscsi.sc_count = 1; 342353901Smckusick if (error = sdcmd(dev, &uscsi)) 342453901Smckusick goto dkior_done; 342553901Smckusick if (error = copyout(sdtmp, p, DEV_BSIZE)) 342653901Smckusick goto dkior_done; 342753901Smckusick blkno++; 342853901Smckusick p += DEV_BSIZE; 342953901Smckusick 343053901Smckusick dkior_done: 343153901Smckusick s = splclock(); 343253901Smckusick if (sdtmp_stat & B_WANTED) 343353901Smckusick wakeup((caddr_t)sdtmp); 343453901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 343553901Smckusick splx(s); 343653901Smckusick } 343753901Smckusick break; 343853901Smckusick 343953901Smckusick case DKIOCWSEC0: 344053901Smckusick case DKIOCWBOOT1: 344153901Smckusick case DKIOCWBOOT: 344253901Smckusick if (sdd->sdd_flags & SDDF_NONFMT) { 344353901Smckusick error = EIO; 344453901Smckusick break; 344553901Smckusick } 344653901Smckusick switch (cmd) { 344753901Smckusick 344853901Smckusick case DKIOCWSEC0: 344953901Smckusick blkno = 0; 345053901Smckusick count = 1; 345153901Smckusick break; 345253901Smckusick 345353901Smckusick case DKIOCWBOOT1: 345453901Smckusick blkno = 1; 345553901Smckusick count = 15; 345653901Smckusick break; 345753901Smckusick 345853901Smckusick default: 345953901Smckusick blkno = 0; 346053901Smckusick count = 16; 346153901Smckusick } 346253901Smckusick p = (char *)*(int *)data; 346353901Smckusick for (i = 0; !error && i < count; i++) { 346453901Smckusick s = splclock(); 346553901Smckusick while (sdtmp_stat & B_BUSY) { 346653901Smckusick sdtmp_stat |= B_WANTED; 346753901Smckusick sleep(sdtmp, PRIBIO); 346853901Smckusick } 346953901Smckusick sdtmp_stat |= B_BUSY; 347053901Smckusick splx(s); 347153901Smckusick if (error = copyin(p, sdtmp, DEV_BSIZE)) 347253901Smckusick goto dkiow_done; 347353901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 347453901Smckusick uscsi.sc_cpoint = sdtmp; 347553901Smckusick uscsi.sc_ctrnscnt = DEV_BSIZE; 347653901Smckusick uscsi.sc_opcode = SCOP_WRITE; 347753901Smckusick uscsi.sc_lad = blkno; 347853901Smckusick uscsi.sc_count = 1; 347953901Smckusick if (error = sdcmd(dev, &uscsi)) 348053901Smckusick goto dkiow_done; 348153901Smckusick blkno++; 348253901Smckusick p += DEV_BSIZE; 348353901Smckusick 348453901Smckusick dkiow_done: 348553901Smckusick s = splclock(); 348653901Smckusick if (sdtmp_stat & B_WANTED) 348753901Smckusick wakeup(sdtmp); 348853901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 348953901Smckusick splx(s); 349053901Smckusick } 349153901Smckusick break; 349253901Smckusick 349353901Smckusick case SDIOC_PRVRMV: 349453901Smckusick case SDIOC_ALWRMV: 349553901Smckusick /* 349653901Smckusick * prevent/allow medium removal 349753901Smckusick */ 349853901Smckusick scinit(sc, ii->ii_slave, sdd->sdd_sectsize); 349953901Smckusick sc->sc_opcode = SCOP_MEDRMV; 350053901Smckusick sc->sc_count = (cmd==SDIOC_PRVRMV)? SDRMV_PREV : SDRMV_ALLOW; 350153901Smckusick if (cmd == SDIOC_PRVRMV) 350253901Smckusick sdd->sdd_flags |= SDDF_INHRMV; 350353901Smckusick else 350453901Smckusick sdd->sdd_flags &= ~SDDF_INHRMV; 350553901Smckusick 350653901Smckusick error = sdcmd(dev, sc); 350753901Smckusick break; 350853901Smckusick 350953901Smckusick case SDIOC_SXUSE: 351053901Smckusick if (isalone(unit) != ONLY_ONE) 351153901Smckusick return (EBUSY); 351253901Smckusick sdd->sdd_flags |= SDDF_XUSE; 351353901Smckusick break; 351453901Smckusick 351553901Smckusick case SDIOC_RXUSE: 351653901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 351753901Smckusick break; 351853901Smckusick 351953901Smckusick case SDIOC_ERSON: 352053901Smckusick sdd->sdd_flags &= ~SDDF_ERASEOFF; 352153901Smckusick break; 352253901Smckusick 352353901Smckusick case SDIOC_ERSOFF: 352453901Smckusick if ((sdd->sdd_flags & SDDF_XUSE) != 0) 352553901Smckusick return (EBUSY); 352653901Smckusick sdd->sdd_flags |= SDDF_ERASEOFF; 352753901Smckusick sdd->sdd_flags &= ~SDDF_NONFMT; 352853901Smckusick break; 352953901Smckusick 353053901Smckusick case SDIOC_FORMAT: 353153901Smckusick /* 353253901Smckusick * format unit 353353901Smckusick */ 353453901Smckusick if ((flag & FWRITE) == 0) 353553901Smckusick return (EINVAL); 353653901Smckusick if (isalone(unit) != ONLY_ONE) 353753901Smckusick return (EBUSY); 353853901Smckusick sdd->sdd_flags |= SDDF_XUSE; 353953901Smckusick sdd->sdd_flags &= ~(SDDF_NONFMT|SDDF_FMTDONE|SDDF_SAMEDSK); 354053901Smckusick scinit(sc, ii->ii_slave, sdd->sdd_sectsize); 354153901Smckusick sc->sc_ctrnscnt = 4; 354253901Smckusick sc->sc_opcode = SCOP_FMT; 354353901Smckusick 354453901Smckusick sc->sc_lad = ((sddevinfo[ii->ii_type].fmt_opts & FMT_DLFMT) 354553901Smckusick | SDF_FMTDAT) << 16; 354653901Smckusick 354753901Smckusick switch (sddevinfo[ii->ii_type].type) { 354853901Smckusick 354953901Smckusick case SMO_S501: 355053901Smckusick case SMO_S501_ISO: 355153901Smckusick case SMO_S501_ISO2: 355253901Smckusick sc->sc_lad |= ((SDF_MKCDA|SDF_MKPLST) << 8); 355353901Smckusick break; 355453901Smckusick 355553901Smckusick default: 355653901Smckusick break; 355753901Smckusick } 355853901Smckusick 355953901Smckusick { 356053901Smckusick struct fmt_data *fdata = (struct fmt_data *)data; 356153901Smckusick 356253901Smckusick error = copyin((caddr_t)fdata->dlh, sc->sc_param, 4); 356353901Smckusick if (error != 0) { 356453901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 356553901Smckusick break; 356653901Smckusick } 356753901Smckusick if (fdata->noglist) 356853901Smckusick sc->sc_lad |= (SDF_CMPLST<<16); 356953901Smckusick } 357053901Smckusick 357153901Smckusick if (sdd->sdd_flags & SDDF_ERASEOFF) 357253901Smckusick sc->sc_ctrl = 0x40; 357353901Smckusick 357453901Smckusick error = sdcmd(dev, sc); 357553901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 357653901Smckusick break; 357753901Smckusick 357853901Smckusick case SDIOC_FORMAT2: 357953901Smckusick /* 358053901Smckusick * format unit 358153901Smckusick */ 358253901Smckusick if ((flag & FWRITE) == 0) 358353901Smckusick return (EINVAL); 358453901Smckusick if (isalone(unit) != ONLY_ONE) 358553901Smckusick return (EBUSY); 358653901Smckusick sdd->sdd_flags |= SDDF_XUSE; 358753901Smckusick sdd->sdd_flags &= ~(SDDF_NONFMT|SDDF_FMTDONE|SDDF_SAMEDSK); 358853901Smckusick 358953901Smckusick scu = (struct sc_ureq *)data; 359053901Smckusick error = sd_scu_exec(dev, scu, sc); 359153901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 359253901Smckusick break; 359353901Smckusick 359453901Smckusick case SDIOC_GSTOPT: 359553901Smckusick case SDIOC_SSTOPT: 359653901Smckusick /* 359753901Smckusick * get/set stop-unit timer 359853901Smckusick */ 359953901Smckusick if (cmd == SDIOC_GSTOPT) 360053901Smckusick *(int *)data = sdd->sdd_stoptime; 360153901Smckusick else { 360253901Smckusick if (*(int *)data == 0) 360353901Smckusick return (EINVAL); 360453901Smckusick sdd->sdd_stoptime = *(int *)data; 360553901Smckusick } 360653901Smckusick break; 360753901Smckusick 360853901Smckusick case SDIOC_SEJECT: 360953901Smckusick /* 361053901Smckusick * set auto eject flag 361153901Smckusick */ 361253901Smckusick sdd->sdd_flags |= SDDF_REQ_EJECT; 361353901Smckusick break; 361453901Smckusick 361553901Smckusick case SDIOC_GFLAGS: 361653901Smckusick /* 361753901Smckusick * get ii->ii_flags 361853901Smckusick */ 361953901Smckusick *(int *)data = ii->ii_flags; 362053901Smckusick break; 362153901Smckusick 362253901Smckusick case SDIOC_SFLAGS: 362353901Smckusick /* 362453901Smckusick * set ii->ii_flags 362553901Smckusick */ 362653901Smckusick ii->ii_flags = *(int *)data; 362753901Smckusick break; 362853901Smckusick 362953901Smckusick case SDIOC_RASBLK: 363053901Smckusick /* 363153901Smckusick * reassign block 363253901Smckusick */ 363353901Smckusick { 363453901Smckusick struct sc_rab *sca = (struct sc_rab *)sc->sc_param; 363553901Smckusick 363653901Smckusick scinit(sc, ii->ii_slave, sdd->sdd_sectsize); 363753901Smckusick sc->sc_opcode = SCOP_RASBLK; 363853901Smckusick sc->sc_ctrnscnt = 8; 363953901Smckusick 364053901Smckusick sca->sca_dllen = 4; 364153901Smckusick sca->sca_dlad[0] = *(int *)data; 364253901Smckusick 364353901Smckusick error = sdcmd(dev, sc); 364453901Smckusick } 364553901Smckusick break; 364653901Smckusick 364753901Smckusick case SDIOC_GNICKNAME: 364853901Smckusick { 364953901Smckusick int len; 365053901Smckusick 365153901Smckusick len = strlen(sddevinfo[ii->ii_type].call_name); 365253901Smckusick 365353901Smckusick if (len > IOCPARM_MASK) 365453901Smckusick len = IOCPARM_MASK; 365553901Smckusick 365653901Smckusick error = copyout( 365753901Smckusick (caddr_t) sddevinfo[ii->ii_type].call_name, 365853901Smckusick (caddr_t) *(int *)data, 365953901Smckusick len); 366053901Smckusick } 366153901Smckusick break; 366253901Smckusick 366353901Smckusick case SDIOC_GTYPINDEX: 366453901Smckusick *(int *)data = (int)ii->ii_type; 366553901Smckusick break; 366653901Smckusick 366753901Smckusick #ifdef SDIOC_SSYNCPARAM 366853901Smckusick case SDIOC_SSYNCPARAM: 366953901Smckusick { 367053901Smckusick struct sync_param *syncp; 367153901Smckusick 367253901Smckusick syncp = (struct sync_param *)data; 367353901Smckusick scinit(sc, ii->ii_slave, sdd->sdd_sectsize); 367453901Smckusick sc->sc_opcode = SCOP_TST; 367553901Smckusick sc->sc_message = MSG_EXTND; /* extended message */ 367653901Smckusick sc->sc_param[0] = MSG_EXTND; 367753901Smckusick sc->sc_param[1] = 0x03; 367853901Smckusick sc->sc_param[2] = 0x01; /* synchronous transfer */ 367953901Smckusick sc->sc_param[3] = syncp->tr_period; /* transfer period */ 368053901Smckusick sc->sc_param[4] = syncp->tr_offset; /* REQ offset */ 368153901Smckusick 368253901Smckusick (void) sdcmd(dev, sc); 368353901Smckusick 368453901Smckusick syncp = &sd_sync_param[unit]; 368553901Smckusick syncp->tr_period = sc->sc_param[3]; 368653901Smckusick syncp->tr_offset = sc->sc_param[4]; 368753901Smckusick 368853901Smckusick if (syncp->tr_offset) 368953901Smckusick sdd->sdd_flags |= SDDF_SYNCTR; 369053901Smckusick else 369153901Smckusick sdd->sdd_flags &= ~SDDF_SYNCTR; 369253901Smckusick } 369353901Smckusick break; 369453901Smckusick 369553901Smckusick case SDIOC_GSYNCPARAM: 369653901Smckusick { 369753901Smckusick struct sync_param *syncp = (struct sync_param *)data; 369853901Smckusick 369953901Smckusick syncp->tr_period = sd_sync_param[unit].tr_period; 370053901Smckusick syncp->tr_offset = sd_sync_param[unit].tr_offset; 370153901Smckusick } 370253901Smckusick break; 370353901Smckusick #endif /* SDIOC_SSYNCPARAM */ 370453901Smckusick 370553901Smckusick case MTIOCTOP: 370653901Smckusick { 370753901Smckusick register struct mtop *mtop = (struct mtop *)data; 370853901Smckusick register int lba; 370953901Smckusick int rest; 371053901Smckusick int blength; 371153901Smckusick 371253901Smckusick switch (mtop->mt_op) { 371353901Smckusick 371453901Smckusick case MTOFFL: 371553901Smckusick /* 371653901Smckusick * set auto eject flag 371753901Smckusick */ 371853901Smckusick sdd->sdd_flags |= SDDF_REQ_EJECT; 371953901Smckusick break; 372053901Smckusick 372153901Smckusick #ifdef MTERASE 372253901Smckusick case MTERASE: 372353901Smckusick if (isalone(unit) != ONLY_ONE) 372453901Smckusick return (EBUSY); 372553901Smckusick sdd->sdd_flags |= SDDF_XUSE; 372653901Smckusick st = &sdstdrv[unit]; 372753901Smckusick /* 372853901Smckusick * MO disk erase 372953901Smckusick * block 0 to end (C partition) 373053901Smckusick */ 373153901Smckusick lba = 0; 373253901Smckusick rest = sdd->sdd_nsect; /* C part size */ 373353901Smckusick while (rest > 0) { 373453901Smckusick blength = (rest > MAXBL)? MAXBL : rest; 373553901Smckusick scinit(sc, ii->ii_slave, 373653901Smckusick sdd->sdd_sectsize); 373753901Smckusick sc->sc_opcode = SCOP_MOERASE; 373853901Smckusick sc->sc_lad = lba; 373953901Smckusick sc->sc_count = (blength % MAXBL); 374053901Smckusick 374153901Smckusick (void) sdcmd(dev, sc); 374253901Smckusick lba += blength; 374353901Smckusick rest -= blength; 374453901Smckusick } 374553901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 374653901Smckusick break; 374753901Smckusick #endif /* MTERASE */ 374853901Smckusick 374953901Smckusick default: 375053901Smckusick return (EINVAL); 375153901Smckusick } 375253901Smckusick } 375353901Smckusick break; 375453901Smckusick 375553901Smckusick case SCSIIOCCMD: 375653901Smckusick scu = (struct sc_ureq *)data; 375753901Smckusick if ((scu->scu_count > 0) && scu->scu_addr) { 375853901Smckusick if (useracc(scu->scu_addr, scu->scu_count, B_WRITE) 375953901Smckusick == NULL) { 376053901Smckusick error = EFAULT; 376153901Smckusick break; 376253901Smckusick } 376353901Smckusick } 376453901Smckusick error = sd_scu_exec(dev, scu, sc); 376553901Smckusick break; 376653901Smckusick 376753901Smckusick 376853901Smckusick case SDIOC_INQUIRY: 376953901Smckusick /* 377053901Smckusick * LOCK sdtmp buffer 377153901Smckusick */ 377253901Smckusick s = splclock(); 377353901Smckusick while (sdtmp_stat & B_BUSY) { 377453901Smckusick sdtmp_stat |= B_WANTED; 377553901Smckusick sleep((caddr_t)sdtmp, PRIBIO); 377653901Smckusick } 377753901Smckusick sdtmp_stat |= B_BUSY; 377853901Smckusick splx(s); 377953901Smckusick 378053901Smckusick bzero((caddr_t)sdtmp, sizeof(struct sc_inq)); 378153901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 378253901Smckusick uscsi.sc_cpoint = sdtmp; 378353901Smckusick uscsi.sc_ctrnscnt = sizeof(struct sc_inq); 378453901Smckusick uscsi.sc_opcode = SCOP_INQUIRY; 378553901Smckusick uscsi.sc_count = sizeof(struct sc_inq); 378653901Smckusick 378753901Smckusick if ((error = sdcmd(dev, &uscsi)) == 0) 378853901Smckusick bcopy((caddr_t)sdtmp, data, sizeof(struct sc_inq)); 378953901Smckusick /* 379053901Smckusick * UNLOCK open 379153901Smckusick */ 379253901Smckusick s = splclock(); 379353901Smckusick if (sdtmp_stat & B_WANTED) 379453901Smckusick wakeup((caddr_t)sdtmp); 379553901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 379653901Smckusick splx(s); 379753901Smckusick break; 379853901Smckusick 379953901Smckusick 380053901Smckusick case SCSIIOCGTIMEO: 380153901Smckusick *(int *)data = sdc->sdc_timeo; 380253901Smckusick break; 380353901Smckusick 380453901Smckusick case SCSIIOCSTIMEO: 380553901Smckusick if (*(int *)data == 0) 380653901Smckusick return (EINVAL); 380753901Smckusick sdc->sdc_timeo = *(int *)data; 380853901Smckusick sdc->sdc_wticks = 0; 380953901Smckusick break; 381053901Smckusick 381153901Smckusick default: 381253901Smckusick error = EINVAL; 381353901Smckusick break; 381453901Smckusick } 381553901Smckusick 381653901Smckusick done: 381753901Smckusick return (error); 381853901Smckusick } 381953901Smckusick 382053901Smckusick static 382153901Smckusick sd_scu_exec(dev, scu, sc) 382253901Smckusick dev_t dev; 382353901Smckusick register struct sc_ureq *scu; 382453901Smckusick register struct scsi *sc; 382553901Smckusick { 382653901Smckusick struct sdd_softc *sdd; 382753901Smckusick int error; 382853901Smckusick 382953901Smckusick sdd = &sdd_softc[dev2unit(dev)]; 383053901Smckusick 383153901Smckusick if (((scu->scu_identify & MSG_IDENT) == 0) 383253901Smckusick || (scu->scu_identify & ~(MSG_IDENT|IDT_DISCON|IDT_DRMASK)) 383353901Smckusick || (scu->scu_addr && (scu->scu_bytesec == 0))) { 383453901Smckusick return (EINVAL); 383553901Smckusick } 383653901Smckusick 383753901Smckusick bzero((caddr_t)sc, sizeof(struct scsi)); 383853901Smckusick sc->sc_tstatus = scu->scu_tstatus; 383953901Smckusick sc->sc_identify = scu->scu_identify; 384053901Smckusick sc->sc_message = scu->scu_message; 384153901Smckusick sc->sc_bytesec = scu->scu_bytesec; 384253901Smckusick sc->sc_cpoint = scu->scu_addr; 384353901Smckusick sc->sc_ctrnscnt = scu->scu_count; 384453901Smckusick bcopy((caddr_t)scu->scu_cdb, &sc->sc_cdb, sizeof(sc->sc_cdb)); 384553901Smckusick 384653901Smckusick bcopy((caddr_t)scu->scu_param, (caddr_t)sc->sc_param, 384753901Smckusick sizeof(sc->sc_param)); 384853901Smckusick 384953901Smckusick sdd->sdd_flags |= SDDF_SKIPCHECK; 385053901Smckusick error = sdcmd(dev, sc); 385153901Smckusick sdd->sdd_flags &= ~SDDF_SKIPCHECK; 385253901Smckusick 385353901Smckusick scu->scu_istatus = sc->sc_istatus; 385453901Smckusick scu->scu_tstatus = sc->sc_tstatus; 385553901Smckusick scu->scu_message = sc->sc_message; 385653901Smckusick bcopy((caddr_t)sc->sc_param, (caddr_t)scu->scu_param, 385753901Smckusick sizeof(sc->sc_param)); 385853901Smckusick return (error); 385953901Smckusick } 386053901Smckusick 386153901Smckusick /*ARGSUSED*/ 386253901Smckusick sddump(dev) 386353901Smckusick dev_t dev; 386453901Smckusick { 386553901Smckusick return (ENXIO); 386653901Smckusick } 386753901Smckusick 386853901Smckusick sdsize(dev) 386953901Smckusick register dev_t dev; 387053901Smckusick { 387153901Smckusick register struct iop/**/_device *ii; 387253901Smckusick register struct sdd_softc *sdd; 387353901Smckusick register struct sdst *st; 387453901Smckusick register int unit; 387553901Smckusick int i; 387653901Smckusick 387753901Smckusick unit = dev2unit(dev); 387853901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) 387953901Smckusick return (-1); 388053901Smckusick 388153901Smckusick sdd = &sdd_softc[unit]; 388253901Smckusick switch (sdc_softc[ii->ii_ctlr].sdc_firmware & SDCFW_DEVMASK) { 388353901Smckusick 388453901Smckusick case SDCFW_HD: /* Hard Disk */ 388553901Smckusick st = &sdstdrv[unit]; 388653901Smckusick break; 388753901Smckusick 388853901Smckusick case SDCFW_MO: /* MO only */ 388953901Smckusick if ((sdd->sdd_flags & SDDF_SAMEDSK) == SDDF_DSKCHGD) { 389053901Smckusick /* 389153901Smckusick * read partition information, 389253901Smckusick * and set up sdstdrv[unit] 389353901Smckusick */ 389453901Smckusick if (sd_b_open(dev, FREAD|FWRITE) != 0) { 389553901Smckusick /* 389653901Smckusick * block device open error 389753901Smckusick */ 389853901Smckusick return (-1); 389953901Smckusick } else { 390053901Smckusick /* 390153901Smckusick * use disk partition information 390253901Smckusick */ 390353901Smckusick st = &sdstdrv[unit]; 390453901Smckusick if (isalone(unit) == ONLY_ONE) 390553901Smckusick sd_b_close(dev, 0); 390653901Smckusick } 390753901Smckusick } else if (sdd->sdd_flags & SDDF_NONFMT) { 390853901Smckusick /* 390953901Smckusick * medium is not initialized. 391053901Smckusick */ 391153901Smckusick return (-1); 391253901Smckusick } else { 391353901Smckusick st = &sdstdrv[unit]; 391453901Smckusick } 391553901Smckusick break; 391653901Smckusick 391753901Smckusick default: 391853901Smckusick /* case SDCFW_CD: */ 391953901Smckusick return (-1); 392053901Smckusick 392153901Smckusick } 392253901Smckusick 392353901Smckusick if (st->sizes == NULL) 392453901Smckusick return (-1); /* XXX */ 392553901Smckusick else 392653901Smckusick return (st->sizes[dev2part(dev)].sd_nblocks); /* XXX */ 392753901Smckusick } 392853901Smckusick 392953901Smckusick /* 393053901Smckusick * Reset driver. 393153901Smckusick * Cancel software state of all pending transfers, 393253901Smckusick * and restart all units and the controller. 393353901Smckusick */ 393453901Smckusick sdreset() 393553901Smckusick { 393653901Smckusick register struct iop/**/_ctlr *im; 393753901Smckusick register struct iop/**/_device *ii; 393853901Smckusick register struct sdc_softc *sdc; 393953901Smckusick register struct sdd_softc *sdd; 394053901Smckusick register int i; 394153901Smckusick register int unit; 394253901Smckusick 394353901Smckusick re_init_done = 1; 394453901Smckusick for (i = 0; i < nsdc; i++) { 394553901Smckusick im = sdminfo[i]; 394653901Smckusick if (im == 0) 394753901Smckusick continue; 394853901Smckusick if (im->im_alive == 0) 394953901Smckusick continue; 395053901Smckusick printf(" sdc%d: ", i); 395153901Smckusick sdc = &sdc_softc[i]; 395253901Smckusick sdc->sdc_wticks = 0; 395353901Smckusick 395453901Smckusick /* scop_init() is already called by screset() */ 395553901Smckusick 395653901Smckusick sdtmp_stat &= ~B_BUSY; 395753901Smckusick 395853901Smckusick for (unit = 0; unit < nsd; unit++) { 395953901Smckusick ii = sddinfo[unit]; 396053901Smckusick if (ii == 0) 396153901Smckusick continue; 396253901Smckusick if (ii->ii_alive == 0) 396353901Smckusick continue; 396453901Smckusick if (ii->ii_mi != im) 396553901Smckusick continue; 396653901Smckusick 396753901Smckusick csdbuf[unit].b_flags &= ~B_BUSY; 396853901Smckusick 396953901Smckusick sdd = &sdd_softc[unit]; 397053901Smckusick sdd->sdd_flags = 0; 397153901Smckusick 397253901Smckusick /* 397353901Smckusick * UNLOCK SCSI access 397453901Smckusick */ 397553901Smckusick sdc->sdc_firmware &= ~SDCFW_BUSY; 397653901Smckusick 397753901Smckusick if (sdslave(ii, ii->ii_addr, im->im_intr) == 0) { 397853901Smckusick printf("sd%d: not ready\n", ii->ii_slave); 397953901Smckusick continue; 398053901Smckusick } 398153901Smckusick sdattach(ii); 398253901Smckusick } 398353901Smckusick } 398453901Smckusick re_init_done = 2; 398553901Smckusick } 398653901Smckusick 398753901Smckusick int sd_long_timeout = 24 * 60 * 60; /* 24 hours */ 398853901Smckusick 398953901Smckusick #define max(a, b) (((a)>(b))?(a):(b)) 399053901Smckusick 399153901Smckusick /* 399253901Smckusick * Wake up every second and if interrupt is pending 399353901Smckusick * but nothing has happened increment a counter. 399453901Smckusick * If nothing happens for sdc_timeo seconds, reset the IOP 399553901Smckusick * and begin anew. 399653901Smckusick */ 399753901Smckusick sdwatch() 399853901Smckusick { 399953901Smckusick register struct iop/**/_ctlr *im; 400053901Smckusick register struct sdc_softc *sdc; 400153901Smckusick register int i; 400253901Smckusick register int unit; 400353901Smckusick int timeo; 400453901Smckusick 400553901Smckusick extern int Scsi_Disconnect; 400653901Smckusick 400753901Smckusick timeout(sdwatch, (caddr_t)0, hz); 400853901Smckusick for (i = 0; i < nsdc; i++) { 400953901Smckusick im = sdminfo[i]; 401053901Smckusick if (im == 0) 401153901Smckusick continue; 401253901Smckusick if (im->im_alive == 0) 401353901Smckusick continue; 401453901Smckusick sdc = &sdc_softc[i]; 401553901Smckusick 401653901Smckusick if (im->im_tab.b_active) 401753901Smckusick goto active; 401853901Smckusick 401953901Smckusick for (unit = 0; unit < nsd; unit++) 402053901Smckusick if (sdutab[unit].b_active && sddinfo[unit]->ii_mi == im) 402153901Smckusick goto active; 402253901Smckusick 402353901Smckusick sdc->sdc_wticks = 0; 402453901Smckusick continue; 402553901Smckusick active: 402653901Smckusick if (Scsi_Disconnect) 402753901Smckusick timeo = sdc->sdc_timeo; 402853901Smckusick else 402953901Smckusick timeo = max(sdc->sdc_timeo, sd_long_timeout); 403053901Smckusick 403153901Smckusick if (sdc->sdc_wticks++ >= timeo) { 403253901Smckusick register struct scsi *sc; 403353901Smckusick 403453901Smckusick sc = get_scsi(im->im_intr); 403553901Smckusick sdc->sdc_wticks = 0; 403653901Smckusick printf("sdc%d: lost interrupt\n", i); 403753901Smckusick 403853901Smckusick screset(im->im_intr); 403953901Smckusick } 404053901Smckusick } 404153901Smckusick } 404253901Smckusick 404353901Smckusick /* 404453901Smckusick * sdstop() is timer interrupt routine. 404553901Smckusick * So, can't use sleep(). 404653901Smckusick */ 404753901Smckusick sdstop() 404853901Smckusick { 404953901Smckusick register struct iop/**/_ctlr *im; 405053901Smckusick register struct iop/**/_device *ii; 405153901Smckusick register struct sdc_softc *sdc; 405253901Smckusick register struct sdd_softc *sdd; 405353901Smckusick register int unit; 405453901Smckusick register int intr; 405553901Smckusick register int i; 405653901Smckusick struct scsi *sc; 405753901Smckusick int eject_sw; 405853901Smckusick 405953901Smckusick timeout(sdstop, (caddr_t)0, hz); 406053901Smckusick 406153901Smckusick for (i = 0; i < nsdc; i++) { 406253901Smckusick im = sdminfo[i]; 406353901Smckusick if (im == 0) 406453901Smckusick continue; 406553901Smckusick if (im->im_alive == 0) 406653901Smckusick continue; 406753901Smckusick for (unit = 0; unit < nsd; unit++) { 406853901Smckusick if ((ii = sddinfo[unit]) == 0) 406953901Smckusick continue; 407053901Smckusick if (ii->ii_mi != im) 407153901Smckusick continue; 407253901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 407353901Smckusick if ((sdc->sdc_firmware & SDCFW_RMB) == 0) 407453901Smckusick continue; 407553901Smckusick intr = ii->ii_intr; 407653901Smckusick if (isalone(unit)) 407753901Smckusick continue; 407853901Smckusick /**********************/ 407953901Smckusick /* MO & CD-ROM */ 408053901Smckusick /**********************/ 408153901Smckusick /* 408253901Smckusick * there is no process which open the unit. 408353901Smckusick */ 408453901Smckusick sdd = &sdd_softc[unit]; 408553901Smckusick sc = get_scsi(intr); 408653901Smckusick if (sdd->sdd_start > 0) 408753901Smckusick sdd->sdd_start--; 408853901Smckusick else if (sdd->sdd_start == 0) { 408953901Smckusick /* 409053901Smckusick * Now stop the unit. 409153901Smckusick * check SCSI access 409253901Smckusick */ 409353901Smckusick if (sdc->sdc_firmware & SDCFW_BUSY) 409453901Smckusick continue; 409553901Smckusick sdc->sdc_firmware |= SDCFW_BUSY; 409653901Smckusick sdc->sdc_state |= SDCS_IOCTL|SDCS_SCUNLOCK; 409753901Smckusick 409853901Smckusick eject_sw = (sdd->sdd_flags & SDDF_REQ_EJECT) ? 409953901Smckusick SDSS_EJECT : SDSS_STOP; 410053901Smckusick scop_stst(intr, sc, ii->ii_slave, 410153901Smckusick SCSI_INTEN, eject_sw); 410253901Smckusick sdd->sdd_start = -2; 410353901Smckusick } 410453901Smckusick } 410553901Smckusick } 410653901Smckusick } 410753901Smckusick 410853901Smckusick isalone(unit) 410953901Smckusick register int unit; 411053901Smckusick { 411153901Smckusick register int i, n; 411253901Smckusick 411353901Smckusick n = 0; 411453901Smckusick for (i = 0; i < PNUM; i++) 411553901Smckusick n += (sd_b_openf[unit][i] + sd_c_openf[unit][i]); 411653901Smckusick return (n); 411753901Smckusick } 411853901Smckusick 411953901Smckusick /************************************************ 412053901Smckusick * Convert Hex and RS code table definition * 412153901Smckusick ************************************************/ 412253901Smckusick 412353901Smckusick #define X8_L 0x001d 412453901Smckusick #define X8_H 0x1d00 412553901Smckusick 412653901Smckusick 412753901Smckusick #define hextors(data) hxtable[(int)((data) & 0xff)] 412853901Smckusick #define XORMASK(code) xortable[(unsigned int)(code)] 412953901Smckusick 413053901Smckusick int hxtable[256] = { 413153901Smckusick 0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 413253901Smckusick 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, 413353901Smckusick 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 413453901Smckusick 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71, 413553901Smckusick 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 413653901Smckusick 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, 413753901Smckusick 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 413853901Smckusick 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6, 413953901Smckusick 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 414053901Smckusick 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, 414153901Smckusick 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 414253901Smckusick 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, 414353901Smckusick 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 414453901Smckusick 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d, 414553901Smckusick 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 414653901Smckusick 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, 414753901Smckusick 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 414853901Smckusick 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18, 414953901Smckusick 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 415053901Smckusick 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, 415153901Smckusick 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 415253901Smckusick 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, 415353901Smckusick 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 415453901Smckusick 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2, 415553901Smckusick 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 415653901Smckusick 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6, 415753901Smckusick 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 415853901Smckusick 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a, 415953901Smckusick 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 416053901Smckusick 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, 416153901Smckusick 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 416253901Smckusick 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf, 416353901Smckusick }; 416453901Smckusick 416553901Smckusick int xortable[256] = { 416653901Smckusick 0x00000000, 0x90910101, 0x91210201, 0x01b00300, 416753901Smckusick 0x92410401, 0x02d00500, 0x03600600, 0x93f10701, 416853901Smckusick 0x94810801, 0x04100900, 0x05a00a00, 0x95310b01, 416953901Smckusick 0x06c00c00, 0x96510d01, 0x97e10e01, 0x07700f00, 417053901Smckusick 0x99011001, 0x09901100, 0x08201200, 0x98b11301, 417153901Smckusick 0x0b401400, 0x9bd11501, 0x9a611601, 0x0af01700, 417253901Smckusick 0x0d801800, 0x9d111901, 0x9ca11a01, 0x0c301b00, 417353901Smckusick 0x9fc11c01, 0x0f501d00, 0x0ee01e00, 0x9e711f01, 417453901Smckusick 0x82012001, 0x12902100, 0x13202200, 0x83b12301, 417553901Smckusick 0x10402400, 0x80d12501, 0x81612601, 0x11f02700, 417653901Smckusick 0x16802800, 0x86112901, 0x87a12a01, 0x17302b00, 417753901Smckusick 0x84c12c01, 0x14502d00, 0x15e02e00, 0x85712f01, 417853901Smckusick 0x1b003000, 0x8b913101, 0x8a213201, 0x1ab03300, 417953901Smckusick 0x89413401, 0x19d03500, 0x18603600, 0x88f13701, 418053901Smckusick 0x8f813801, 0x1f103900, 0x1ea03a00, 0x8e313b01, 418153901Smckusick 0x1dc03c00, 0x8d513d01, 0x8ce13e01, 0x1c703f00, 418253901Smckusick 0xb4014001, 0x24904100, 0x25204200, 0xb5b14301, 418353901Smckusick 0x26404400, 0xb6d14501, 0xb7614601, 0x27f04700, 418453901Smckusick 0x20804800, 0xb0114901, 0xb1a14a01, 0x21304b00, 418553901Smckusick 0xb2c14c01, 0x22504d00, 0x23e04e00, 0xb3714f01, 418653901Smckusick 0x2d005000, 0xbd915101, 0xbc215201, 0x2cb05300, 418753901Smckusick 0xbf415401, 0x2fd05500, 0x2e605600, 0xbef15701, 418853901Smckusick 0xb9815801, 0x29105900, 0x28a05a00, 0xb8315b01, 418953901Smckusick 0x2bc05c00, 0xbb515d01, 0xbae15e01, 0x2a705f00, 419053901Smckusick 0x36006000, 0xa6916101, 0xa7216201, 0x37b06300, 419153901Smckusick 0xa4416401, 0x34d06500, 0x35606600, 0xa5f16701, 419253901Smckusick 0xa2816801, 0x32106900, 0x33a06a00, 0xa3316b01, 419353901Smckusick 0x30c06c00, 0xa0516d01, 0xa1e16e01, 0x31706f00, 419453901Smckusick 0xaf017001, 0x3f907100, 0x3e207200, 0xaeb17301, 419553901Smckusick 0x3d407400, 0xadd17501, 0xac617601, 0x3cf07700, 419653901Smckusick 0x3b807800, 0xab117901, 0xaaa17a01, 0x3a307b00, 419753901Smckusick 0xa9c17c01, 0x39507d00, 0x38e07e00, 0xa8717f01, 419853901Smckusick 0xd8018001, 0x48908100, 0x49208200, 0xd9b18301, 419953901Smckusick 0x4a408400, 0xdad18501, 0xdb618601, 0x4bf08700, 420053901Smckusick 0x4c808800, 0xdc118901, 0xdda18a01, 0x4d308b00, 420153901Smckusick 0xdec18c01, 0x4e508d00, 0x4fe08e00, 0xdf718f01, 420253901Smckusick 0x41009000, 0xd1919101, 0xd0219201, 0x40b09300, 420353901Smckusick 0xd3419401, 0x43d09500, 0x42609600, 0xd2f19701, 420453901Smckusick 0xd5819801, 0x45109900, 0x44a09a00, 0xd4319b01, 420553901Smckusick 0x47c09c00, 0xd7519d01, 0xd6e19e01, 0x46709f00, 420653901Smckusick 0x5a00a000, 0xca91a101, 0xcb21a201, 0x5bb0a300, 420753901Smckusick 0xc841a401, 0x58d0a500, 0x5960a600, 0xc9f1a701, 420853901Smckusick 0xce81a801, 0x5e10a900, 0x5fa0aa00, 0xcf31ab01, 420953901Smckusick 0x5cc0ac00, 0xcc51ad01, 0xcde1ae01, 0x5d70af00, 421053901Smckusick 0xc301b001, 0x5390b100, 0x5220b200, 0xc2b1b301, 421153901Smckusick 0x5140b400, 0xc1d1b501, 0xc061b601, 0x50f0b700, 421253901Smckusick 0x5780b800, 0xc711b901, 0xc6a1ba01, 0x5630bb00, 421353901Smckusick 0xc5c1bc01, 0x5550bd00, 0x54e0be00, 0xc471bf01, 421453901Smckusick 0x6c00c000, 0xfc91c101, 0xfd21c201, 0x6db0c300, 421553901Smckusick 0xfe41c401, 0x6ed0c500, 0x6f60c600, 0xfff1c701, 421653901Smckusick 0xf881c801, 0x6810c900, 0x69a0ca00, 0xf931cb01, 421753901Smckusick 0x6ac0cc00, 0xfa51cd01, 0xfbe1ce01, 0x6b70cf00, 421853901Smckusick 0xf501d001, 0x6590d100, 0x6420d200, 0xf4b1d301, 421953901Smckusick 0x6740d400, 0xf7d1d501, 0xf661d601, 0x66f0d700, 422053901Smckusick 0x6180d800, 0xf111d901, 0xf0a1da01, 0x6030db00, 422153901Smckusick 0xf3c1dc01, 0x6350dd00, 0x62e0de00, 0xf271df01, 422253901Smckusick 0xee01e001, 0x7e90e100, 0x7f20e200, 0xefb1e301, 422353901Smckusick 0x7c40e400, 0xecd1e501, 0xed61e601, 0x7df0e700, 422453901Smckusick 0x7a80e800, 0xea11e901, 0xeba1ea01, 0x7b30eb00, 422553901Smckusick 0xe8c1ec01, 0x7850ed00, 0x79e0ee00, 0xe971ef01, 422653901Smckusick 0x7700f000, 0xe791f101, 0xe621f201, 0x76b0f300, 422753901Smckusick 0xe541f401, 0x75d0f500, 0x7460f600, 0xe4f1f701, 422853901Smckusick 0xe381f801, 0x7310f900, 0x72a0fa00, 0xe231fb01, 422953901Smckusick 0x71c0fc00, 0xe151fd01, 0xe0e1fe01, 0x7070ff00 423053901Smckusick }; 423153901Smckusick 423253901Smckusick /******************************************************** 423353901Smckusick * EDC (Error Detection Code) check * 423453901Smckusick * (using CRC code) * 423553901Smckusick * MODE 1 : Sync + Header + User data + edc * 423653901Smckusick * MODE 2 : Sub header + User data + edc * 423753901Smckusick ********************************************************/ 423853901Smckusick 423953901Smckusick #define SYNC_EDC 0x908eff4e /* sector sync EDC value */ 424053901Smckusick #define HEADER 4 /* header length 4 bytes */ 424153901Smckusick #define SUB_H 8 /* Subheader length 8 bytes */ 424253901Smckusick #define USER_DATA 2048 /* User data length 2048 bytes */ 424353901Smckusick #define EDC_LEN 4 /* EDC code length 4 bytes */ 424453901Smckusick 424553901Smckusick cal_edc1(db, mode) 424653901Smckusick register unsigned char *db; 424753901Smckusick int mode; 424853901Smckusick { 424953901Smckusick register int j; 425053901Smckusick register unsigned int work; 425153901Smckusick 425253901Smckusick j = USER_DATA + EDC_LEN; 425353901Smckusick if (mode == 2) { 425453901Smckusick j += SUB_H; 425553901Smckusick work = 0; 425653901Smckusick } else { 425753901Smckusick j += HEADER; 425853901Smckusick work = SYNC_EDC; 425953901Smckusick } 426053901Smckusick while (--j >= 0) 426153901Smckusick work = ((work >> 8) | (*db++ << 24)) ^ XORMASK(work & 0xff); 426253901Smckusick 426353901Smckusick return (work); 426453901Smckusick } 426553901Smckusick 426653901Smckusick 426753901Smckusick /************************************************/ 426853901Smckusick /* error detection & correction */ 426953901Smckusick /* if form 1 */ 427053901Smckusick /* header area should be zero */ 427153901Smckusick /************************************************/ 427253901Smckusick 427353901Smckusick /* 427453901Smckusick * error detection & correction P-direction 427553901Smckusick */ 427653901Smckusick p_dir(dbuf) 427753901Smckusick register unsigned short *dbuf; 427853901Smckusick { 427953901Smckusick unsigned short s0, s1, d; 428053901Smckusick register int col, row; 428153901Smckusick register int x; 428253901Smckusick unsigned char s0l, s0h, s1l, s1h; 428353901Smckusick 428453901Smckusick /* 428553901Smckusick * calculate syndrome S0 S1 428653901Smckusick */ 428753901Smckusick for (col = 0; col < 43; col++) { 428853901Smckusick s0 = s1 = 0; 428953901Smckusick 429053901Smckusick for (row = 0; row < 26; row++) { 429153901Smckusick d = dbuf[43 * row + col]; 429253901Smckusick s0 ^= d; 429353901Smckusick s1 = rsshift(s1) ^ d; 429453901Smckusick } 429553901Smckusick 429653901Smckusick s0h = s0 & 0x00ff; 429753901Smckusick s1h = s1 & 0x00ff; 429853901Smckusick s0l = (s0 >> 8) & 0x00ff; 429953901Smckusick s1l = (s1 >> 8) & 0x00ff; 430053901Smckusick /* 430153901Smckusick * calculate error position & correction 430253901Smckusick */ 430353901Smckusick if (s0l != 0) { 430453901Smckusick if((x = hextors(s1l) - hextors(s0l)) < 0) 430553901Smckusick x += 255; 430653901Smckusick if ((x >= 0) && (x < 26)) { 430753901Smckusick x = 25 - x; 430853901Smckusick /* 430953901Smckusick * correction 431053901Smckusick */ 431153901Smckusick dbuf[43 * x + col] ^= (s0 & 0xff00); 431253901Smckusick } 431353901Smckusick } 431453901Smckusick 431553901Smckusick /* 431653901Smckusick * calculate error position & correction 431753901Smckusick */ 431853901Smckusick if (s0h != 0) { 431953901Smckusick if((x = hextors(s1h) - hextors(s0h)) < 0) 432053901Smckusick x += 255; 432153901Smckusick if ((x >= 0) && (x < 26)) { 432253901Smckusick x = 25 - x; 432353901Smckusick /* 432453901Smckusick * correction 432553901Smckusick */ 432653901Smckusick dbuf[43 * x + col] ^= (s0 & 0x00ff); 432753901Smckusick } 432853901Smckusick } 432953901Smckusick } 433053901Smckusick } 433153901Smckusick 433253901Smckusick /* 433353901Smckusick * error detection & correction Q-direction 433453901Smckusick */ 433553901Smckusick q_dir(dbuf) 433653901Smckusick register unsigned short *dbuf; 433753901Smckusick { 433853901Smckusick unsigned short s0, s1, d; 433953901Smckusick register int col, row; 434053901Smckusick register int x; 434153901Smckusick unsigned char s0l, s0h, s1l, s1h; 434253901Smckusick 434353901Smckusick /* 434453901Smckusick * calculate syndrome S0 S1 434553901Smckusick */ 434653901Smckusick for (row = 0; row < 26; row++) { 434753901Smckusick s0 = s1 = 0; 434853901Smckusick 434953901Smckusick for (col = 0; col < 45; col++) { 435053901Smckusick if (col < 43) 435153901Smckusick d = dbuf[(44 * col + 43 * row) % 1118]; 435253901Smckusick else if (col == 43) 435353901Smckusick d = dbuf[43 * 26 + row]; 435453901Smckusick else 435553901Smckusick d = dbuf[44 * 26 + row]; 435653901Smckusick s0 ^= d; 435753901Smckusick s1 = rsshift(s1) ^ d; 435853901Smckusick } 435953901Smckusick 436053901Smckusick s0h = s0 & 0x00ff; 436153901Smckusick s1h = s1 & 0x00ff; 436253901Smckusick s0l = (s0 >> 8) & 0x00ff; 436353901Smckusick s1l = (s1 >> 8) & 0x00ff; 436453901Smckusick /* 436553901Smckusick * calculate error position & correction 436653901Smckusick */ 436753901Smckusick if (s0l != 0) { 436853901Smckusick if((x = hextors(s1l) - hextors(s0l)) < 0) 436953901Smckusick x += 255; 437053901Smckusick if (x >= 0 && x < 45) { 437153901Smckusick x = 44 - x; 437253901Smckusick /* 437353901Smckusick * correction 437453901Smckusick */ 437553901Smckusick if (x < 43) 437653901Smckusick dbuf[(44 * x + 43 * row) % 1118] 437753901Smckusick ^= s0 & 0xff00; 437853901Smckusick else if (x == 43) 437953901Smckusick dbuf[43 * 26 + row] ^= s0 & 0xff00; 438053901Smckusick else 438153901Smckusick dbuf[44 * 26 + row] ^= s0 & 0xff00; 438253901Smckusick } 438353901Smckusick } 438453901Smckusick 438553901Smckusick /* 438653901Smckusick * calculate error position & correction 438753901Smckusick */ 438853901Smckusick if (s0h != 0) { 438953901Smckusick if((x = hextors(s1h) - hextors(s0h)) < 0) 439053901Smckusick x += 255; 439153901Smckusick if ((x >= 0) && (x < 45)) { 439253901Smckusick x = 44 - x; 439353901Smckusick /* 439453901Smckusick * correction 439553901Smckusick */ 439653901Smckusick if (x < 43) 439753901Smckusick dbuf[(44 * x + 43 * row) % 1118] 439853901Smckusick ^= s0 & 0x00ff; 439953901Smckusick else if ( x == 43) 440053901Smckusick dbuf[43 * 26 + row] ^= s0 & 0x00ff; 440153901Smckusick else 440253901Smckusick dbuf[44 * 26 + row] ^= s0 & 0x00ff; 440353901Smckusick } 440453901Smckusick } 440553901Smckusick } 440653901Smckusick } 440753901Smckusick 440853901Smckusick /* 440953901Smckusick * shift high & low byte at the same time 441053901Smckusick */ 441153901Smckusick rsshift(d) 441253901Smckusick unsigned short d; 441353901Smckusick { 441453901Smckusick register int x; 441553901Smckusick register int dmy; /* This way is faster */ 441653901Smckusick 441753901Smckusick dmy = (int)d; 441853901Smckusick x = (dmy << 1) & 0xfefe; /* clear LSB of high & low byte */ 441953901Smckusick if ((dmy & 0x0080) != 0) 442053901Smckusick x ^= X8_L; 442153901Smckusick if ((dmy & 0x8000) != 0) 442253901Smckusick x ^= X8_H; 442353901Smckusick return(x); 442453901Smckusick } 442553901Smckusick #endif /* NSD > 0 */ 4426