1*53901Smckusick /* 2*53901Smckusick * Copyright (c) 1992 The Regents of the University of California. 3*53901Smckusick * All rights reserved. 4*53901Smckusick * 5*53901Smckusick * This code is derived from software contributed to Berkeley by 6*53901Smckusick * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. 7*53901Smckusick * 8*53901Smckusick * %sccs.include.redist.c% 9*53901Smckusick * 10*53901Smckusick * from: $Hdr: sd.c,v 4.300 91/06/27 20:42:56 root Rel41 $ SONY 11*53901Smckusick * 12*53901Smckusick * @(#)sd.c 7.1 (Berkeley) 06/04/92 13*53901Smckusick */ 14*53901Smckusick #define dkblock(bp) bp->b_blkno 15*53901Smckusick 16*53901Smckusick /* 17*53901Smckusick * Copyright (c) 1987-1991 by SONY Corporation. 18*53901Smckusick */ 19*53901Smckusick 20*53901Smckusick #include "sd.h" 21*53901Smckusick #if NSD > 0 22*53901Smckusick 23*53901Smckusick #include "../include/fix_machine_type.h" 24*53901Smckusick 25*53901Smckusick #include "param.h" 26*53901Smckusick #include "buf.h" 27*53901Smckusick #include "proc.h" 28*53901Smckusick #include "user.h" 29*53901Smckusick #include "dkstat.h" 30*53901Smckusick #include "uio.h" 31*53901Smckusick #include "kernel.h" 32*53901Smckusick #include "reboot.h" 33*53901Smckusick #include "ioctl.h" 34*53901Smckusick #include "systm.h" 35*53901Smckusick #include "mtio.h" 36*53901Smckusick #include "stat.h" 37*53901Smckusick #include "disklabel.h" 38*53901Smckusick #include "vm/vm.h" 39*53901Smckusick #include "syslog.h" 40*53901Smckusick 41*53901Smckusick #include "../ufs/ffs/fs.h" 42*53901Smckusick 43*53901Smckusick # include "../include/cpu.h" 44*53901Smckusick 45*53901Smckusick #ifdef IPC_MRX 46*53901Smckusick # include "../iop/iopvar.h" 47*53901Smckusick # include "../ipc/newsipc.h" 48*53901Smckusick #endif 49*53901Smckusick 50*53901Smckusick #ifdef CPU_SINGLE 51*53901Smckusick # include "../hbdev/hbvar.h" 52*53901Smckusick # include "../iodev/ioptohb.h" 53*53901Smckusick #endif 54*53901Smckusick 55*53901Smckusick #include "../iodev/scsireg.h" 56*53901Smckusick #include "../iodev/scu.h" 57*53901Smckusick #include "../iodev/dkio.h" 58*53901Smckusick #include "../iodev/sdreg.h" 59*53901Smckusick /* #ifdef DISKINFO KU:XXX */ 60*53901Smckusick #include "../iodev/diskinfo.h" 61*53901Smckusick /* #endif /* DISKINFO */ 62*53901Smckusick 63*53901Smckusick #define sce_sdecode sce_hdecode 64*53901Smckusick 65*53901Smckusick #define dev2unit(x) ((minor(x) & ~0x80) >> 3) 66*53901Smckusick #define dev2part(x) (minor(x) & 0x7) 67*53901Smckusick 68*53901Smckusick /* /sys/sys/file.h */ 69*53901Smckusick #define FREAD 00001 /* descriptor read/receive'able */ 70*53901Smckusick #define FWRITE 00002 /* descriptor write/send'able */ 71*53901Smckusick 72*53901Smckusick #define PART_A 0 73*53901Smckusick #define PART_B 1 74*53901Smckusick #define PART_C 2 75*53901Smckusick #define PART_D 3 76*53901Smckusick #define PART_E 4 77*53901Smckusick #define PART_F 5 78*53901Smckusick #define PART_G 6 79*53901Smckusick #define PART_H 7 80*53901Smckusick 81*53901Smckusick #define MAXPROBERETRY 100 82*53901Smckusick #define NRETRY 10 83*53901Smckusick #define MAXHRDERR 100 84*53901Smckusick #define MAXRETRYCNT 16 85*53901Smckusick 86*53901Smckusick #define SDBSIZE1K (DEV_BSIZE * 2) 87*53901Smckusick #define MAXSDPHYS ((NSCMAP - 1) * NBPG) 88*53901Smckusick 89*53901Smckusick #define D100MSEC 100000 90*53901Smckusick 91*53901Smckusick #if OD_STOPTIME < 1 92*53901Smckusick # define OD_STOPTIME 5 93*53901Smckusick #endif /* OD_STOPTIME < 1 */ 94*53901Smckusick 95*53901Smckusick #define FORMAT_MODE_CORRUPTED 0x31 96*53901Smckusick #define ONLY_ONE 1 97*53901Smckusick 98*53901Smckusick /************** PARTITIONS *************************************/ 99*53901Smckusick 100*53901Smckusick #define PART_UNUSED (0) 101*53901Smckusick #define PART_SPEC (-1) 102*53901Smckusick #define PART_CALCF (-2) 103*53901Smckusick #define PART_CALCG (-3) 104*53901Smckusick 105*53901Smckusick struct defpart { 106*53901Smckusick int range_min; 107*53901Smckusick int range_max; 108*53901Smckusick int partsize[PNUM]; 109*53901Smckusick }; 110*53901Smckusick 111*53901Smckusick struct defpart defpart_std[] = { 112*53901Smckusick { 113*53901Smckusick 0, /* range_min */ 114*53901Smckusick 20, /* range_max */ 115*53901Smckusick 116*53901Smckusick PART_SPEC, /* A: */ 117*53901Smckusick PART_UNUSED, /* B: */ 118*53901Smckusick PART_SPEC, /* C: */ 119*53901Smckusick PART_UNUSED, /* D: */ 120*53901Smckusick PART_UNUSED, /* E: */ 121*53901Smckusick PART_UNUSED, /* F: */ 122*53901Smckusick PART_UNUSED, /* G: */ 123*53901Smckusick PART_UNUSED, /* H: */ 124*53901Smckusick }, 125*53901Smckusick { 126*53901Smckusick 20, /* range_min */ 127*53901Smckusick 61, /* range_max */ 128*53901Smckusick 129*53901Smckusick 15884, /* A: */ 130*53901Smckusick 10032, /* B: */ 131*53901Smckusick PART_SPEC, /* C: */ 132*53901Smckusick 15884, /* D: */ 133*53901Smckusick PART_UNUSED, /* E: */ 134*53901Smckusick PART_CALCF, /* F: */ 135*53901Smckusick PART_CALCG, /* G: */ 136*53901Smckusick PART_UNUSED, /* H: */ 137*53901Smckusick }, 138*53901Smckusick { 139*53901Smckusick 61, /* range_min */ 140*53901Smckusick 206, /* range_max */ 141*53901Smckusick 142*53901Smckusick 15884, /* A: */ 143*53901Smckusick 33440, /* B: */ 144*53901Smckusick PART_SPEC, /* C: */ 145*53901Smckusick 15884, /* D: */ 146*53901Smckusick 55936, /* E: */ 147*53901Smckusick PART_CALCF, /* F: */ 148*53901Smckusick PART_CALCG, /* G: */ 149*53901Smckusick PART_UNUSED, /* H: */ 150*53901Smckusick }, 151*53901Smckusick { 152*53901Smckusick 206, /* range_min */ 153*53901Smckusick 356, /* range_max */ 154*53901Smckusick 155*53901Smckusick 15884, /* A: */ 156*53901Smckusick 33440, /* B: */ 157*53901Smckusick PART_SPEC, /* C: */ 158*53901Smckusick 15884, /* D: */ 159*53901Smckusick 55936, /* E: */ 160*53901Smckusick PART_CALCF, /* F: */ 161*53901Smckusick PART_CALCG, /* G: */ 162*53901Smckusick 291346, /* H: */ 163*53901Smckusick }, 164*53901Smckusick { 165*53901Smckusick 356, /* range_min */ 166*53901Smckusick 99999999, /* range_max */ 167*53901Smckusick 168*53901Smckusick 15884, /* A: */ 169*53901Smckusick 66880, /* B: */ 170*53901Smckusick PART_SPEC, /* C: */ 171*53901Smckusick 15884, /* D: */ 172*53901Smckusick 307200, /* E: */ 173*53901Smckusick PART_CALCF, /* F: */ 174*53901Smckusick PART_CALCG, /* G: */ 175*53901Smckusick 291346, /* H: */ 176*53901Smckusick }, 177*53901Smckusick { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 178*53901Smckusick }; 179*53901Smckusick 180*53901Smckusick 181*53901Smckusick 182*53901Smckusick /************* ADDITIONAL SENSE ERROR CODES *************************/ 183*53901Smckusick 184*53901Smckusick struct msg_list { 185*53901Smckusick int ml_code; /* message code */ 186*53901Smckusick int ml_msglvl; /* message level */ 187*53901Smckusick char *ml_msgstr; /* message string */ 188*53901Smckusick }; 189*53901Smckusick 190*53901Smckusick #define sdskeylist skeylist 191*53901Smckusick 192*53901Smckusick struct msg_list ecodelist_mo[] = { 193*53901Smckusick { 0x80, 0, NULL }, 194*53901Smckusick { 0x81, 0, NULL }, 195*53901Smckusick { 0x82, 0, NULL }, 196*53901Smckusick { 0x83, 0, NULL }, 197*53901Smckusick 198*53901Smckusick { -1, 0, NULL } 199*53901Smckusick }; 200*53901Smckusick 201*53901Smckusick /************** Ref. sd_var.c ********************************/ 202*53901Smckusick 203*53901Smckusick extern struct iop/**/_ctlr *sdminfo[]; 204*53901Smckusick extern struct iop/**/_device *sddinfo[]; 205*53901Smckusick extern struct iop/**/_device *sdip[][MAXSLAVE]; 206*53901Smckusick 207*53901Smckusick extern struct buf rsdbuf[]; /* buffer for raw I/O */ 208*53901Smckusick extern struct buf csdbuf[]; /* buffer for controll */ 209*53901Smckusick extern struct buf sdutab[]; /* per drive buffers */ 210*53901Smckusick 211*53901Smckusick extern struct sdc_softc sdc_softc[]; 212*53901Smckusick extern struct sdd_softc sdd_softc[]; 213*53901Smckusick extern u_char sd_b_openf[][PNUM]; 214*53901Smckusick extern u_char sd_c_openf[][PNUM]; 215*53901Smckusick 216*53901Smckusick extern struct scsi kernscsi[]; 217*53901Smckusick extern struct sdst sdstdrv[]; 218*53901Smckusick extern struct disklabel sdlabel[]; 219*53901Smckusick extern struct size sdsizedrv[][PNUM]; 220*53901Smckusick 221*53901Smckusick extern u_char sdc_rsense[][RSEN_CNT]; 222*53901Smckusick 223*53901Smckusick extern struct sync_param sd_sync_param[]; 224*53901Smckusick 225*53901Smckusick extern int nsd; 226*53901Smckusick extern int nsdc; 227*53901Smckusick 228*53901Smckusick /************** Ref. sddefs.c *********************************/ 229*53901Smckusick 230*53901Smckusick extern struct sddevinfo sddevinfo[]; 231*53901Smckusick 232*53901Smckusick /**************************************************************/ 233*53901Smckusick 234*53901Smckusick extern struct msg_list skeylist[]; 235*53901Smckusick extern struct msg_list ecodelist[]; 236*53901Smckusick 237*53901Smckusick extern int boothowto; 238*53901Smckusick extern int rsense_msg_disp; /* RSENSE-message display flag */ 239*53901Smckusick extern int mo_disp_format; /* MO format mode display flag */ 240*53901Smckusick 241*53901Smckusick int sd_ignore_error; 242*53901Smckusick 243*53901Smckusick static int re_init_done; 244*53901Smckusick 245*53901Smckusick static u_char sdwork[2340]; /* buffer for error recovery */ 246*53901Smckusick static u_char sdtmp[DEV_BSIZE]; /* buffer for temporary */ 247*53901Smckusick #ifdef mips 248*53901Smckusick volatile static int sdtmp_stat = 0; /* status of sdtmp */ 249*53901Smckusick #else 250*53901Smckusick static int sdtmp_stat = 0; /* status of sdtmp */ 251*53901Smckusick #endif 252*53901Smckusick 253*53901Smckusick char pname[] = "abcdefgh"; 254*53901Smckusick 255*53901Smckusick struct scsi *get_scsi(); 256*53901Smckusick struct sc_map *get_sc_map(); 257*53901Smckusick struct sc_inq *get_sc_inq(); 258*53901Smckusick 259*53901Smckusick int sdprobe(), sdslave(), sdattach(), sddgo(), sdintr(); 260*53901Smckusick int sdwstart, sdwatch(), sdstop(); /* Have started guardian */ 261*53901Smckusick void sdexec(); 262*53901Smckusick 263*53901Smckusick #ifdef CPU_SINGLE 264*53901Smckusick struct hb_driver sdcdriver = 265*53901Smckusick {sdprobe, sdslave, sdattach, sddgo, sdintr, "sd", sddinfo, "sdc", sdminfo}; 266*53901Smckusick #else 267*53901Smckusick struct iop_driver sdcdriver = 268*53901Smckusick {sdprobe, sdslave, sdattach, sddgo, "sd", sddinfo, "sdc", sdminfo}; 269*53901Smckusick #endif 270*53901Smckusick 271*53901Smckusick /*ARGSUSED*/ 272*53901Smckusick sdprobe(im) 273*53901Smckusick struct iop/**/_ctlr *im; 274*53901Smckusick { 275*53901Smckusick static int sdd_init = 0; 276*53901Smckusick register struct sc_inq *sci; 277*53901Smckusick register int ctlr; 278*53901Smckusick register int fw; 279*53901Smckusick int i; 280*53901Smckusick 281*53901Smckusick if (sdd_init == 0) { 282*53901Smckusick sdd_init++; 283*53901Smckusick for (i = 0; i < nsd; i++) 284*53901Smckusick sdd_softc[i].sdd_start = -2; 285*53901Smckusick } 286*53901Smckusick 287*53901Smckusick sci = get_sc_inq(im->im_intr); 288*53901Smckusick ctlr = im->im_ctlr; 289*53901Smckusick /* 290*53901Smckusick * Check device type 291*53901Smckusick * 0x00: Direct access device. 292*53901Smckusick * 0x01: Sequential access device. 293*53901Smckusick * 0x04: Write-once read-multiple device. 294*53901Smckusick * 0x05: Read-only Direct-access device. 295*53901Smckusick * 0x7f: Specified device is nonexistent. 296*53901Smckusick */ 297*53901Smckusick fw = sdc_softc[ctlr].sdc_firmware & ~SDCFW_DEVMASK; 298*53901Smckusick 299*53901Smckusick switch (sci->sci_devtype) { 300*53901Smckusick 301*53901Smckusick case 0x00: 302*53901Smckusick /* 303*53901Smckusick * Assumed that the device is HD. 304*53901Smckusick * Later, distinguish MO from HD. 305*53901Smckusick */ 306*53901Smckusick sdc_softc[ctlr].sdc_firmware = fw | SDCFW_HD; 307*53901Smckusick break; 308*53901Smckusick 309*53901Smckusick default: 310*53901Smckusick /* 311*53901Smckusick * device type mis-match 312*53901Smckusick */ 313*53901Smckusick return (0); 314*53901Smckusick } 315*53901Smckusick 316*53901Smckusick /* 317*53901Smckusick * Set interrupt handler routine 318*53901Smckusick */ 319*53901Smckusick if (set_inthandler(im, sdintr) == 0) 320*53901Smckusick return (0); 321*53901Smckusick 322*53901Smckusick return (1); 323*53901Smckusick } 324*53901Smckusick 325*53901Smckusick 326*53901Smckusick /*ARGSUSED*/ 327*53901Smckusick sdslave(ii, reg, intr) 328*53901Smckusick register struct iop/**/_device *ii; 329*53901Smckusick caddr_t reg; 330*53901Smckusick int intr; 331*53901Smckusick { 332*53901Smckusick register struct scsi *sc; 333*53901Smckusick 334*53901Smckusick sc = get_scsi(intr); 335*53901Smckusick sdip[ii->ii_ctlr][ii->ii_slave] = ii; 336*53901Smckusick ii->ii_intr = intr; 337*53901Smckusick 338*53901Smckusick /* 339*53901Smckusick * check what the device is. 340*53901Smckusick */ 341*53901Smckusick if ((ii->ii_type = sd_check(ii, sc)) < 0) 342*53901Smckusick goto bad_slave; 343*53901Smckusick 344*53901Smckusick /* 345*53901Smckusick * set up ERROR RECOVERY PARAMETERS 346*53901Smckusick */ 347*53901Smckusick if (sd_err_rcv(ii, sc) < 0) 348*53901Smckusick goto bad_slave; 349*53901Smckusick 350*53901Smckusick /* 351*53901Smckusick * set up OTHER PARAMETERS 352*53901Smckusick */ 353*53901Smckusick if (sd_other_pages(ii, sc) < 0) 354*53901Smckusick goto bad_slave; 355*53901Smckusick 356*53901Smckusick /* 357*53901Smckusick * set up Synchronous Transfer 358*53901Smckusick */ 359*53901Smckusick sd_synctr_on(ii, sc); 360*53901Smckusick 361*53901Smckusick return (1); 362*53901Smckusick 363*53901Smckusick bad_slave: 364*53901Smckusick /* 365*53901Smckusick * no such slave 366*53901Smckusick */ 367*53901Smckusick ii->ii_intr = -1; 368*53901Smckusick return (0); 369*53901Smckusick } 370*53901Smckusick 371*53901Smckusick identity_check(sci, capacity, unit) 372*53901Smckusick register struct sc_inq *sci; 373*53901Smckusick int capacity; 374*53901Smckusick int unit; 375*53901Smckusick { 376*53901Smckusick register struct sddevinfo *sdi; 377*53901Smckusick register u_char *id_name; 378*53901Smckusick register int index; 379*53901Smckusick register int i; 380*53901Smckusick int id_pass; 381*53901Smckusick 382*53901Smckusick id_name = sci->sci_vendid; 383*53901Smckusick while (*id_name == ' ') 384*53901Smckusick id_name++; 385*53901Smckusick 386*53901Smckusick index = UNKNOWN_DISK; 387*53901Smckusick id_pass = 0; 388*53901Smckusick for (sdi = sddevinfo; sdi->id_len >= 0; sdi++) { 389*53901Smckusick /* 390*53901Smckusick * check vendor & product ID 391*53901Smckusick */ 392*53901Smckusick if (strncmp(id_name, sdi->id_name, sdi->id_len) != 0) 393*53901Smckusick continue; 394*53901Smckusick id_pass = sdi - sddevinfo; 395*53901Smckusick 396*53901Smckusick /* 397*53901Smckusick * check revision 398*53901Smckusick */ 399*53901Smckusick if (strncmp(sdi->revs, sci->sci_revision, 4) == 0) 400*53901Smckusick index = id_pass; 401*53901Smckusick else { 402*53901Smckusick for (i = 0; i < 4; i++) { 403*53901Smckusick if (*(sdi->revs + i) == '?') 404*53901Smckusick continue; 405*53901Smckusick if (*(sdi->revs + i) != sci->sci_revision[i]) 406*53901Smckusick break; 407*53901Smckusick } 408*53901Smckusick if (i < 4) 409*53901Smckusick continue; 410*53901Smckusick } 411*53901Smckusick 412*53901Smckusick /* 413*53901Smckusick * check capacity 414*53901Smckusick */ 415*53901Smckusick if (capacity == -1) 416*53901Smckusick break; 417*53901Smckusick if (sdi->capacity == -1) { 418*53901Smckusick printf("sd%d: capacity=0x%x(%d)\n", 419*53901Smckusick unit, capacity, capacity); 420*53901Smckusick break; 421*53901Smckusick } 422*53901Smckusick if (capacity == sdi->capacity) 423*53901Smckusick break; 424*53901Smckusick } 425*53901Smckusick if (index == 0) 426*53901Smckusick index = id_pass; 427*53901Smckusick 428*53901Smckusick return (index); 429*53901Smckusick } 430*53901Smckusick 431*53901Smckusick search_index(type) 432*53901Smckusick register int type; 433*53901Smckusick { 434*53901Smckusick register struct sddevinfo *sdi; 435*53901Smckusick register int i; 436*53901Smckusick int index; 437*53901Smckusick 438*53901Smckusick index = UNKNOWN_DISK; 439*53901Smckusick i = 0; 440*53901Smckusick for (sdi = sddevinfo; sdi->id_len > 0; sdi++) { 441*53901Smckusick if (sdi->type == type) { 442*53901Smckusick index = i; 443*53901Smckusick break; 444*53901Smckusick } 445*53901Smckusick i++; 446*53901Smckusick } 447*53901Smckusick return (index); 448*53901Smckusick } 449*53901Smckusick 450*53901Smckusick static 451*53901Smckusick sd_check(ii, sc) 452*53901Smckusick register struct iop/**/_device *ii; 453*53901Smckusick register struct scsi *sc; 454*53901Smckusick { 455*53901Smckusick register struct sc_inq *sci; 456*53901Smckusick register struct sc_rcap *scr; 457*53901Smckusick register int intr; 458*53901Smckusick register int slave; 459*53901Smckusick register int unit; 460*53901Smckusick struct sdc_softc *sdc; 461*53901Smckusick struct sdd_softc *sdd; 462*53901Smckusick struct sc_extnd *sce; 463*53901Smckusick int retrycnt; 464*53901Smckusick int index; 465*53901Smckusick int media_in; 466*53901Smckusick 467*53901Smckusick intr = ii->ii_intr; 468*53901Smckusick slave = ii->ii_slave; 469*53901Smckusick unit = ii->ii_unit; 470*53901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 471*53901Smckusick sdd = &sdd_softc[unit]; 472*53901Smckusick scr = (struct sc_rcap *)sc->sc_param; 473*53901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 474*53901Smckusick 475*53901Smckusick /* 476*53901Smckusick * check if the logical unit is ready. 477*53901Smckusick * (by TEST UNIT READY command) 478*53901Smckusick */ 479*53901Smckusick media_in = sd_tstdrv(ii, sc); 480*53901Smckusick if (media_in < 0) 481*53901Smckusick return (-3); 482*53901Smckusick 483*53901Smckusick /* 484*53901Smckusick * Get controller and drive information. 485*53901Smckusick * (by INQUIRY command) 486*53901Smckusick */ 487*53901Smckusick retrycnt = 0; 488*53901Smckusick sci = get_sc_inq(intr); 489*53901Smckusick loop_inq: 490*53901Smckusick if (retrycnt++ > MAXPROBERETRY) 491*53901Smckusick return (-1); 492*53901Smckusick 493*53901Smckusick scop_inquiry(intr, sc, slave, SCSI_INTDIS, sizeof(struct sc_inq), sci); 494*53901Smckusick sc->sc_tstatus &= TGSTMASK; 495*53901Smckusick 496*53901Smckusick if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) { 497*53901Smckusick 498*53901Smckusick bzero((caddr_t)sce, RSEN_CNT); 499*53901Smckusick scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT, 500*53901Smckusick (caddr_t)sce); 501*53901Smckusick sc->sc_tstatus &= TGSTMASK; 502*53901Smckusick if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) 503*53901Smckusick return (-1); 504*53901Smckusick if (sce->sce_extend != 0x70) 505*53901Smckusick goto loop_inq; 506*53901Smckusick 507*53901Smckusick switch (sce->sce_sdecode) { 508*53901Smckusick 509*53901Smckusick case 0x04: /* Drive Not Ready */ 510*53901Smckusick case 0x28: /* Medium Changed */ 511*53901Smckusick case 0x29: /* Power On or Reset or Bus Device Reset */ 512*53901Smckusick case 0x2a: /* Mode Select Parameter Changed */ 513*53901Smckusick break; 514*53901Smckusick 515*53901Smckusick default: 516*53901Smckusick return (-1); 517*53901Smckusick } 518*53901Smckusick DELAY(D100MSEC); /* wait 100 ms. */ 519*53901Smckusick goto loop_inq; 520*53901Smckusick } 521*53901Smckusick 522*53901Smckusick index = identity_check(sci, -1, unit); 523*53901Smckusick 524*53901Smckusick switch (sddevinfo[index].type) { 525*53901Smckusick 526*53901Smckusick case SMO_S501: 527*53901Smckusick case SMO_S501_ISO: 528*53901Smckusick case SMO_S501_ISO2: 529*53901Smckusick sdc->sdc_firmware = 530*53901Smckusick SDCFW_MO | (sdc->sdc_firmware & ~SDCFW_DEVMASK); 531*53901Smckusick break; 532*53901Smckusick 533*53901Smckusick defaults: 534*53901Smckusick break; 535*53901Smckusick } 536*53901Smckusick 537*53901Smckusick if (sci->sci_qual & 0x80) { 538*53901Smckusick /* 539*53901Smckusick * removable medium device 540*53901Smckusick */ 541*53901Smckusick sdc->sdc_firmware |= SDCFW_RMB; 542*53901Smckusick if ((media_in == 0) || ((sdc->sdc_firmware & SDCFW_MO) == 0)) 543*53901Smckusick return (index); 544*53901Smckusick } 545*53901Smckusick 546*53901Smckusick /****************/ 547*53901Smckusick /* HD & MO only */ 548*53901Smckusick /****************/ 549*53901Smckusick /* 550*53901Smckusick * Get drive capacity 551*53901Smckusick * (by READ CAPACITY command) 552*53901Smckusick */ 553*53901Smckusick retrycnt = 0; 554*53901Smckusick loop_rcap: 555*53901Smckusick if (retrycnt++ > MAXPROBERETRY) 556*53901Smckusick return (-4); 557*53901Smckusick 558*53901Smckusick scop_rcap(intr, sc, slave, SCSI_INTDIS, 8, (caddr_t)0); 559*53901Smckusick sc->sc_tstatus &= TGSTMASK; 560*53901Smckusick if (sc->sc_istatus != INST_EP) 561*53901Smckusick return (-5); 562*53901Smckusick if (sc->sc_tstatus == TGST_CC) { 563*53901Smckusick bzero((caddr_t)sce, RSEN_CNT); 564*53901Smckusick scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT, 565*53901Smckusick (caddr_t)sce); 566*53901Smckusick sc->sc_tstatus &= TGSTMASK; 567*53901Smckusick if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) 568*53901Smckusick return (-6); 569*53901Smckusick if (sderrordisp((caddr_t)sce, ii) == FORMAT_MODE_CORRUPTED) { 570*53901Smckusick scr->scr_nblock = 0; 571*53901Smckusick scr->scr_blocklen = DEV_BSIZE; 572*53901Smckusick sdd->sdd_flags |= SDDF_NONFMT; 573*53901Smckusick } else { 574*53901Smckusick DELAY(D100MSEC); /* wait 100 ms. */ 575*53901Smckusick goto loop_rcap; 576*53901Smckusick } 577*53901Smckusick } 578*53901Smckusick else if (sc->sc_tstatus != TGST_GOOD) { 579*53901Smckusick DELAY(D100MSEC); /* wait 100 ms. */ 580*53901Smckusick goto loop_rcap; 581*53901Smckusick } 582*53901Smckusick 583*53901Smckusick sdd->sdd_nsect = scr->scr_nblock + 1; 584*53901Smckusick sdd->sdd_sectsize = scr->scr_blocklen; 585*53901Smckusick 586*53901Smckusick index = identity_check(sci, scr->scr_nblock +1, unit); 587*53901Smckusick 588*53901Smckusick return (index); 589*53901Smckusick } 590*53901Smckusick 591*53901Smckusick static 592*53901Smckusick sd_tstdrv(ii, sc) 593*53901Smckusick register struct iop/**/_device *ii; 594*53901Smckusick register struct scsi *sc; 595*53901Smckusick { 596*53901Smckusick register struct sc_extnd *sce; 597*53901Smckusick register int intr; 598*53901Smckusick register int slave; 599*53901Smckusick register int retrycnt; 600*53901Smckusick struct sdc_softc *sdc; 601*53901Smckusick struct sdd_softc *sdd; 602*53901Smckusick 603*53901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 604*53901Smckusick sdd = &sdd_softc[ii->ii_unit]; 605*53901Smckusick 606*53901Smckusick intr = ii->ii_intr; 607*53901Smckusick slave = ii->ii_slave; 608*53901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 609*53901Smckusick retrycnt = 0; 610*53901Smckusick loop_tst: 611*53901Smckusick if (retrycnt++ > MAXPROBERETRY) 612*53901Smckusick return (-1); 613*53901Smckusick 614*53901Smckusick scop_tst(intr, sc, slave, SCSI_INTDIS); 615*53901Smckusick sc->sc_tstatus &= TGSTMASK; 616*53901Smckusick if (sc->sc_istatus != INST_EP) { 617*53901Smckusick DELAY(D100MSEC); /* wait 100 ms. */ 618*53901Smckusick goto loop_tst; 619*53901Smckusick } 620*53901Smckusick 621*53901Smckusick switch (sc->sc_tstatus) { 622*53901Smckusick 623*53901Smckusick case TGST_CC: 624*53901Smckusick /* Get error code */ 625*53901Smckusick bzero((caddr_t)sce, RSEN_CNT); 626*53901Smckusick scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT, 627*53901Smckusick (caddr_t)sce); 628*53901Smckusick sc->sc_tstatus &= TGSTMASK; 629*53901Smckusick if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) { 630*53901Smckusick DELAY(D100MSEC); /* wait 100 ms. */ 631*53901Smckusick goto loop_tst; 632*53901Smckusick } 633*53901Smckusick 634*53901Smckusick if (sce->sce_extend != 0x70) 635*53901Smckusick goto loop_tst; 636*53901Smckusick 637*53901Smckusick switch (sce->sce_skey) { 638*53901Smckusick 639*53901Smckusick case 0x0: /* No Sense */ 640*53901Smckusick case 0x4: /* Hardware error */ 641*53901Smckusick case 0x6: /* Unit attention */ 642*53901Smckusick goto loop_tst; 643*53901Smckusick 644*53901Smckusick case 0x2: /* Not ready */ 645*53901Smckusick switch (sce->sce_sdecode) { 646*53901Smckusick 647*53901Smckusick case 0x04: /* Not ready */ 648*53901Smckusick /* 649*53901Smckusick * Drive not ready... so start.. 650*53901Smckusick */ 651*53901Smckusick scop_stst(intr, sc, slave, SCSI_INTDIS, SDSS_START); 652*53901Smckusick DELAY(D100MSEC * 10); /* wait 1 sec. */ 653*53901Smckusick goto loop_tst; 654*53901Smckusick 655*53901Smckusick case 0x0a: /* No Disk *//*MO*/ 656*53901Smckusick default: 657*53901Smckusick DELAY(D100MSEC); 658*53901Smckusick goto loop_tst; 659*53901Smckusick } 660*53901Smckusick break; 661*53901Smckusick 662*53901Smckusick case 0x03: 663*53901Smckusick if (sce->sce_sdecode == FORMAT_MODE_CORRUPTED) 664*53901Smckusick return (1); /* ignore error */ 665*53901Smckusick /* fall through */ 666*53901Smckusick 667*53901Smckusick default: 668*53901Smckusick return (-2); 669*53901Smckusick } 670*53901Smckusick break; 671*53901Smckusick 672*53901Smckusick case TGST_BUSY: 673*53901Smckusick goto loop_tst; 674*53901Smckusick 675*53901Smckusick case TGST_GOOD: 676*53901Smckusick break; 677*53901Smckusick 678*53901Smckusick default: 679*53901Smckusick return (-3); 680*53901Smckusick } 681*53901Smckusick 682*53901Smckusick return (1); 683*53901Smckusick } 684*53901Smckusick 685*53901Smckusick #ifdef NEWSOS4 686*53901Smckusick static 687*53901Smckusick sd_setup_cmds(ii, sc) 688*53901Smckusick register struct iop/**/_device *ii; 689*53901Smckusick register struct scsi *sc; 690*53901Smckusick { 691*53901Smckusick register struct sddevinfo *sdi; 692*53901Smckusick register struct sc_extnd *sce; 693*53901Smckusick struct sc_ureq **p; 694*53901Smckusick struct sc_ureq *scu; 695*53901Smckusick int error; 696*53901Smckusick extern struct sc_ureq scu_rsense; 697*53901Smckusick 698*53901Smckusick if ((p = sddevinfo[ii->ii_type].setup_cmds) == NULL) 699*53901Smckusick return (0); 700*53901Smckusick 701*53901Smckusick /* 702*53901Smckusick * Do setup commands 703*53901Smckusick */ 704*53901Smckusick while (scu = *p) { 705*53901Smckusick bcopy((caddr_t)scu, sdtmp, sizeof(struct sc_ureq)); 706*53901Smckusick scu = (struct sc_ureq *)sdtmp; 707*53901Smckusick scu->scu_cdb[1] |= (ii->ii_slave & 0x07) << 5; 708*53901Smckusick error = sd_scu_exec((ii->ii_unit << 3), scu, sc); 709*53901Smckusick if (error != 0) 710*53901Smckusick return (-1); 711*53901Smckusick if ((scu->scu_istatus != INST_EP) 712*53901Smckusick || (scu->scu_tstatus != TGST_GOOD)) { 713*53901Smckusick bcopy((caddr_t)&scu_rsense, sdtmp, sizeof(struct sc_ureq)); 714*53901Smckusick scu = (struct sc_ureq *)sdtmp; 715*53901Smckusick scu->scu_cdb[1] |= (ii->ii_slave & 0x07) << 5; 716*53901Smckusick sce = (scu->scu_addr == NULL) ? 717*53901Smckusick (struct sc_extnd *)scu->scu_param : 718*53901Smckusick (struct sc_extnd *)scu->scu_addr; 719*53901Smckusick if (sd_scu_exec((ii->ii_unit << 3), scu, sc) == 0) { 720*53901Smckusick /* UNIT ATTENTION */ 721*53901Smckusick /* retry same command */ 722*53901Smckusick if (sce->sce_skey == 0x06) 723*53901Smckusick continue; 724*53901Smckusick } 725*53901Smckusick } 726*53901Smckusick p++; 727*53901Smckusick } 728*53901Smckusick return (1); 729*53901Smckusick } 730*53901Smckusick #endif /* NEWSOS4 */ 731*53901Smckusick 732*53901Smckusick static 733*53901Smckusick sd_other_pages(ii, sc) 734*53901Smckusick register struct iop/**/_device *ii; 735*53901Smckusick register struct scsi *sc; 736*53901Smckusick { 737*53901Smckusick register struct sddevinfo *sdi; 738*53901Smckusick char **p; 739*53901Smckusick char *page; 740*53901Smckusick int length; 741*53901Smckusick int retrycnt; 742*53901Smckusick int len; 743*53901Smckusick 744*53901Smckusick sdi = &sddevinfo[ii->ii_type]; 745*53901Smckusick if ((p = sdi->other_pages) == NULL) 746*53901Smckusick return (0); 747*53901Smckusick 748*53901Smckusick /* 749*53901Smckusick * set other parameters 750*53901Smckusick */ 751*53901Smckusick while (page = *p++) { 752*53901Smckusick retrycnt = 0; 753*53901Smckusick loop_other_pages: 754*53901Smckusick bzero((caddr_t)sdtmp, 4); 755*53901Smckusick length = *(page + 1) + 2; 756*53901Smckusick bcopy(page, &sdtmp[4], length); 757*53901Smckusick if (retrycnt++ > MAXPROBERETRY) 758*53901Smckusick return (-1); 759*53901Smckusick 760*53901Smckusick scop_mselect(ii->ii_intr, sc, ii->ii_slave, SCSI_INTDIS, 761*53901Smckusick (SDM_PF<<24) + length +4, (caddr_t)sdtmp); 762*53901Smckusick sc->sc_tstatus &= TGSTMASK; 763*53901Smckusick if ((sc->sc_istatus != INST_EP) 764*53901Smckusick || (sc->sc_tstatus != TGST_GOOD)) { 765*53901Smckusick struct sc_extnd *sce; 766*53901Smckusick 767*53901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 768*53901Smckusick scop_rsense(ii->ii_intr, sc, ii->ii_slave, SCSI_INTDIS, 769*53901Smckusick RSEN_CNT, (caddr_t)sce); 770*53901Smckusick switch (sce->sce_skey) { 771*53901Smckusick 772*53901Smckusick case 0x00: 773*53901Smckusick case 0x02: 774*53901Smckusick case 0x04: 775*53901Smckusick case 0x06: 776*53901Smckusick DELAY(D100MSEC); /* 100 ms. */ 777*53901Smckusick goto loop_other_pages; 778*53901Smckusick 779*53901Smckusick default: 780*53901Smckusick return (-1); 781*53901Smckusick } 782*53901Smckusick } 783*53901Smckusick } 784*53901Smckusick 785*53901Smckusick if (sdi->firm_flags & FIRM_CACHE_ON) 786*53901Smckusick sdc_softc[ii->ii_ctlr].sdc_firmware |= SDCFW_CACHE; 787*53901Smckusick else 788*53901Smckusick sdc_softc[ii->ii_ctlr].sdc_firmware &= ~SDCFW_CACHE; 789*53901Smckusick 790*53901Smckusick return (1); 791*53901Smckusick } 792*53901Smckusick 793*53901Smckusick static 794*53901Smckusick sd_err_rcv(ii, sc) 795*53901Smckusick register struct iop/**/_device *ii; 796*53901Smckusick register struct scsi *sc; 797*53901Smckusick { 798*53901Smckusick register struct sdc_softc *sdc; 799*53901Smckusick register int intr; 800*53901Smckusick register int slave; 801*53901Smckusick register int len; 802*53901Smckusick struct sc_extnd *sce; 803*53901Smckusick struct sdd_softc *sdd; 804*53901Smckusick struct sddevinfo *sdi; 805*53901Smckusick int retrycnt; 806*53901Smckusick char *erp_page; 807*53901Smckusick 808*53901Smckusick intr = ii->ii_intr; 809*53901Smckusick slave = ii->ii_slave; 810*53901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 811*53901Smckusick sdd = &sdd_softc[ii->ii_unit]; 812*53901Smckusick sdi = &sddevinfo[ii->ii_type]; 813*53901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 814*53901Smckusick 815*53901Smckusick /* 816*53901Smckusick * set Default DISK sector size 817*53901Smckusick */ 818*53901Smckusick if (sdd->sdd_sectsize == 0) 819*53901Smckusick sdd->sdd_sectsize = DEV_BSIZE; 820*53901Smckusick 821*53901Smckusick 822*53901Smckusick if (sdi->ERP_page == NULL) { 823*53901Smckusick /* 824*53901Smckusick * use default error recovery parameters 825*53901Smckusick */ 826*53901Smckusick sdc->sdc_firmware |= SDCFW_DEFMODE; 827*53901Smckusick return (0); 828*53901Smckusick } 829*53901Smckusick 830*53901Smckusick if (sdi->firm_flags & FIRM_AWRE) 831*53901Smckusick sdc->sdc_firmware |= SDCFW_AWRE; 832*53901Smckusick if (sdi->firm_flags & FIRM_ARRE) 833*53901Smckusick sdc->sdc_firmware |= SDCFW_ARRE; 834*53901Smckusick /* 835*53901Smckusick * set ERROR RECOVERY PARAMETERS 836*53901Smckusick */ 837*53901Smckusick loop_err_rcv: 838*53901Smckusick bzero((caddr_t)sdtmp, 4); 839*53901Smckusick erp_page = sdi->ERP_page; 840*53901Smckusick len = *(erp_page + 1) + 2; 841*53901Smckusick bcopy(erp_page, &sdtmp[4], len); 842*53901Smckusick 843*53901Smckusick scop_mselect(intr, sc, slave, SCSI_INTDIS, 844*53901Smckusick (SDM_PF<<24) + len +4, (caddr_t)sdtmp); 845*53901Smckusick sc->sc_tstatus &= TGSTMASK; 846*53901Smckusick if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) { 847*53901Smckusick if (sc->sc_tstatus == TGST_CC) { 848*53901Smckusick bzero((caddr_t)sce, RSEN_CNT); 849*53901Smckusick scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT, 850*53901Smckusick (caddr_t)sce); 851*53901Smckusick if (sce->sce_sdecode == 0x2a) { 852*53901Smckusick /* mode select parameter changed */ 853*53901Smckusick goto ercv_done; 854*53901Smckusick } else if (sce->sce_skey == 0x6) { 855*53901Smckusick /* unit attention */ 856*53901Smckusick goto loop_err_rcv; 857*53901Smckusick } 858*53901Smckusick } 859*53901Smckusick /* 860*53901Smckusick * use default ERROR RECOVERY mode 861*53901Smckusick */ 862*53901Smckusick sdc->sdc_firmware |= SDCFW_DEFMODE; 863*53901Smckusick sdc->sdc_firmware &= ~(SDCFW_AWRE|SDCFW_ARRE); 864*53901Smckusick } 865*53901Smckusick 866*53901Smckusick ercv_done: 867*53901Smckusick 868*53901Smckusick return (1); 869*53901Smckusick } 870*53901Smckusick 871*53901Smckusick static 872*53901Smckusick sd_synctr_on(ii, sc) 873*53901Smckusick register struct iop/**/_device *ii; 874*53901Smckusick register struct scsi *sc; 875*53901Smckusick { 876*53901Smckusick register struct sddevinfo *sdi; 877*53901Smckusick register struct sync_param *syncp; 878*53901Smckusick 879*53901Smckusick sdi = &sddevinfo[ii->ii_type]; 880*53901Smckusick 881*53901Smckusick if (sdi->firm_flags & FIRM_SYNCTR) { 882*53901Smckusick scinit(sc, ii->ii_slave, DEV_BSIZE); 883*53901Smckusick sc->sc_opcode = SCOP_TST; 884*53901Smckusick sc->sc_message = MSG_EXTND; /* extended message */ 885*53901Smckusick sc->sc_param[0] = MSG_EXTND; 886*53901Smckusick sc->sc_param[1] = 0x03; 887*53901Smckusick sc->sc_param[2] = 0x01; /* synchronous transfer */ 888*53901Smckusick sc->sc_param[3] = sdi->tr_period; /* transfer period */ 889*53901Smckusick sc->sc_param[4] = sdi->tr_offset; /* REQ offset */ 890*53901Smckusick 891*53901Smckusick if (sdc_softc[ii->ii_ctlr].sdc_firmware & SDCFW_CACHE) 892*53901Smckusick sc->sc_tstatus |= TS_CONTR_ON; /* contiguous TR ON */ 893*53901Smckusick else 894*53901Smckusick sc->sc_tstatus |= TS_CONTR_OFF; /* contiguous TR OFF */ 895*53901Smckusick 896*53901Smckusick #ifdef news1800 897*53901Smckusick if (scsi_berr_bug() != 0) { 898*53901Smckusick sc->sc_tstatus &= ~TS_CONTR_ON; 899*53901Smckusick sc->sc_tstatus |= TS_CONTR_OFF; 900*53901Smckusick } 901*53901Smckusick #endif 902*53901Smckusick 903*53901Smckusick if (sc->sc_tstatus & TS_CONTR_OFF) 904*53901Smckusick sdc_softc[ii->ii_ctlr].sdc_firmware &= ~SDCFW_CONTR; 905*53901Smckusick else 906*53901Smckusick sdc_softc[ii->ii_ctlr].sdc_firmware |= SDCFW_CONTR; 907*53901Smckusick 908*53901Smckusick sc_go(ii->ii_intr, sc, SCSI_INTDIS); 909*53901Smckusick 910*53901Smckusick syncp = &sd_sync_param[ii->ii_unit]; 911*53901Smckusick syncp->tr_period = sc->sc_param[3]; 912*53901Smckusick syncp->tr_offset = sc->sc_param[4]; 913*53901Smckusick if (sc->sc_param[4]) 914*53901Smckusick sdd_softc[ii->ii_unit].sdd_flags |= SDDF_SYNCTR; 915*53901Smckusick } 916*53901Smckusick } 917*53901Smckusick 918*53901Smckusick 919*53901Smckusick sdattach(ii) 920*53901Smckusick register struct iop/**/_device *ii; 921*53901Smckusick { 922*53901Smckusick register int unit; 923*53901Smckusick register int i; 924*53901Smckusick struct sdc_softc *sdc; 925*53901Smckusick struct sdd_softc *sdd; 926*53901Smckusick int dummy; 927*53901Smckusick 928*53901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 929*53901Smckusick sdc->sdc_timeo = 60; /* timeout 60 sec */ 930*53901Smckusick 931*53901Smckusick unit = ii->ii_unit; 932*53901Smckusick sdd = &sdd_softc[unit]; 933*53901Smckusick sdd->sdd_stoptime = OD_STOPTIME; /* REMOVABLE MEDIA */ 934*53901Smckusick sdd->sdd_start = -2; 935*53901Smckusick 936*53901Smckusick sdmaptype(ii); 937*53901Smckusick 938*53901Smckusick if (sdwstart == 0) { 939*53901Smckusick sdwstart++; 940*53901Smckusick timeout(sdwatch, (caddr_t)0, hz); 941*53901Smckusick timeout(sdstop, (caddr_t)0, hz); 942*53901Smckusick } 943*53901Smckusick 944*53901Smckusick #ifdef NEWSOS4 945*53901Smckusick /* 946*53901Smckusick * Do setup commands 947*53901Smckusick */ 948*53901Smckusick if (sd_setup_cmds(ii, get_scsi(ii->ii_intr)) < 0) 949*53901Smckusick printf("sd%d: setup failure\n", ii->ii_unit); 950*53901Smckusick #endif 951*53901Smckusick 952*53901Smckusick /* 953*53901Smckusick * initialize open flag 954*53901Smckusick */ 955*53901Smckusick for (i = 0; i < PNUM; i++) { 956*53901Smckusick sd_b_openf[unit][i] = 0; 957*53901Smckusick sd_c_openf[unit][i] = 0; 958*53901Smckusick } 959*53901Smckusick 960*53901Smckusick if (re_init_done > 0) 961*53901Smckusick return; 962*53901Smckusick 963*53901Smckusick if (sdc->sdc_firmware & SDCFW_HD) { 964*53901Smckusick /* 965*53901Smckusick * If device is Hard Disk, 966*53901Smckusick * then get partition information. 967*53901Smckusick */ 968*53901Smckusick sdrpartinfo(ii); 969*53901Smckusick dummy = DEV_BSIZE * sdstdrv[unit].rps * sdstdrv[unit].nsect; 970*53901Smckusick } else 971*53901Smckusick dummy = DEV_BSIZE * 40 * 31; 972*53901Smckusick 973*53901Smckusick if (ii->ii_dk >= 0 && dummy) 974*53901Smckusick dk_wpms[ii->ii_dk] = dummy / (2 * 1000000); 975*53901Smckusick } 976*53901Smckusick 977*53901Smckusick sdmaptype(ii) 978*53901Smckusick register struct iop/**/_device *ii; 979*53901Smckusick { 980*53901Smckusick printf("sd%d: %s\n", ii->ii_unit, sddevinfo[ii->ii_type].call_name); 981*53901Smckusick } 982*53901Smckusick 983*53901Smckusick int sd_b_major = -1; 984*53901Smckusick 985*53901Smckusick sd_b_open(dev, flag) 986*53901Smckusick dev_t dev; 987*53901Smckusick int flag; 988*53901Smckusick { 989*53901Smckusick sd_b_major = major(dev); 990*53901Smckusick return (_sdopen(dev, flag, S_IFBLK)); 991*53901Smckusick } 992*53901Smckusick 993*53901Smckusick int sd_c_major = -1; 994*53901Smckusick 995*53901Smckusick sd_c_open(dev, flag) 996*53901Smckusick dev_t dev; 997*53901Smckusick int flag; 998*53901Smckusick { 999*53901Smckusick sd_c_major = major(dev); 1000*53901Smckusick return (_sdopen(dev, flag, S_IFCHR)); 1001*53901Smckusick } 1002*53901Smckusick 1003*53901Smckusick _sdopen(dev, flag, fmt) 1004*53901Smckusick register dev_t dev; 1005*53901Smckusick int flag; 1006*53901Smckusick int fmt; 1007*53901Smckusick { 1008*53901Smckusick register struct iop/**/_device *ii; 1009*53901Smckusick register struct sdd_softc *sdd; 1010*53901Smckusick register struct sdc_softc *sdc; 1011*53901Smckusick register struct sddevinfo *sdi; 1012*53901Smckusick register int unit; 1013*53901Smckusick register int i; 1014*53901Smckusick u_char *sdopfp; 1015*53901Smckusick u_char old_sdopf; 1016*53901Smckusick int media_changed; 1017*53901Smckusick int s; 1018*53901Smckusick int stat; 1019*53901Smckusick struct scsi uscsi; 1020*53901Smckusick 1021*53901Smckusick unit = dev2unit(dev); 1022*53901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) 1023*53901Smckusick return (ENXIO); 1024*53901Smckusick 1025*53901Smckusick sdd = &sdd_softc[unit]; 1026*53901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 1027*53901Smckusick sdi = &sddevinfo[ii->ii_type]; 1028*53901Smckusick 1029*53901Smckusick if (sdd->sdd_flags & SDDF_XUSE) 1030*53901Smckusick return (EBUSY); 1031*53901Smckusick 1032*53901Smckusick /* 1033*53901Smckusick * LOCK while sdstop() running. 1034*53901Smckusick */ 1035*53901Smckusick s = splclock(); 1036*53901Smckusick while (sdc->sdc_state & SDCS_SCUNLOCK) { 1037*53901Smckusick sdc->sdc_state |= SDCS_OPEN_WAIT; 1038*53901Smckusick sleep((caddr_t)sdc, PRIBIO); 1039*53901Smckusick } 1040*53901Smckusick splx(s); 1041*53901Smckusick 1042*53901Smckusick /* 1043*53901Smckusick * LOCK sdtmp buffer 1044*53901Smckusick */ 1045*53901Smckusick s = splclock(); 1046*53901Smckusick while (sdtmp_stat & B_BUSY) { 1047*53901Smckusick sdtmp_stat |= B_WANTED; 1048*53901Smckusick sleep((caddr_t)sdtmp, PRIBIO); 1049*53901Smckusick } 1050*53901Smckusick sdtmp_stat |= B_BUSY; 1051*53901Smckusick splx(s); 1052*53901Smckusick sdd->sdd_flags |= SDDF_GETTMP; 1053*53901Smckusick 1054*53901Smckusick if ((fmt & S_IFMT) == S_IFBLK) 1055*53901Smckusick sdopfp = &sd_b_openf[unit][dev2part(dev)]; 1056*53901Smckusick else 1057*53901Smckusick sdopfp = &sd_c_openf[unit][dev2part(dev)]; 1058*53901Smckusick old_sdopf = *sdopfp; 1059*53901Smckusick if (old_sdopf <= 1) 1060*53901Smckusick *sdopfp += 1; /* 1: 1st open (ONLY_ONE) */ 1061*53901Smckusick /* 2: already opened */ 1062*53901Smckusick stat = 0; 1063*53901Smckusick media_changed = 0; 1064*53901Smckusick 1065*53901Smckusick /* 1066*53901Smckusick * From here on until pre_open_done is only for removable devices 1067*53901Smckusick */ 1068*53901Smckusick if ((sdc->sdc_firmware & SDCFW_RMB) == 0) 1069*53901Smckusick goto pre_open_done; 1070*53901Smckusick 1071*53901Smckusick if ((minor(dev) & 0x80) || (dev == rootdev)) 1072*53901Smckusick sdd->sdd_stoptime = 0x7fffffff; /*XXX*/ 1073*53901Smckusick 1074*53901Smckusick /* 1075*53901Smckusick * Start Unit 1076*53901Smckusick */ 1077*53901Smckusick s = splclock(); /* inhibit clock interrupt */ 1078*53901Smckusick i = sdd->sdd_start; 1079*53901Smckusick sdd->sdd_start = sdd->sdd_stoptime; 1080*53901Smckusick splx(s); 1081*53901Smckusick if (i <= 0) { 1082*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 1083*53901Smckusick uscsi.sc_opcode = SCOP_STST; 1084*53901Smckusick uscsi.sc_count = SDSS_START; 1085*53901Smckusick 1086*53901Smckusick if (sdcmd(dev, &uscsi)) { 1087*53901Smckusick sdd->sdd_start = i; 1088*53901Smckusick if ((flag & FWRITE) == 0) 1089*53901Smckusick goto sdopen_setup; 1090*53901Smckusick stat = EIO; 1091*53901Smckusick goto pre_open_done; 1092*53901Smckusick } 1093*53901Smckusick } 1094*53901Smckusick 1095*53901Smckusick /* 1096*53901Smckusick * prevent medium removal 1097*53901Smckusick */ 1098*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 1099*53901Smckusick uscsi.sc_opcode = SCOP_MEDRMV; 1100*53901Smckusick uscsi.sc_count = SDRMV_PREV; 1101*53901Smckusick if (sdcmd(dev, &uscsi)) { 1102*53901Smckusick stat = EIO; 1103*53901Smckusick goto pre_open_done; 1104*53901Smckusick } 1105*53901Smckusick sdd->sdd_flags |= SDDF_INHRMV; 1106*53901Smckusick 1107*53901Smckusick sdopen_setup: 1108*53901Smckusick if ((sdd->sdd_flags & SDDF_SAMEDSK) == SDDF_DSKCHGD) { 1109*53901Smckusick sdd->sdd_flags |= SDDF_SAMEDSK; 1110*53901Smckusick media_changed = 1; 1111*53901Smckusick 1112*53901Smckusick /* 1113*53901Smckusick * From here on until mo_check_done is only for MO device 1114*53901Smckusick */ 1115*53901Smckusick if ((sdc->sdc_firmware & SDCFW_MO) == 0) 1116*53901Smckusick goto mo_check_done; 1117*53901Smckusick 1118*53901Smckusick /* 1119*53901Smckusick * Mode Sense 1120*53901Smckusick */ 1121*53901Smckusick bzero(sdtmp, 36); 1122*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 1123*53901Smckusick uscsi.sc_cpoint = sdtmp; 1124*53901Smckusick uscsi.sc_ctrnscnt = 36; 1125*53901Smckusick uscsi.sc_opcode = SCOP_MSENSE; 1126*53901Smckusick uscsi.sc_lad = (SDM_PF << 16)|((SDM_PC_CUR|SDM_PCODE_ALL) << 8); 1127*53901Smckusick uscsi.sc_count = 36; 1128*53901Smckusick 1129*53901Smckusick if (sdcmd(dev, &uscsi) == 0) { 1130*53901Smckusick /* 1131*53901Smckusick * check Write Protect mode 1132*53901Smckusick */ 1133*53901Smckusick if (sdtmp[2] & 0x80) 1134*53901Smckusick sdd->sdd_flags |= SDDF_WPROTECT; 1135*53901Smckusick else 1136*53901Smckusick sdd->sdd_flags &= ~SDDF_WPROTECT; 1137*53901Smckusick /* 1138*53901Smckusick * check Format Mode 1139*53901Smckusick */ 1140*53901Smckusick if (sdtmp[26] == 2) { 1141*53901Smckusick ii->ii_type = search_index(SMO_S501); 1142*53901Smckusick if (mo_disp_format) 1143*53901Smckusick printf("sd%d: format mode 2 (original format)\n", unit); 1144*53901Smckusick } else if (sdtmp[26] == 3) { 1145*53901Smckusick int spare; 1146*53901Smckusick 1147*53901Smckusick spare = *(short *)&sdtmp[32]; 1148*53901Smckusick if (spare == 2048) 1149*53901Smckusick ii->ii_type = 1150*53901Smckusick search_index(SMO_S501_ISO2); 1151*53901Smckusick else 1152*53901Smckusick ii->ii_type = 1153*53901Smckusick search_index(SMO_S501_ISO); 1154*53901Smckusick if (mo_disp_format) 1155*53901Smckusick printf("sd%d: format mode 3 (ISO format) spare=%d\n", unit, spare); 1156*53901Smckusick } else { 1157*53901Smckusick sdd->sdd_flags |= SDDF_NONFMT; 1158*53901Smckusick if (mo_disp_format) 1159*53901Smckusick printf("sd%d: Non format\n", unit); 1160*53901Smckusick } 1161*53901Smckusick sdi = &sddevinfo[ii->ii_type]; 1162*53901Smckusick } 1163*53901Smckusick 1164*53901Smckusick /* 1165*53901Smckusick * Mode Select 1166*53901Smckusick * Error Recovery Parameters set 1167*53901Smckusick */ 1168*53901Smckusick i = *(sdi->ERP_page +1) + 2; /* page length */ 1169*53901Smckusick bzero(sdtmp, i + 4); 1170*53901Smckusick bcopy(sdi->ERP_page, (caddr_t)&sdtmp[4], i); 1171*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 1172*53901Smckusick uscsi.sc_cpoint = sdtmp; 1173*53901Smckusick uscsi.sc_ctrnscnt = i + 4; 1174*53901Smckusick uscsi.sc_opcode = SCOP_MSELECT; 1175*53901Smckusick uscsi.sc_lad = (SDM_PF << 16); 1176*53901Smckusick uscsi.sc_count = i + 4; 1177*53901Smckusick 1178*53901Smckusick (void) sdcmd(dev, &uscsi); 1179*53901Smckusick 1180*53901Smckusick /* 1181*53901Smckusick * Read Grown Defect list 1182*53901Smckusick */ 1183*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 1184*53901Smckusick uscsi.sc_cpoint = sdtmp; 1185*53901Smckusick uscsi.sc_ctrnscnt = 4; 1186*53901Smckusick uscsi.sc_opcode = SCOP_RDL; 1187*53901Smckusick uscsi.sc_cdb.un_type1.t1_ladhi = (SDDL_GLIST|SDDL_PHYSFMT) << 8; 1188*53901Smckusick uscsi.sc_cdb.un_type1.t1_p3 = 4; 1189*53901Smckusick 1190*53901Smckusick (void) sdcmd(dev, &uscsi); 1191*53901Smckusick i = *(short *)&sdtmp[2] / 8; 1192*53901Smckusick if (i > (1024*9/10)) 1193*53901Smckusick printf("sd%d: WARNING: DEFECT SPARE LOCATION < 10%\n", 1194*53901Smckusick unit); 1195*53901Smckusick mo_check_done: 1196*53901Smckusick /* 1197*53901Smckusick * Read Capacity 1198*53901Smckusick */ 1199*53901Smckusick bzero((caddr_t)sdtmp, 8); 1200*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 1201*53901Smckusick uscsi.sc_cpoint = sdtmp; 1202*53901Smckusick uscsi.sc_ctrnscnt = 8; 1203*53901Smckusick uscsi.sc_opcode = SCOP_RCAP; 1204*53901Smckusick 1205*53901Smckusick (void) sdcmd(dev, &uscsi); 1206*53901Smckusick sdd->sdd_nsect = *(int *)&sdtmp[0] + 1; 1207*53901Smckusick sdd->sdd_sectsize = *(int *)&sdtmp[4]; 1208*53901Smckusick 1209*53901Smckusick if ((sdd->sdd_sectsize != DEV_BSIZE) 1210*53901Smckusick && (sdd->sdd_sectsize != SDBSIZE1K)) 1211*53901Smckusick sdd->sdd_sectsize = DEV_BSIZE; 1212*53901Smckusick } 1213*53901Smckusick 1214*53901Smckusick if ((sdd->sdd_flags & SDDF_WPROTECT) && (flag & FWRITE)) 1215*53901Smckusick stat = EROFS; 1216*53901Smckusick 1217*53901Smckusick pre_open_done: 1218*53901Smckusick 1219*53901Smckusick if (stat == 0) { 1220*53901Smckusick if ((isalone(unit) == ONLY_ONE) || media_changed) { 1221*53901Smckusick /* 1222*53901Smckusick * read partition information from sector zero. 1223*53901Smckusick */ 1224*53901Smckusick sdrpartinfo(ii); 1225*53901Smckusick if (ii->ii_dk >= 0) { 1226*53901Smckusick dk_wpms[ii->ii_dk] = 1227*53901Smckusick sdd->sdd_sectsize * sdstdrv[unit].rps 1228*53901Smckusick * sdstdrv[unit].nsect / (2 * 1000000); 1229*53901Smckusick } 1230*53901Smckusick } 1231*53901Smckusick } else { 1232*53901Smckusick /* 1233*53901Smckusick * open error 1234*53901Smckusick */ 1235*53901Smckusick *sdopfp = old_sdopf; 1236*53901Smckusick if ((sdd->sdd_flags & SDDF_INHRMV) && (isalone(unit) == 0)) { 1237*53901Smckusick sdd->sdd_flags &= ~SDDF_INHRMV; 1238*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 1239*53901Smckusick uscsi.sc_opcode = SCOP_MEDRMV; 1240*53901Smckusick uscsi.sc_count = SDRMV_ALLOW; 1241*53901Smckusick (void) sdcmd(dev, &uscsi); 1242*53901Smckusick } 1243*53901Smckusick } 1244*53901Smckusick 1245*53901Smckusick /* 1246*53901Smckusick * UNLOCK open 1247*53901Smckusick */ 1248*53901Smckusick s = splclock(); 1249*53901Smckusick sdd->sdd_flags &= ~SDDF_GETTMP; 1250*53901Smckusick if (sdtmp_stat & B_WANTED) 1251*53901Smckusick wakeup((caddr_t)sdtmp); 1252*53901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 1253*53901Smckusick splx(s); 1254*53901Smckusick return (stat); 1255*53901Smckusick } 1256*53901Smckusick 1257*53901Smckusick int sd_access_check_on; /* Common flags for sd_access_check() */ 1258*53901Smckusick 1259*53901Smckusick sd_access_check(bp) 1260*53901Smckusick register struct buf *bp; 1261*53901Smckusick { 1262*53901Smckusick register struct iop/**/_device *ii; 1263*53901Smckusick register struct sdd_softc *sdd; 1264*53901Smckusick int unit; 1265*53901Smckusick int check_part; 1266*53901Smckusick int limit; 1267*53901Smckusick int over; 1268*53901Smckusick register struct size *sizes; 1269*53901Smckusick register int lba; /* logical block address */ 1270*53901Smckusick register int sz; 1271*53901Smckusick register int i; 1272*53901Smckusick 1273*53901Smckusick check_part = 0; 1274*53901Smckusick unit = dev2unit(bp->b_dev); 1275*53901Smckusick ii = sddinfo[unit]; 1276*53901Smckusick sdd = &sdd_softc[unit]; 1277*53901Smckusick sizes = sdstdrv[unit].sizes; 1278*53901Smckusick 1279*53901Smckusick lba = sizes[dev2part(bp->b_dev)].sd_blkoff + dkblock(bp); 1280*53901Smckusick sz = howmany(bp->b_bcount, sdd->sdd_sectsize); 1281*53901Smckusick 1282*53901Smckusick /* 1283*53901Smckusick * When block device is used, 1284*53901Smckusick * inhibit raw device write operation. 1285*53901Smckusick */ 1286*53901Smckusick if ((major(bp->b_dev) == sd_c_major) /* RAW I/O */ 1287*53901Smckusick && ((bp->b_flags & B_READ) == 0) /* WRITE */ 1288*53901Smckusick && ((ii->ii_flags & SD_F_ENW) == 0) /* INHIBIT */ 1289*53901Smckusick && ((sd_access_check_on & SD_F_ENW) == 0)) { 1290*53901Smckusick 1291*53901Smckusick for (i = 0; i < PNUM; i++) { 1292*53901Smckusick if (sd_b_openf[unit][i] == 0) 1293*53901Smckusick continue; 1294*53901Smckusick /* 1295*53901Smckusick * |----|========|---|======|-------| 1296*53901Smckusick * 1 |---+++--------------------------| CUT OFF 1297*53901Smckusick * 2 |---++++++++++++-----------------| CUT OFF 1298*53901Smckusick * 3 |---++++++++++++++++-------------| CUT OFF 1299*53901Smckusick * 4 |---++++++++++++++++++++++++-----| CUT OFF 1300*53901Smckusick * 5 |-------+++----------------------| ERROR 1301*53901Smckusick * 6 |------------+++-----------------| ERROR 1302*53901Smckusick * 7 |------------+++++++-------------| ERROR 1303*53901Smckusick * 8 |------------+++++++++++++++-----| ERROR 1304*53901Smckusick */ 1305*53901Smckusick if ((lba < (sizes[i].sd_blkoff + sizes[i].sd_nblocks)) 1306*53901Smckusick && ((lba + sz) > sizes[i].sd_blkoff)) 1307*53901Smckusick check_part |= (1 << i); 1308*53901Smckusick } 1309*53901Smckusick } 1310*53901Smckusick 1311*53901Smckusick if (check_part) { 1312*53901Smckusick limit = 0x7fffffff; /* XXX */ 1313*53901Smckusick for (i = 0; i < PNUM; i++) { 1314*53901Smckusick if ((check_part & (1 << i)) == 0) 1315*53901Smckusick continue; 1316*53901Smckusick 1317*53901Smckusick if (lba >= sizes[i].sd_blkoff) { 1318*53901Smckusick bp->b_flags |= B_ERROR; 1319*53901Smckusick bp->b_error = EIO; 1320*53901Smckusick bp->b_resid = bp->b_bcount; 1321*53901Smckusick 1322*53901Smckusick printf("sd%d%c: RAW DEVICE WRITE PROTECTED: ", 1323*53901Smckusick unit, pname[dev2part(bp->b_dev)]); 1324*53901Smckusick printf("sn = 0x%x(%d), off = 0x%x(%d)\n", 1325*53901Smckusick dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize, 1326*53901Smckusick dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize, 1327*53901Smckusick sizes[dev2part(bp->b_dev)].sd_blkoff, 1328*53901Smckusick sizes[dev2part(bp->b_dev)].sd_blkoff); 1329*53901Smckusick 1330*53901Smckusick return (-1); 1331*53901Smckusick } 1332*53901Smckusick 1333*53901Smckusick if (sizes[i].sd_blkoff < limit) 1334*53901Smckusick limit = sizes[i].sd_blkoff; 1335*53901Smckusick } 1336*53901Smckusick } else { 1337*53901Smckusick limit = sizes[dev2part(bp->b_dev)].sd_blkoff 1338*53901Smckusick + sizes[dev2part(bp->b_dev)].sd_nblocks; 1339*53901Smckusick } 1340*53901Smckusick 1341*53901Smckusick if ((over = (lba + sz) - limit) > 0) { 1342*53901Smckusick /* 1343*53901Smckusick * Logical Block Address is outside the valid area. 1344*53901Smckusick */ 1345*53901Smckusick if (((ii->ii_flags & SD_F_EOLBA) != 0) 1346*53901Smckusick || ((sd_access_check_on & SD_F_EOLBA) != 0)) { 1347*53901Smckusick /* 1348*53901Smckusick * error if outside LBA 1349*53901Smckusick */ 1350*53901Smckusick return(-1); 1351*53901Smckusick } 1352*53901Smckusick bp->b_resid = bp->b_bcount - (sz - over) * sdd->sdd_sectsize; 1353*53901Smckusick if (bp->b_resid >= bp->b_bcount) { 1354*53901Smckusick bp->b_resid = bp->b_bcount; 1355*53901Smckusick return(-1); 1356*53901Smckusick } 1357*53901Smckusick } 1358*53901Smckusick 1359*53901Smckusick return (0); 1360*53901Smckusick } 1361*53901Smckusick 1362*53901Smckusick sd_b_close(dev, flag) 1363*53901Smckusick dev_t dev; 1364*53901Smckusick int flag; 1365*53901Smckusick { 1366*53901Smckusick return (_sdclose(dev, flag, S_IFBLK)); 1367*53901Smckusick } 1368*53901Smckusick 1369*53901Smckusick sd_c_close(dev, flag) 1370*53901Smckusick dev_t dev; 1371*53901Smckusick int flag; 1372*53901Smckusick { 1373*53901Smckusick return (_sdclose(dev, flag, S_IFCHR)); 1374*53901Smckusick } 1375*53901Smckusick 1376*53901Smckusick _sdclose(dev, flag, fmt) 1377*53901Smckusick register dev_t dev; 1378*53901Smckusick int flag; 1379*53901Smckusick int fmt; 1380*53901Smckusick { 1381*53901Smckusick register struct iop/**/_device *ii; 1382*53901Smckusick register struct sdd_softc *sdd; 1383*53901Smckusick register int unit; 1384*53901Smckusick struct sdc_softc *sdc; 1385*53901Smckusick struct scsi uscsi; 1386*53901Smckusick struct sc_extnd *sce; 1387*53901Smckusick 1388*53901Smckusick unit = dev2unit(dev); 1389*53901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) 1390*53901Smckusick return (ENXIO); 1391*53901Smckusick 1392*53901Smckusick sdd = &sdd_softc[unit]; 1393*53901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 1394*53901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 1395*53901Smckusick 1396*53901Smckusick /* 1397*53901Smckusick * still remain jobs 1398*53901Smckusick * sleep about 10ms -> 1sec 1399*53901Smckusick */ 1400*53901Smckusick while (ii->ii_mi->im_tab.b_actf != NULL) 1401*53901Smckusick sleep((caddr_t)&lbolt, PRIBIO); 1402*53901Smckusick 1403*53901Smckusick if ((fmt & S_IFMT) == S_IFBLK) 1404*53901Smckusick sd_b_openf[unit][dev2part(dev)] = 0; 1405*53901Smckusick else 1406*53901Smckusick sd_c_openf[unit][dev2part(dev)] = 0; 1407*53901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 1408*53901Smckusick 1409*53901Smckusick if ((sdc->sdc_firmware & SDCFW_RMB) && (isalone(unit) == 0)) { 1410*53901Smckusick sdd->sdd_flags &= ~SDDF_INHRMV; 1411*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 1412*53901Smckusick uscsi.sc_opcode = SCOP_MEDRMV; 1413*53901Smckusick uscsi.sc_count = SDRMV_ALLOW; 1414*53901Smckusick (void) sdcmd(dev, &uscsi); 1415*53901Smckusick } 1416*53901Smckusick return (0); 1417*53901Smckusick } 1418*53901Smckusick 1419*53901Smckusick sdcmd(dev, usc) 1420*53901Smckusick dev_t dev; 1421*53901Smckusick struct scsi *usc; 1422*53901Smckusick { 1423*53901Smckusick register struct buf *bp; 1424*53901Smckusick register struct scsi *ksc; 1425*53901Smckusick register u_char *point; 1426*53901Smckusick register int unit; 1427*53901Smckusick int error; 1428*53901Smckusick int s; 1429*53901Smckusick int cnt; 1430*53901Smckusick 1431*53901Smckusick if (usc == 0) 1432*53901Smckusick return (ENXIO); 1433*53901Smckusick 1434*53901Smckusick error = 0; 1435*53901Smckusick unit = dev2unit(dev); 1436*53901Smckusick bp = &csdbuf[unit]; 1437*53901Smckusick 1438*53901Smckusick /* 1439*53901Smckusick * LOCK csdbuf 1440*53901Smckusick */ 1441*53901Smckusick s = splclock(); 1442*53901Smckusick while (bp->b_flags & B_BUSY) { 1443*53901Smckusick bp->b_flags |= B_WANTED; 1444*53901Smckusick sleep((caddr_t)bp, PRIBIO); 1445*53901Smckusick } 1446*53901Smckusick bzero((caddr_t)bp, sizeof(struct buf)); 1447*53901Smckusick bp->b_flags = B_BUSY|B_READ; 1448*53901Smckusick splx(s); 1449*53901Smckusick 1450*53901Smckusick ksc = &kernscsi[unit]; 1451*53901Smckusick bcopy((caddr_t)usc, (caddr_t)ksc, sizeof(struct scsi)); 1452*53901Smckusick /* 1453*53901Smckusick * setup command buffer 1454*53901Smckusick */ 1455*53901Smckusick bp->b_dev = dev; 1456*53901Smckusick bp->b_proc = curproc; 1457*53901Smckusick cnt = ksc->sc_ctrnscnt; 1458*53901Smckusick bp->b_bcount = cnt; 1459*53901Smckusick 1460*53901Smckusick point = ksc->sc_cpoint; 1461*53901Smckusick bp->b_un.b_addr = (caddr_t)point; 1462*53901Smckusick if (cnt > 0) { 1463*53901Smckusick if (point == NULL) { 1464*53901Smckusick ksc->sc_cpoint = point = get_scsi(unit)->sc_param; 1465*53901Smckusick if (cnt > 20) { 1466*53901Smckusick error = EFAULT; 1467*53901Smckusick goto done; 1468*53901Smckusick } 1469*53901Smckusick } 1470*53901Smckusick if (point < (u_char *)KERNBASE) { 1471*53901Smckusick if (useracc(point, cnt, B_WRITE) == NULL) { 1472*53901Smckusick error = EFAULT; 1473*53901Smckusick goto done; 1474*53901Smckusick } 1475*53901Smckusick curproc->p_flag |= SPHYSIO; 1476*53901Smckusick vslock(point, cnt); 1477*53901Smckusick bp->b_flags |= B_PHYS; 1478*53901Smckusick } 1479*53901Smckusick #ifndef mips 1480*53901Smckusick else { 1481*53901Smckusick if (kernacc(point, cnt, B_WRITE) == NULL) { 1482*53901Smckusick error = EFAULT; 1483*53901Smckusick goto done; 1484*53901Smckusick } 1485*53901Smckusick } 1486*53901Smckusick #endif 1487*53901Smckusick ksc->sc_tstatus = TS_MAPPED_PIO; /* XXX */ 1488*53901Smckusick } 1489*53901Smckusick 1490*53901Smckusick /* 1491*53901Smckusick * call strategy entry, and wait command done. 1492*53901Smckusick */ 1493*53901Smckusick sdstrategy(bp); 1494*53901Smckusick iowait(bp); 1495*53901Smckusick 1496*53901Smckusick if ((cnt > 0) && (point < (u_char *)KERNBASE)) { 1497*53901Smckusick vsunlock(point, cnt, B_READ); 1498*53901Smckusick curproc->p_flag &= ~SPHYSIO; 1499*53901Smckusick } 1500*53901Smckusick if ((bp->b_flags & B_ERROR) == 0) 1501*53901Smckusick error = 0; 1502*53901Smckusick else { 1503*53901Smckusick if (bp->b_error) 1504*53901Smckusick error = bp->b_error; 1505*53901Smckusick else 1506*53901Smckusick error = EIO; 1507*53901Smckusick } 1508*53901Smckusick bcopy((caddr_t)ksc, (caddr_t)usc, sizeof(struct scsi)); 1509*53901Smckusick 1510*53901Smckusick done: 1511*53901Smckusick /* 1512*53901Smckusick * UNLOCK csdbuf 1513*53901Smckusick */ 1514*53901Smckusick s = splclock(); 1515*53901Smckusick if (bp->b_flags & B_WANTED) 1516*53901Smckusick wakeup((caddr_t)bp); 1517*53901Smckusick bp->b_flags = 0; 1518*53901Smckusick splx(s); 1519*53901Smckusick return (error); 1520*53901Smckusick } 1521*53901Smckusick 1522*53901Smckusick /* 1523*53901Smckusick * read partition information from sector zero. 1524*53901Smckusick */ 1525*53901Smckusick sdrpartinfo(ii) 1526*53901Smckusick register struct iop/**/_device *ii; 1527*53901Smckusick { 1528*53901Smckusick register struct disklabel *dlp; 1529*53901Smckusick register struct sdst *hsp; 1530*53901Smckusick register struct sdst *st; 1531*53901Smckusick register int unit; 1532*53901Smckusick register int i; 1533*53901Smckusick struct firstsector *fsp; 1534*53901Smckusick struct sdc_softc *sdc; 1535*53901Smckusick struct sdd_softc *sdd; 1536*53901Smckusick struct sddevinfo *sdi; 1537*53901Smckusick #ifdef DISKINFO 1538*53901Smckusick struct diskinfo *dip; 1539*53901Smckusick #endif 1540*53901Smckusick struct scsi uscsi; 1541*53901Smckusick int s; 1542*53901Smckusick 1543*53901Smckusick sdi = &sddevinfo[ii->ii_type]; 1544*53901Smckusick unit = ii->ii_unit; 1545*53901Smckusick 1546*53901Smckusick sdd = &sdd_softc[unit]; 1547*53901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 1548*53901Smckusick 1549*53901Smckusick if ((sdd->sdd_flags & (SDDF_NONFMT|SDDF_FMTDONE)) == 0) { 1550*53901Smckusick register struct sc_rcap *scr = (struct sc_rcap *)sdtmp; 1551*53901Smckusick 1552*53901Smckusick sdd->sdd_flags |= SDDF_FMTDONE; 1553*53901Smckusick 1554*53901Smckusick bzero((caddr_t)sdtmp, 8); 1555*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 1556*53901Smckusick uscsi.sc_cpoint = (u_char *)scr; 1557*53901Smckusick uscsi.sc_ctrnscnt = 8; 1558*53901Smckusick uscsi.sc_opcode = SCOP_RCAP; 1559*53901Smckusick (void) sdcmd(unit << 3, &uscsi); 1560*53901Smckusick 1561*53901Smckusick sdd->sdd_nsect = scr->scr_nblock + 1; 1562*53901Smckusick sdd->sdd_sectsize = scr->scr_blocklen; 1563*53901Smckusick if (sdd->sdd_sectsize == 0) 1564*53901Smckusick sdd->sdd_sectsize = SDBSIZE1K; 1565*53901Smckusick } 1566*53901Smckusick 1567*53901Smckusick bzero(sdtmp, DEV_BSIZE); 1568*53901Smckusick 1569*53901Smckusick if ((sdd->sdd_flags & SDDF_NONFMT) == 0) { 1570*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 1571*53901Smckusick uscsi.sc_cpoint = sdtmp; 1572*53901Smckusick uscsi.sc_ctrnscnt = DEV_BSIZE; 1573*53901Smckusick uscsi.sc_opcode = SCOP_READ; 1574*53901Smckusick uscsi.sc_lad = 0; 1575*53901Smckusick uscsi.sc_count = 1; 1576*53901Smckusick 1577*53901Smckusick (void) sdcmd(unit << 3, &uscsi); 1578*53901Smckusick sdd->sdd_flags &= ~SDDF_SKIPCHECK; 1579*53901Smckusick } 1580*53901Smckusick 1581*53901Smckusick fsp = (struct firstsector *)sdtmp; 1582*53901Smckusick dlp = (struct disklabel *)(sdtmp + LABELOFFSET); 1583*53901Smckusick #ifdef DISKINFO 1584*53901Smckusick dip = &fsp->diskinfo; 1585*53901Smckusick #endif 1586*53901Smckusick 1587*53901Smckusick s = splclock(); 1588*53901Smckusick hsp = &sdstdrv[unit]; 1589*53901Smckusick bzero((caddr_t)hsp, sizeof (struct sdst)); 1590*53901Smckusick bzero(&sdlabel[unit], sizeof (struct disklabel)); 1591*53901Smckusick 1592*53901Smckusick if ((dlp->d_magic == DISKMAGIC) 1593*53901Smckusick && ((ii->ii_flags & SD_F_IGNLABEL) == 0)) { 1594*53901Smckusick sdlabel[unit] = *dlp; 1595*53901Smckusick disklabel2sdst(unit, dlp, hsp); 1596*53901Smckusick #ifdef DISKINFO 1597*53901Smckusick } else if ((dip->di_magic == DISKINFO_MAGIC) 1598*53901Smckusick && ((ii->ii_flags & SD_F_IGNLABEL) == 0)) { 1599*53901Smckusick diskinfo2sdst(unit, dip, hsp); 1600*53901Smckusick diskinfo2disklabel(unit, dip, &sdlabel[unit]); 1601*53901Smckusick #endif 1602*53901Smckusick } else { 1603*53901Smckusick if ((ii->ii_type == UNKNOWN_DISK) 1604*53901Smckusick || (sdi->sdstp->sizes == calc_disk_sizes)) { 1605*53901Smckusick /* 1606*53901Smckusick * If device is UNKNOWN PARTITION SIZE, 1607*53901Smckusick * calculate default partition from capacity. 1608*53901Smckusick */ 1609*53901Smckusick st = sdi->sdstp; 1610*53901Smckusick hsp->nsect = st->nsect; /* # sectors/track */ 1611*53901Smckusick hsp->ntrak = st->ntrak; /* # tracks/cylinder */ 1612*53901Smckusick hsp->nspc = st->nspc; /* # sectors/cylinder */ 1613*53901Smckusick hsp->ncyl = st->ncyl; /* # cylinders */ 1614*53901Smckusick hsp->rps = st->rps; /* # revolutions/sec */ 1615*53901Smckusick hsp->sizes = sdsizedrv[unit]; /* partition table */ 1616*53901Smckusick 1617*53901Smckusick sd_calcpart(ii, hsp->sizes, 1618*53901Smckusick sdd->sdd_nsect, sdd->sdd_sectsize); 1619*53901Smckusick sdst2disklabel(unit, hsp, &sdlabel[unit]); 1620*53901Smckusick } else { 1621*53901Smckusick /* 1622*53901Smckusick * If device is support disk, 1623*53901Smckusick * copy default partition from size table. 1624*53901Smckusick */ 1625*53901Smckusick st = sdi->sdstp; 1626*53901Smckusick 1627*53901Smckusick hsp->nsect = st->nsect; /* # sectors/track */ 1628*53901Smckusick hsp->ntrak = st->ntrak; /* # tracks/cylinder */ 1629*53901Smckusick hsp->nspc = st->nspc; /* # sectors/cylinder */ 1630*53901Smckusick hsp->ncyl = st->ncyl; /* # cylinders */ 1631*53901Smckusick hsp->rps = st->rps; /* # revolutions / second */ 1632*53901Smckusick hsp->sizes = sdsizedrv[unit]; /* partition table */ 1633*53901Smckusick 1634*53901Smckusick for (i = 0; i < PNUM; i++) { 1635*53901Smckusick hsp->sizes[i].sd_nblocks = st->sizes[i].sd_nblocks; 1636*53901Smckusick hsp->sizes[i].sd_blkoff = st->sizes[i].sd_blkoff; 1637*53901Smckusick } 1638*53901Smckusick sdst2disklabel(unit, hsp, &sdlabel[unit]); 1639*53901Smckusick } 1640*53901Smckusick } 1641*53901Smckusick 1642*53901Smckusick /* BEGIN XXX*/ 1643*53901Smckusick if (hsp->rps == 0) { 1644*53901Smckusick /* 1645*53901Smckusick * If device is support disk, 1646*53901Smckusick * copy default partition from size table. 1647*53901Smckusick */ 1648*53901Smckusick st = sdi->sdstp; 1649*53901Smckusick 1650*53901Smckusick hsp->nsect = st->nsect; /* # sectors/track */ 1651*53901Smckusick hsp->ntrak = st->ntrak; /* # tracks/cylinder */ 1652*53901Smckusick hsp->nspc = st->nspc; /* # sectors/cylinder */ 1653*53901Smckusick hsp->ncyl = st->ncyl; /* # cylinders */ 1654*53901Smckusick hsp->rps = st->rps; /* # revolutions / second */ 1655*53901Smckusick sdst2disklabel(unit, hsp, &sdlabel[unit]); 1656*53901Smckusick } 1657*53901Smckusick /* END XXX*/ 1658*53901Smckusick (void)splx(s); 1659*53901Smckusick } 1660*53901Smckusick 1661*53901Smckusick static char Warn_Part[] = "sd%d: PARTITION TABLE CHANGED\n"; 1662*53901Smckusick static char Pr_Part_Fmt[] = "sd%d%c: nblk=%d, off=%d\n"; 1663*53901Smckusick 1664*53901Smckusick #define stsz(N) st->sizes[(N)].sd_nblocks 1665*53901Smckusick #define stof(N) st->sizes[(N)].sd_blkoff 1666*53901Smckusick #define dlsz(N) dlp->d_partitions[(N)].p_size 1667*53901Smckusick #define dlof(N) dlp->d_partitions[(N)].p_offset 1668*53901Smckusick #define disz(N) dip->di_part[(N)].dp_nblocks 1669*53901Smckusick #define diof(N) dip->di_part[(N)].dp_blkoff 1670*53901Smckusick 1671*53901Smckusick #ifndef BBSIZE 1672*53901Smckusick #define BBSIZE 8192 1673*53901Smckusick #endif 1674*53901Smckusick 1675*53901Smckusick static 1676*53901Smckusick check_sdst(unit, st) 1677*53901Smckusick int unit; 1678*53901Smckusick struct sdst *st; 1679*53901Smckusick { 1680*53901Smckusick if (st->nsect == 0) { 1681*53901Smckusick st->nsect = 1; 1682*53901Smckusick printf("sd%d: nsect SHOULD BE != 0, 1 assumed\n", unit); 1683*53901Smckusick } 1684*53901Smckusick 1685*53901Smckusick if (st->rps == 0) { 1686*53901Smckusick st->rps = 60; 1687*53901Smckusick printf("sd%d: rps SHOULD BE != 0, 60 assumed\n", unit); 1688*53901Smckusick } 1689*53901Smckusick } 1690*53901Smckusick 1691*53901Smckusick static 1692*53901Smckusick disklabel2sdst(unit, dlp, st) 1693*53901Smckusick int unit; 1694*53901Smckusick register struct disklabel *dlp; 1695*53901Smckusick register struct sdst *st; 1696*53901Smckusick { 1697*53901Smckusick register int i; 1698*53901Smckusick int msg_header_printed; 1699*53901Smckusick 1700*53901Smckusick msg_header_printed = 0; 1701*53901Smckusick 1702*53901Smckusick st->nsect = dlp->d_nsectors; /* # sectors/track */ 1703*53901Smckusick st->ntrak = dlp->d_ntracks; /* # tracks/cylinder */ 1704*53901Smckusick st->nspc = dlp->d_secpercyl; /* # sectors/cylinder */ 1705*53901Smckusick st->ncyl = dlp->d_ncylinders; /* # cylinders */ 1706*53901Smckusick st->rps = dlp->d_rpm / 60; /* # revolutions / second */ 1707*53901Smckusick st->sizes = sdsizedrv[unit]; /* partition table */ 1708*53901Smckusick 1709*53901Smckusick check_sdst(unit, st); 1710*53901Smckusick 1711*53901Smckusick for (i = 0; i < PNUM; i++) { 1712*53901Smckusick if (msg_header_printed == 0) { 1713*53901Smckusick if (((stsz(i) != 0) || (stof(i) != 0)) 1714*53901Smckusick && ((stsz(i) != dlsz(i)) || (stof(i) != dlof(i)))) { 1715*53901Smckusick msg_header_printed = 1; 1716*53901Smckusick } 1717*53901Smckusick } 1718*53901Smckusick } 1719*53901Smckusick 1720*53901Smckusick for (i = 0; i < PNUM; i++) { 1721*53901Smckusick stsz(i) = dlsz(i); 1722*53901Smckusick stof(i) = dlof(i); 1723*53901Smckusick } 1724*53901Smckusick 1725*53901Smckusick if (msg_header_printed) { 1726*53901Smckusick printf(Warn_Part, unit); 1727*53901Smckusick for (i = 0; i < PNUM; i++) 1728*53901Smckusick printf(Pr_Part_Fmt, unit, pname[i], stsz(i), stof(i)); 1729*53901Smckusick } 1730*53901Smckusick } 1731*53901Smckusick 1732*53901Smckusick #ifdef DISKINFO 1733*53901Smckusick static 1734*53901Smckusick diskinfo2sdst(unit, dip, st) 1735*53901Smckusick int unit; 1736*53901Smckusick register struct diskinfo *dip; 1737*53901Smckusick register struct sdst *st; 1738*53901Smckusick { 1739*53901Smckusick register int i; 1740*53901Smckusick int msg_header_printed; 1741*53901Smckusick 1742*53901Smckusick msg_header_printed = 0; 1743*53901Smckusick 1744*53901Smckusick st->nsect = dip->di_dkst.dks_nsect; /* # sectors/track */ 1745*53901Smckusick st->ntrak = dip->di_dkst.dks_ntrak; /* # tracks/cylinder */ 1746*53901Smckusick st->nspc = dip->di_dkst.dks_nsect * dip->di_dkst.dks_ntrak; 1747*53901Smckusick /* # sectors/cylinder */ 1748*53901Smckusick st->ncyl = dip->di_dkst.dks_ncyl; /* # cylinders */ 1749*53901Smckusick st->rps = dip->di_dkst.dks_rps; /* # revolutions / second */ 1750*53901Smckusick st->sizes = sdsizedrv[unit]; /* partition table */ 1751*53901Smckusick 1752*53901Smckusick check_sdst(unit, st); 1753*53901Smckusick 1754*53901Smckusick for (i = 0; i < PNUM; i++) { 1755*53901Smckusick if (msg_header_printed == 0) { 1756*53901Smckusick if (((stsz(i) != 0) || (stof(i) != 0)) 1757*53901Smckusick && ((stsz(i) != disz(i)) || (stof(i) != diof(i)))) { 1758*53901Smckusick msg_header_printed = 1; 1759*53901Smckusick } 1760*53901Smckusick } 1761*53901Smckusick } 1762*53901Smckusick 1763*53901Smckusick for (i = 0; i < PNUM; i++) { 1764*53901Smckusick stsz(i) = disz(i); 1765*53901Smckusick stof(i) = diof(i); 1766*53901Smckusick } 1767*53901Smckusick 1768*53901Smckusick if (msg_header_printed) { 1769*53901Smckusick printf(Warn_Part, unit); 1770*53901Smckusick for (i = 0; i < PNUM; i++) 1771*53901Smckusick printf(Pr_Part_Fmt, unit, pname[i], stsz(i), stof(i)); 1772*53901Smckusick } 1773*53901Smckusick } 1774*53901Smckusick 1775*53901Smckusick static 1776*53901Smckusick diskinfo2disklabel(unit, dip, dlp) 1777*53901Smckusick int unit; 1778*53901Smckusick register struct diskinfo *dip; 1779*53901Smckusick register struct disklabel *dlp; 1780*53901Smckusick { 1781*53901Smckusick register int i; 1782*53901Smckusick 1783*53901Smckusick dlp->d_type = DTYPE_SCSI; /* drive type */ 1784*53901Smckusick dlp->d_secsize = sdd_softc[unit].sdd_sectsize; /* # of bytes per sector */ 1785*53901Smckusick dlp->d_nsectors = dip->di_dkst.dks_nsect; /* # sectors/track */ 1786*53901Smckusick dlp->d_ntracks = dip->di_dkst.dks_ntrak; /* # tracks/cylinder */ 1787*53901Smckusick dlp->d_ncylinders = dip->di_dkst.dks_ncyl; /* # cylinders */ 1788*53901Smckusick dlp->d_secpercyl = dip->di_dkst.dks_nsect * dip->di_dkst.dks_ntrak; 1789*53901Smckusick /* # sectors/cylinder */ 1790*53901Smckusick dlp->d_rpm = dip->di_dkst.dks_rps * 60; /* # revolutions / second */ 1791*53901Smckusick dlp->d_bbsize = BBSIZE; /*XXX*/ /* size of boot area at sn0, bytes */ 1792*53901Smckusick dlp->d_sbsize = SBSIZE; /*XXX*/ /* max size of fs superblock, bytes */ 1793*53901Smckusick 1794*53901Smckusick for (i = 0; i < PNUM; i++) { 1795*53901Smckusick dlsz(i) = disz(i); 1796*53901Smckusick dlof(i) = diof(i); 1797*53901Smckusick } 1798*53901Smckusick } 1799*53901Smckusick #endif /* DISKINFO */ 1800*53901Smckusick 1801*53901Smckusick /* #ifdef DISKINFO KU:XXX */ 1802*53901Smckusick static 1803*53901Smckusick disklabel2diskinfo(unit, dlp, dip) 1804*53901Smckusick int unit; 1805*53901Smckusick register struct disklabel *dlp; 1806*53901Smckusick register struct diskinfo *dip; 1807*53901Smckusick { 1808*53901Smckusick register int i; 1809*53901Smckusick 1810*53901Smckusick dip->di_magic = DISKINFO_MAGIC; 1811*53901Smckusick dip->di_dkst.dks_nsect = dlp->d_nsectors; /* # sectors/track */ 1812*53901Smckusick dip->di_dkst.dks_ntrak = dlp->d_ntracks; /* # tracks/cylinder */ 1813*53901Smckusick dip->di_dkst.dks_ncyl = dlp->d_ncylinders; /* # cylinders */ 1814*53901Smckusick dip->di_dkst.dks_rps = dlp->d_rpm / 60; /* # revolutions/second */ 1815*53901Smckusick 1816*53901Smckusick for (i = 0; i < PNUM; i++) { 1817*53901Smckusick disz(i) = dlsz(i); 1818*53901Smckusick diof(i) = dlof(i); 1819*53901Smckusick } 1820*53901Smckusick } 1821*53901Smckusick /* #endif /* DISKINFO */ 1822*53901Smckusick 1823*53901Smckusick static 1824*53901Smckusick sdst2disklabel(unit, st, dlp) 1825*53901Smckusick int unit; /*XXX*/ 1826*53901Smckusick register struct sdst *st; 1827*53901Smckusick register struct disklabel *dlp; 1828*53901Smckusick { 1829*53901Smckusick register int i; 1830*53901Smckusick 1831*53901Smckusick dlp->d_type = DTYPE_SCSI; /* drive type */ 1832*53901Smckusick dlp->d_secsize = sdd_softc[unit].sdd_sectsize; /* # of bytes per sector */ 1833*53901Smckusick dlp->d_nsectors = st->nsect; /* # sectors/track */ 1834*53901Smckusick dlp->d_ntracks = st->ntrak; /* # tracks/cylinder */ 1835*53901Smckusick dlp->d_ncylinders = st->ncyl; /* # cylinders */ 1836*53901Smckusick dlp->d_secpercyl = st->nspc; /* # sectors/cylinder */ 1837*53901Smckusick dlp->d_rpm = st->rps * 60; /* # revolutions / minute */ 1838*53901Smckusick dlp->d_bbsize = BBSIZE; /*XXX*/ /* size of boot area at sn0, bytes */ 1839*53901Smckusick dlp->d_sbsize = SBSIZE; /*XXX*/ /* max size of fs superblock, bytes */ 1840*53901Smckusick 1841*53901Smckusick for (i = 0; i < PNUM; i++) { 1842*53901Smckusick dlsz(i) = stsz(i); 1843*53901Smckusick dlof(i) = stof(i); 1844*53901Smckusick } 1845*53901Smckusick } 1846*53901Smckusick 1847*53901Smckusick #undef stsz 1848*53901Smckusick #undef stof 1849*53901Smckusick #undef dlsz 1850*53901Smckusick #undef dlof 1851*53901Smckusick #undef disz 1852*53901Smckusick #undef diof 1853*53901Smckusick 1854*53901Smckusick sd_calcpart(ii, disk_sizes, nsect, sectsize) 1855*53901Smckusick register struct iop/**/_device *ii; 1856*53901Smckusick register struct size disk_sizes[]; 1857*53901Smckusick int nsect; 1858*53901Smckusick int sectsize; 1859*53901Smckusick { 1860*53901Smckusick register struct defpart *dp; 1861*53901Smckusick register int size_mb; 1862*53901Smckusick register int i; 1863*53901Smckusick int psize; 1864*53901Smckusick 1865*53901Smckusick size_mb = nsect * sectsize / (1024 * 1024); 1866*53901Smckusick 1867*53901Smckusick for (dp = defpart_std; dp->range_max; dp++) 1868*53901Smckusick if ((dp->range_min <= size_mb) && (size_mb < dp->range_max)) 1869*53901Smckusick break; 1870*53901Smckusick 1871*53901Smckusick /* PASS1 */ 1872*53901Smckusick for (i = 0; i < PNUM; i++) { 1873*53901Smckusick psize = dp->partsize[i]; 1874*53901Smckusick 1875*53901Smckusick switch (psize) { 1876*53901Smckusick 1877*53901Smckusick case PART_UNUSED: 1878*53901Smckusick disk_sizes[i].sd_nblocks = 0; 1879*53901Smckusick break; 1880*53901Smckusick 1881*53901Smckusick case PART_SPEC: 1882*53901Smckusick disk_sizes[i].sd_nblocks = nsect * sectsize / DEV_BSIZE; 1883*53901Smckusick break; 1884*53901Smckusick 1885*53901Smckusick case PART_CALCF: 1886*53901Smckusick case PART_CALCG: 1887*53901Smckusick break; 1888*53901Smckusick 1889*53901Smckusick default: 1890*53901Smckusick disk_sizes[i].sd_nblocks = psize; 1891*53901Smckusick break; 1892*53901Smckusick } 1893*53901Smckusick } 1894*53901Smckusick 1895*53901Smckusick /* PASS2 */ 1896*53901Smckusick for (i = 0; i < PNUM; i++) { 1897*53901Smckusick psize = dp->partsize[i]; 1898*53901Smckusick 1899*53901Smckusick switch (psize) { 1900*53901Smckusick 1901*53901Smckusick case PART_UNUSED: 1902*53901Smckusick case PART_SPEC: 1903*53901Smckusick break; 1904*53901Smckusick 1905*53901Smckusick case PART_CALCF: 1906*53901Smckusick disk_sizes[i].sd_nblocks = 1907*53901Smckusick disk_sizes[PART_C].sd_nblocks - 1908*53901Smckusick (disk_sizes[PART_A].sd_nblocks + 1909*53901Smckusick disk_sizes[PART_B].sd_nblocks + 1910*53901Smckusick disk_sizes[PART_D].sd_nblocks + 1911*53901Smckusick disk_sizes[PART_E].sd_nblocks + 1912*53901Smckusick disk_sizes[PART_H].sd_nblocks); 1913*53901Smckusick break; 1914*53901Smckusick 1915*53901Smckusick case PART_CALCG: 1916*53901Smckusick disk_sizes[i].sd_nblocks = 1917*53901Smckusick disk_sizes[PART_C].sd_nblocks - 1918*53901Smckusick (disk_sizes[PART_A].sd_nblocks + 1919*53901Smckusick disk_sizes[PART_B].sd_nblocks + 1920*53901Smckusick disk_sizes[PART_H].sd_nblocks); 1921*53901Smckusick break; 1922*53901Smckusick 1923*53901Smckusick default: 1924*53901Smckusick break; 1925*53901Smckusick } 1926*53901Smckusick } 1927*53901Smckusick 1928*53901Smckusick /* OFFSET */ 1929*53901Smckusick disk_sizes[PART_A].sd_blkoff = 0; 1930*53901Smckusick disk_sizes[PART_B].sd_blkoff = disk_sizes[PART_A].sd_nblocks; 1931*53901Smckusick disk_sizes[PART_C].sd_blkoff = 0; 1932*53901Smckusick disk_sizes[PART_D].sd_blkoff = disk_sizes[PART_A].sd_nblocks 1933*53901Smckusick + disk_sizes[PART_B].sd_nblocks 1934*53901Smckusick + disk_sizes[PART_H].sd_nblocks; 1935*53901Smckusick disk_sizes[PART_E].sd_blkoff = disk_sizes[PART_D].sd_blkoff 1936*53901Smckusick + disk_sizes[PART_D].sd_nblocks; 1937*53901Smckusick disk_sizes[PART_F].sd_blkoff = disk_sizes[PART_E].sd_blkoff 1938*53901Smckusick + disk_sizes[PART_E].sd_nblocks; 1939*53901Smckusick disk_sizes[PART_G].sd_blkoff = disk_sizes[PART_D].sd_blkoff; 1940*53901Smckusick 1941*53901Smckusick if (disk_sizes[PART_H].sd_nblocks == 0) 1942*53901Smckusick disk_sizes[PART_H].sd_blkoff = 0; 1943*53901Smckusick else { 1944*53901Smckusick disk_sizes[PART_H].sd_blkoff = 1945*53901Smckusick disk_sizes[PART_A].sd_nblocks + 1946*53901Smckusick disk_sizes[PART_B].sd_nblocks; 1947*53901Smckusick } 1948*53901Smckusick 1949*53901Smckusick for (i = 0; i < PNUM; i++) 1950*53901Smckusick if (disk_sizes[i].sd_nblocks == 0) 1951*53901Smckusick disk_sizes[i].sd_blkoff = 0; 1952*53901Smckusick } 1953*53901Smckusick 1954*53901Smckusick int sd_str_pr = 0; 1955*53901Smckusick 1956*53901Smckusick sdstrategy(bp) 1957*53901Smckusick register struct buf *bp; 1958*53901Smckusick { 1959*53901Smckusick register struct iop/**/_device *ii; 1960*53901Smckusick register struct sdst *st; 1961*53901Smckusick register struct buf *dp; 1962*53901Smckusick register int unit; 1963*53901Smckusick register int ssize; 1964*53901Smckusick struct sdd_softc *sdd; 1965*53901Smckusick struct sdc_softc *sdc; 1966*53901Smckusick long bn; 1967*53901Smckusick int xunit; 1968*53901Smckusick int s; 1969*53901Smckusick 1970*53901Smckusick xunit = dev2part(bp->b_dev); 1971*53901Smckusick unit = dev2unit(bp->b_dev); 1972*53901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) 1973*53901Smckusick goto bad; 1974*53901Smckusick 1975*53901Smckusick if (bp != &csdbuf[unit]) { 1976*53901Smckusick /* 1977*53901Smckusick * READ / WRITE command 1978*53901Smckusick */ 1979*53901Smckusick sdd = &sdd_softc[unit]; 1980*53901Smckusick if (sdd->sdd_flags & SDDF_NONFMT) 1981*53901Smckusick goto bad; 1982*53901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 1983*53901Smckusick ssize = sdd->sdd_sectsize; 1984*53901Smckusick if ((ssize != DEV_BSIZE) 1985*53901Smckusick && ((((dkblock(bp) * DEV_BSIZE) % ssize) != 0) 1986*53901Smckusick || (((bp->b_flags & B_READ) == 0) && 1987*53901Smckusick ((bp->b_bcount % ssize) != 0)))) { 1988*53901Smckusick goto bad; 1989*53901Smckusick } 1990*53901Smckusick 1991*53901Smckusick st = &sdstdrv[unit]; 1992*53901Smckusick bn = dkblock(bp); 1993*53901Smckusick bp->b_resid = 0; 1994*53901Smckusick if ((bn < 0) || (bn >= st->sizes[xunit].sd_nblocks)) 1995*53901Smckusick goto bad2; 1996*53901Smckusick if (sd_access_check(bp) < 0) 1997*53901Smckusick goto bad2; 1998*53901Smckusick 1999*53901Smckusick #ifdef notdef /* KU: XXX */ 2000*53901Smckusick bp->b_cylin = (bn + st->sizes[xunit].sd_blkoff) / st->nspc; 2001*53901Smckusick } else { 2002*53901Smckusick bp->b_cylin = 0; 2003*53901Smckusick #endif 2004*53901Smckusick } 2005*53901Smckusick 2006*53901Smckusick s = splsc(); 2007*53901Smckusick dp = &sdutab[ii->ii_unit]; 2008*53901Smckusick disksort(dp, bp); 2009*53901Smckusick if (dp->b_active == 0) { 2010*53901Smckusick sdustart(ii); 2011*53901Smckusick bp = &ii->ii_mi->im_tab; 2012*53901Smckusick if (bp->b_actf && bp->b_active == 0) 2013*53901Smckusick sdstart(ii->ii_mi); 2014*53901Smckusick } 2015*53901Smckusick splx(s); 2016*53901Smckusick return; 2017*53901Smckusick 2018*53901Smckusick bad: 2019*53901Smckusick bp->b_flags |= B_ERROR; 2020*53901Smckusick goto done; 2021*53901Smckusick bad2: 2022*53901Smckusick bp->b_resid = bp->b_bcount; 2023*53901Smckusick done: 2024*53901Smckusick iodone(bp); 2025*53901Smckusick } 2026*53901Smckusick 2027*53901Smckusick /* 2028*53901Smckusick * Unit start routine. 2029*53901Smckusick */ 2030*53901Smckusick sdustart(ii) 2031*53901Smckusick register struct iop/**/_device *ii; 2032*53901Smckusick { 2033*53901Smckusick register struct iop/**/_ctlr *im; 2034*53901Smckusick register struct buf *dp; 2035*53901Smckusick 2036*53901Smckusick if (ii == NULL) 2037*53901Smckusick return; 2038*53901Smckusick im = ii->ii_mi; 2039*53901Smckusick dk_busy &= ~(1 << ii->ii_dk); 2040*53901Smckusick dp = &sdutab[ii->ii_unit]; 2041*53901Smckusick if (dp->b_actf == NULL) 2042*53901Smckusick return; 2043*53901Smckusick /* 2044*53901Smckusick * If the controller is active, just remember 2045*53901Smckusick * that this device would like to be positioned ... 2046*53901Smckusick * if we tried to position now we would confuse the SD. 2047*53901Smckusick */ 2048*53901Smckusick if (im->im_tab.b_active) { 2049*53901Smckusick sdc_softc[im->im_ctlr].sdc_softas |= (1 << ii->ii_slave); 2050*53901Smckusick return; 2051*53901Smckusick } 2052*53901Smckusick /* 2053*53901Smckusick * If we have already positioned this drive, 2054*53901Smckusick * then just put it on the ready queue. 2055*53901Smckusick */ 2056*53901Smckusick if (dp->b_active == 0) 2057*53901Smckusick dp->b_active = 1; 2058*53901Smckusick /* 2059*53901Smckusick * Device is ready to go 2060*53901Smckusick * put it on the ready queue for the controller 2061*53901Smckusick * (unless its already there.) 2062*53901Smckusick */ 2063*53901Smckusick if (dp->b_active != 2) { 2064*53901Smckusick dp->b_forw = NULL; 2065*53901Smckusick if (im->im_tab.b_actf == NULL) 2066*53901Smckusick im->im_tab.b_actf = dp; 2067*53901Smckusick else 2068*53901Smckusick im->im_tab.b_actl->b_forw = dp; 2069*53901Smckusick im->im_tab.b_actl = dp; 2070*53901Smckusick dp->b_active = 2; 2071*53901Smckusick } 2072*53901Smckusick } 2073*53901Smckusick 2074*53901Smckusick /* 2075*53901Smckusick * Start up a transfer on a drive. 2076*53901Smckusick */ 2077*53901Smckusick sdstart(im) 2078*53901Smckusick register struct iop/**/_ctlr *im; 2079*53901Smckusick { 2080*53901Smckusick register struct buf *bp; 2081*53901Smckusick register struct buf *dp; 2082*53901Smckusick register struct sdc_softc *sdc; 2083*53901Smckusick 2084*53901Smckusick loop: 2085*53901Smckusick /* 2086*53901Smckusick * Pull a request off the controller queue. 2087*53901Smckusick */ 2088*53901Smckusick if ((dp = im->im_tab.b_actf) == NULL) 2089*53901Smckusick return; 2090*53901Smckusick if ((bp = dp->b_actf) == NULL) { 2091*53901Smckusick im->im_tab.b_actf = dp->b_forw; 2092*53901Smckusick goto loop; 2093*53901Smckusick } 2094*53901Smckusick /* 2095*53901Smckusick * Mark controller busy, and 2096*53901Smckusick * determine destination of this request. 2097*53901Smckusick */ 2098*53901Smckusick im->im_tab.b_active++; 2099*53901Smckusick 2100*53901Smckusick sdexec(bp); 2101*53901Smckusick } 2102*53901Smckusick 2103*53901Smckusick void 2104*53901Smckusick sdexec(bp) 2105*53901Smckusick register struct buf *bp; 2106*53901Smckusick { 2107*53901Smckusick register struct iop/**/_device *ii; 2108*53901Smckusick register struct buf_stat *bs; 2109*53901Smckusick register struct scsi *sc; 2110*53901Smckusick register int ssize; 2111*53901Smckusick register int unit; 2112*53901Smckusick register int intr; 2113*53901Smckusick register int bn; 2114*53901Smckusick struct sdc_softc *sdc; 2115*53901Smckusick struct sdd_softc *sdd; 2116*53901Smckusick struct sdst *st; 2117*53901Smckusick int sz; 2118*53901Smckusick int over; 2119*53901Smckusick struct sc_map *map; 2120*53901Smckusick 2121*53901Smckusick unit = dev2unit(bp->b_dev); 2122*53901Smckusick ii= sddinfo[unit]; 2123*53901Smckusick intr = ii->ii_intr; 2124*53901Smckusick sdd = &sdd_softc[unit]; 2125*53901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 2126*53901Smckusick 2127*53901Smckusick sc = get_scsi(intr); 2128*53901Smckusick 2129*53901Smckusick if (bp == &csdbuf[unit]) { /* do sdcmd() */ 2130*53901Smckusick bcopy((caddr_t)&kernscsi[unit], 2131*53901Smckusick (caddr_t)sc, sizeof(struct scsi)); 2132*53901Smckusick if (bp->b_un.b_addr == NULL) { 2133*53901Smckusick map = 0; 2134*53901Smckusick } else { 2135*53901Smckusick map = get_sc_map(intr); 2136*53901Smckusick sc->sc_map = (struct sc_map *)ipc_phys(map); 2137*53901Smckusick } 2138*53901Smckusick } else { /* R/W */ 2139*53901Smckusick ssize = sdd->sdd_sectsize; 2140*53901Smckusick 2141*53901Smckusick st = &sdstdrv[unit]; 2142*53901Smckusick bn = dkblock(bp); 2143*53901Smckusick if (sdd->sdd_lastblk / st->nspc != bn / st->nspc) 2144*53901Smckusick dk_seek[ii->ii_dk]++; 2145*53901Smckusick 2146*53901Smckusick st = &sdstdrv[unit]; 2147*53901Smckusick bn = dkblock(bp); 2148*53901Smckusick 2149*53901Smckusick /* 2150*53901Smckusick * Setup for the transfer, and get in the IOP queue. 2151*53901Smckusick */ 2152*53901Smckusick scinit(sc, ii->ii_slave, ssize); 2153*53901Smckusick sc->sc_ctrnscnt = bp->b_bcount - bp->b_resid; 2154*53901Smckusick map = get_sc_map(intr); 2155*53901Smckusick sc->sc_map = (struct sc_map *)ipc_phys(map); 2156*53901Smckusick 2157*53901Smckusick /* cdb */ 2158*53901Smckusick sc->sc_cdb.un_type1.t1_opcode = 2159*53901Smckusick (bp->b_flags & B_READ) ? SCOP_EREAD : 2160*53901Smckusick (ii->ii_flags & SD_F_WRTVRFY) ? SCOP_WRTVRFY : 2161*53901Smckusick SCOP_EWRITE; 2162*53901Smckusick #ifdef mips 2163*53901Smckusick { 2164*53901Smckusick int v; 2165*53901Smckusick 2166*53901Smckusick v = (bn + st->sizes[dev2part(bp->b_dev)].sd_blkoff) 2167*53901Smckusick * DEV_BSIZE / sdd->sdd_sectsize; 2168*53901Smckusick sc->sc_ladhi = v >> 16; 2169*53901Smckusick sc->sc_ladlo = v; 2170*53901Smckusick 2171*53901Smckusick v = (sc->sc_ctrnscnt + ssize - 1) / ssize; 2172*53901Smckusick sc->sc_cdb.un_type1.t1_p2 = v >> 8; 2173*53901Smckusick sc->sc_cdb.un_type1.t1_p3 = v; 2174*53901Smckusick } 2175*53901Smckusick #else 2176*53901Smckusick *(u_int *)(&sc->sc_cdb.un_type1.t1_ladhi) = 2177*53901Smckusick (bn + st->sizes[dev2part(bp->b_dev)].sd_blkoff) 2178*53901Smckusick * DEV_BSIZE / sdd->sdd_sectsize; 2179*53901Smckusick *(u_short *)(&sc->sc_cdb.un_type1.t1_p2) = 2180*53901Smckusick (sc->sc_ctrnscnt + ssize -1) / ssize; 2181*53901Smckusick #endif 2182*53901Smckusick if ((sdd->sdd_flags & SDDF_ERASEOFF) 2183*53901Smckusick && ((bp->b_flags & B_READ) == 0)) { 2184*53901Smckusick sc->sc_ctrl = 0x40; 2185*53901Smckusick } 2186*53901Smckusick } 2187*53901Smckusick 2188*53901Smckusick sdc->sdc_firmware |= SDCFW_BUSY; 2189*53901Smckusick iop/**/go(ii, map); 2190*53901Smckusick } 2191*53901Smckusick 2192*53901Smckusick /* 2193*53901Smckusick * Now all ready to go. 2194*53901Smckusick */ 2195*53901Smckusick sddgo(im) 2196*53901Smckusick register struct iop/**/_ctlr *im; 2197*53901Smckusick { 2198*53901Smckusick register int intr; 2199*53901Smckusick 2200*53901Smckusick im->im_tab.b_active = 2; 2201*53901Smckusick intr = im->im_intr; 2202*53901Smckusick 2203*53901Smckusick sc_go(intr, get_scsi(intr), SCSI_INTEN); 2204*53901Smckusick } 2205*53901Smckusick 2206*53901Smckusick /* 2207*53901Smckusick * copyin(), copyout() can't use in the interrupt routine. 2208*53901Smckusick * because user process is changed. 2209*53901Smckusick */ 2210*53901Smckusick /* 2211*53901Smckusick * Handle a disk interrupt. 2212*53901Smckusick * d: controller number 2213*53901Smckusick */ 2214*53901Smckusick sdintr(d) 2215*53901Smckusick int d; 2216*53901Smckusick { 2217*53901Smckusick register struct iop/**/_ctlr *im; 2218*53901Smckusick register struct sdc_softc *sdc; 2219*53901Smckusick register struct sdd_softc *sdd; 2220*53901Smckusick register struct scsi *sc; 2221*53901Smckusick register int intr; 2222*53901Smckusick register int unit; 2223*53901Smckusick register int slave; 2224*53901Smckusick register int as; 2225*53901Smckusick struct iop/**/_device *ii; 2226*53901Smckusick struct sddevinfo *sdi; 2227*53901Smckusick struct sc_extnd *sce; 2228*53901Smckusick struct sdst *st; 2229*53901Smckusick struct buf *bp; 2230*53901Smckusick struct buf *dp; 2231*53901Smckusick char *erp_page; 2232*53901Smckusick int code; 2233*53901Smckusick int len; 2234*53901Smckusick int tstatus; 2235*53901Smckusick int delay_start(); 2236*53901Smckusick int delay_medrmv(); 2237*53901Smckusick int wait_re_init_done(); 2238*53901Smckusick 2239*53901Smckusick im = sdminfo[d]; 2240*53901Smckusick sdc = &sdc_softc[im->im_ctlr]; 2241*53901Smckusick intr = im->im_intr; 2242*53901Smckusick as = sdc->sdc_softas; 2243*53901Smckusick 2244*53901Smckusick sdc->sdc_wticks = 0; 2245*53901Smckusick sc = get_scsi(intr); 2246*53901Smckusick /* 2247*53901Smckusick * If SDCS_IOCTL bit is set, then don't check error. 2248*53901Smckusick */ 2249*53901Smckusick if (sdc->sdc_state & SDCS_IOCTL) { 2250*53901Smckusick sdc->sdc_state &= ~SDCS_IOCTL; 2251*53901Smckusick sdd = &sdd_softc[(sdip[d][sc->sc_identify & IDT_DRMASK])->ii_unit]; 2252*53901Smckusick 2253*53901Smckusick if (sdc->sdc_state & SDCS_SCUNLOCK) { 2254*53901Smckusick int s; 2255*53901Smckusick 2256*53901Smckusick sdc->sdc_state &= ~SDCS_SCUNLOCK; 2257*53901Smckusick s = splclock(); 2258*53901Smckusick if (sdc->sdc_state & SDCS_OPEN_WAIT) { 2259*53901Smckusick sdc->sdc_state &= ~SDCS_OPEN_WAIT; 2260*53901Smckusick wakeup((caddr_t)sdc); 2261*53901Smckusick } 2262*53901Smckusick splx(s); 2263*53901Smckusick /* 2264*53901Smckusick * UNLOCK SCSI access 2265*53901Smckusick */ 2266*53901Smckusick sdc->sdc_firmware &= ~SDCFW_BUSY; 2267*53901Smckusick } 2268*53901Smckusick return; 2269*53901Smckusick } 2270*53901Smckusick 2271*53901Smckusick im->im_tab.b_active = 1; 2272*53901Smckusick /* 2273*53901Smckusick * Get device and block structures, and a pointer 2274*53901Smckusick * to the iop_device for the drive. 2275*53901Smckusick */ 2276*53901Smckusick dp = im->im_tab.b_actf; 2277*53901Smckusick bp = dp->b_actf; 2278*53901Smckusick unit = dev2unit(bp->b_dev); 2279*53901Smckusick 2280*53901Smckusick ii = sddinfo[unit]; 2281*53901Smckusick slave = ii->ii_slave; 2282*53901Smckusick st = &sdstdrv[unit]; 2283*53901Smckusick dk_busy &= ~(1 << ii->ii_dk); 2284*53901Smckusick sdd = &sdd_softc[unit]; 2285*53901Smckusick sdi = &sddevinfo[ii->ii_type]; 2286*53901Smckusick sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0]; 2287*53901Smckusick 2288*53901Smckusick /* 2289*53901Smckusick * Check error on the drive. 2290*53901Smckusick */ 2291*53901Smckusick tstatus = sc->sc_tstatus & TGSTMASK; 2292*53901Smckusick if (sc->sc_istatus != INST_EP) { 2293*53901Smckusick /* 2294*53901Smckusick * initiator status is bad. 2295*53901Smckusick * check & retry !! 2296*53901Smckusick */ 2297*53901Smckusick if ((sc->sc_istatus&(INST_EP|INST_PRE)) == (INST_EP|INST_PRE)) { 2298*53901Smckusick /* detect parity error or abnormal terminate */ 2299*53901Smckusick if ((sc->sc_istatus & INST_LB) == 0) 2300*53901Smckusick printf("sd%d: SCSI bus parity error\n", unit); 2301*53901Smckusick sdc->sdc_countcc--; 2302*53901Smckusick goto sdintr_exec; 2303*53901Smckusick } 2304*53901Smckusick if ((sc->sc_istatus & INST_EP) == 0) { 2305*53901Smckusick if (sc->sc_istatus & (INST_WAIT | INST_IP | INST_WR)) { 2306*53901Smckusick if (++sdc->sdc_retrycnt < NRETRY) { 2307*53901Smckusick im->im_tab.b_active = 2; 2308*53901Smckusick /* 2309*53901Smckusick * Konomama return sitemo, 2310*53901Smckusick * lost interrupt ni narudake deha 2311*53901Smckusick * naidarou ka ? 2312*53901Smckusick * Isso error ni sitahou ga 2313*53901Smckusick * ii nodeha naidarou ka ? 2314*53901Smckusick */ 2315*53901Smckusick return; 2316*53901Smckusick } 2317*53901Smckusick } 2318*53901Smckusick printf("SCSI%d: abnormal termination\n", intr); 2319*53901Smckusick printf("ISTAT = 0x%x, TSTAT = 0x%x\n", 2320*53901Smckusick sc->sc_istatus, sc->sc_tstatus); 2321*53901Smckusick if (++sdc->sdc_nhrderr >= MAXHRDERR) { 2322*53901Smckusick printf("SCSI%d: too many hard errors\n", intr); 2323*53901Smckusick sdc->sdc_nhrderr = 0; 2324*53901Smckusick goto sdintr_error; 2325*53901Smckusick } 2326*53901Smckusick screset(intr); 2327*53901Smckusick goto sdintr_exec; 2328*53901Smckusick } 2329*53901Smckusick if ((sc->sc_istatus & (INST_TO|INST_HE)) != 0) { 2330*53901Smckusick if (sc->sc_istatus & INST_HE) { 2331*53901Smckusick /* 2332*53901Smckusick * SCSI bus reset is occured. 2333*53901Smckusick * to be continue --> hdreset() 2334*53901Smckusick */ 2335*53901Smckusick re_init_done = 0; 2336*53901Smckusick timeout(wait_re_init_done, bp, 10*hz); 2337*53901Smckusick return; 2338*53901Smckusick } 2339*53901Smckusick if (++sdc->sdc_nhrderr >= MAXHRDERR) { 2340*53901Smckusick printf("SCSI%d: too many hard errors (ISTAT=0x%x)\n", 2341*53901Smckusick intr, sc->sc_istatus); 2342*53901Smckusick sdc->sdc_nhrderr = 0; 2343*53901Smckusick goto sdintr_error; 2344*53901Smckusick } 2345*53901Smckusick if (++sdc->sdc_retrycnt >= NRETRY) { 2346*53901Smckusick printf("SCSI%d: too many initiator errors (ISTAT=0x%x)\n", 2347*53901Smckusick intr, sc->sc_istatus); 2348*53901Smckusick goto sdintr_error; 2349*53901Smckusick } 2350*53901Smckusick DELAY(D100MSEC * 10); 2351*53901Smckusick goto sdintr_exec; 2352*53901Smckusick } 2353*53901Smckusick } 2354*53901Smckusick 2355*53901Smckusick if (sdd->sdd_flags & SDDF_SKIPCHECK) 2356*53901Smckusick goto sdintr_done; 2357*53901Smckusick 2358*53901Smckusick check_target_status: 2359*53901Smckusick /* 2360*53901Smckusick * check target status 2361*53901Smckusick */ 2362*53901Smckusick switch (sdc->sdc_state) { 2363*53901Smckusick 2364*53901Smckusick /********************************/ 2365*53901Smckusick /* */ 2366*53901Smckusick /* NORMAL OPERATION */ 2367*53901Smckusick /* */ 2368*53901Smckusick /********************************/ 2369*53901Smckusick case SDCS_NORMAL: 2370*53901Smckusick switch (tstatus) { 2371*53901Smckusick 2372*53901Smckusick case TGST_GOOD: 2373*53901Smckusick break; 2374*53901Smckusick 2375*53901Smckusick case TGST_CC: 2376*53901Smckusick sdc->sdc_state |= SDCS_RSENSE; 2377*53901Smckusick sdintr_rsense: 2378*53901Smckusick im->im_tab.b_active = 2; 2379*53901Smckusick bzero((caddr_t)sce, RSEN_CNT); 2380*53901Smckusick scop_rsense(intr, sc, slave, 2381*53901Smckusick SCSI_INTEN, RSEN_CNT, (caddr_t)sce); 2382*53901Smckusick return; 2383*53901Smckusick 2384*53901Smckusick case TGST_BUSY: 2385*53901Smckusick if (++sdc->sdc_retrycnt > MAXRETRYCNT) { 2386*53901Smckusick goto sdintr_error; 2387*53901Smckusick } 2388*53901Smckusick timeout(sdexec, (caddr_t)bp, hz); 2389*53901Smckusick return; 2390*53901Smckusick 2391*53901Smckusick default: 2392*53901Smckusick printf("sd%d: bad target status 0x%x\n", 2393*53901Smckusick unit, sc->sc_tstatus); 2394*53901Smckusick goto sdintr_error; 2395*53901Smckusick } 2396*53901Smckusick break; 2397*53901Smckusick 2398*53901Smckusick /****************************************/ 2399*53901Smckusick /* */ 2400*53901Smckusick /* REQUEST SENSE analysis */ 2401*53901Smckusick /* */ 2402*53901Smckusick /****************************************/ 2403*53901Smckusick case SDCS_RSENSE: 2404*53901Smckusick case SDCS_PREVRMB|SDCS_RSENSE: 2405*53901Smckusick case SDCS_ECC|SDCS_RASREAD|SDCS_RSENSE: 2406*53901Smckusick case SDCS_ECC|SDCS_RASWRITE|SDCS_RSENSE: 2407*53901Smckusick case SDCS_ECCOFF|SDCS_RSENSE: 2408*53901Smckusick case SDCS_ECCOFF|SDCS_RASBLK|SDCS_RSENSE: 2409*53901Smckusick case SDCS_ECCOFF|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE: 2410*53901Smckusick case SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE: 2411*53901Smckusick case SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE: 2412*53901Smckusick if (tstatus != TGST_GOOD) { 2413*53901Smckusick printf("sd%d: bad target status 0x%x\n", 2414*53901Smckusick unit, sc->sc_tstatus); 2415*53901Smckusick goto sdintr_error; 2416*53901Smckusick } 2417*53901Smckusick /* 2418*53901Smckusick * error message print out 2419*53901Smckusick */ 2420*53901Smckusick code = sderrordisp(sce, ii); 2421*53901Smckusick 2422*53901Smckusick 2423*53901Smckusick if ((sdc->sdc_state == (SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE)) || 2424*53901Smckusick (sdc->sdc_state == (SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE))) { 2425*53901Smckusick printf("sd%d: cannot reassign block %d\n", 2426*53901Smckusick unit, sdd->sdd_badsect); 2427*53901Smckusick goto sdintr_error; 2428*53901Smckusick } 2429*53901Smckusick if (sdc->sdc_state == (SDCS_PREVRMB|SDCS_RSENSE)) { 2430*53901Smckusick if (sce->sce_skey == 0x2) { 2431*53901Smckusick /* 2432*53901Smckusick * Not ready 2433*53901Smckusick */ 2434*53901Smckusick sdc->sdc_state = SDCS_PREVRMB; 2435*53901Smckusick timeout(delay_medrmv, (caddr_t)ii, hz); 2436*53901Smckusick return; 2437*53901Smckusick } 2438*53901Smckusick } 2439*53901Smckusick 2440*53901Smckusick /* */ 2441*53901Smckusick /* RSENSE error handler */ 2442*53901Smckusick /* */ 2443*53901Smckusick switch (code) { 2444*53901Smckusick 2445*53901Smckusick /********************************/ 2446*53901Smckusick /* continue */ 2447*53901Smckusick /********************************/ 2448*53901Smckusick /* NO SENSE */ 2449*53901Smckusick case 0x00: /* No Additional Sense Information */ 2450*53901Smckusick /* RECOVERED ERROR */ 2451*53901Smckusick case 0x38: /* Recovered with Auto-Reallocation */ 2452*53901Smckusick sdc->sdc_state &= ~SDCS_RSENSE; 2453*53901Smckusick goto check_target_status; 2454*53901Smckusick 2455*53901Smckusick /********************************/ 2456*53901Smckusick /* continue or error */ 2457*53901Smckusick /********************************/ 2458*53901Smckusick /* ILLEGAL REQUEST */ 2459*53901Smckusick 2460*53901Smckusick case 0x21: /* illegal Logical Block Address */ 2461*53901Smckusick if (&st->sizes[dev2part(bp->b_dev)] == NULL) 2462*53901Smckusick goto sdintr_error; 2463*53901Smckusick if (bp->b_bcount > 0) { 2464*53901Smckusick bp->b_resid = bp->b_bcount 2465*53901Smckusick - (sdd->sdd_badsect * sdd->sdd_sectsize 2466*53901Smckusick - (st->sizes[dev2part(bp->b_dev)].sd_blkoff 2467*53901Smckusick + dkblock(bp)) * DEV_BSIZE); 2468*53901Smckusick } 2469*53901Smckusick if (bp->b_resid >= bp->b_bcount || bp->b_resid <= 0) { 2470*53901Smckusick /* 2471*53901Smckusick * all I/O failure 2472*53901Smckusick */ 2473*53901Smckusick bp->b_resid = bp->b_bcount; 2474*53901Smckusick goto sdintr_error; 2475*53901Smckusick } 2476*53901Smckusick /* Ignore error */ 2477*53901Smckusick break; 2478*53901Smckusick 2479*53901Smckusick /* MEDIUM ERROR */ 2480*53901Smckusick case 0x31: /* Medium Format Corrupted */ 2481*53901Smckusick sdd->sdd_flags |= SDDF_NONFMT; 2482*53901Smckusick /* Ignore error */ 2483*53901Smckusick break; 2484*53901Smckusick 2485*53901Smckusick /********************************/ 2486*53901Smckusick /* more retry */ 2487*53901Smckusick /********************************/ 2488*53901Smckusick /* MEDIUM or RECOVERED ERROR */ 2489*53901Smckusick case 0x10: /* ID CRC Error */ 2490*53901Smckusick case 0x12: /* No Address Mark found in ID field */ 2491*53901Smckusick case 0x13: /* No Address Mark found in Data field */ 2492*53901Smckusick case 0x14: /* No recode found */ 2493*53901Smckusick /* H/W or MEDIUM or RECOVERED ERROR */ 2494*53901Smckusick case 0x15: /* Seek Positioning Error */ 2495*53901Smckusick if (sd_ignore_error) { 2496*53901Smckusick sdc->sdc_state = SDCS_NORMAL; 2497*53901Smckusick goto check_target_status; 2498*53901Smckusick } 2499*53901Smckusick /* fall through */ 2500*53901Smckusick 2501*53901Smckusick /* H/W ERROR */ 2502*53901Smckusick case 0x01: /* No Index/Address Mark Found signal */ 2503*53901Smckusick case 0x02: /* No Seek Complete */ 2504*53901Smckusick case 0x06: /* No Track Zero found */ 2505*53901Smckusick /* H/W ERROR or RECOVERED ERROR */ 2506*53901Smckusick case 0x03: /* Write Fault */ 2507*53901Smckusick case 0x08: /* Logical Unit Communication Failure */ 2508*53901Smckusick case 0x09: /* Track Following Error */ 2509*53901Smckusick case 0x0b: /* Load/Unload Failure */ 2510*53901Smckusick case 0x0c: /* Spindle Failure */ 2511*53901Smckusick case 0x0d: /* Focus Failure */ 2512*53901Smckusick case 0x0e: /* Tracking Failure */ 2513*53901Smckusick case 0x0f: /* Drive Initialization Failure */ 2514*53901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_REZERO; 2515*53901Smckusick 2516*53901Smckusick scinit(sc, slave, sdd->sdd_sectsize); 2517*53901Smckusick /* sc_cdb */ 2518*53901Smckusick sc->sc_opcode = SCOP_REZERO; 2519*53901Smckusick 2520*53901Smckusick sddgo(im); 2521*53901Smckusick return; 2522*53901Smckusick 2523*53901Smckusick /********************************/ 2524*53901Smckusick /* re-allocate & retry */ 2525*53901Smckusick /********************************/ 2526*53901Smckusick /* MEDIUM or RECOVERED ERROR */ 2527*53901Smckusick case 0x11: /* Unrecovered Read Error */ 2528*53901Smckusick if (sdc->sdc_state & SDCS_RASREAD) { 2529*53901Smckusick sdintr_lostdata: 2530*53901Smckusick sdc->sdc_state = 2531*53901Smckusick SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA; 2532*53901Smckusick im->im_tab.b_active = 2; 2533*53901Smckusick scop_rasblk(intr, sc, slave, 2534*53901Smckusick SCSI_INTEN, sdd->sdd_badsect); 2535*53901Smckusick sdd->sdd_flags &= ~SDDF_VBADSECT; 2536*53901Smckusick return; 2537*53901Smckusick } 2538*53901Smckusick /* fall through */ 2539*53901Smckusick 2540*53901Smckusick /* RECOVERED ERROR */ 2541*53901Smckusick case 0x17: /* Recovered read data with retries */ 2542*53901Smckusick case 0x18: /* Recovered read data with ECC */ 2543*53901Smckusick /* 2544*53901Smckusick * set ECC ON & more retry 2545*53901Smckusick */ 2546*53901Smckusick if (sdc->sdc_firmware & SDCFW_DEFMODE) 2547*53901Smckusick goto sdintr_ecc; 2548*53901Smckusick 2549*53901Smckusick if (sdc->sdc_state & SDCS_RASREAD) 2550*53901Smckusick goto sdintr_rasblk; 2551*53901Smckusick 2552*53901Smckusick sdc->sdc_state = SDCS_ECC; 2553*53901Smckusick goto sdintr_msel_set; 2554*53901Smckusick 2555*53901Smckusick /********************************/ 2556*53901Smckusick /* unit start & retry */ 2557*53901Smckusick /********************************/ 2558*53901Smckusick /* NOT READY */ 2559*53901Smckusick case 0x04: /* Drive Not Ready */ 2560*53901Smckusick if (sdc->sdc_state & SDCS_ECC) 2561*53901Smckusick sdc->sdc_state = SDCS_ECCOFF|SDCS_RETRY; 2562*53901Smckusick else 2563*53901Smckusick sdc->sdc_state = SDCS_RETRY; 2564*53901Smckusick goto sdintr_stst; 2565*53901Smckusick 2566*53901Smckusick /********************************/ 2567*53901Smckusick /* retry */ 2568*53901Smckusick /********************************/ 2569*53901Smckusick /* UNIT ATTENTION */ 2570*53901Smckusick case 0x28: /* Medium Changed */ 2571*53901Smckusick sdd->sdd_flags &= ~(SDDF_NONFMT 2572*53901Smckusick |SDDF_SAMEDSK 2573*53901Smckusick |SDDF_REQ_EJECT 2574*53901Smckusick |SDDF_XUSE 2575*53901Smckusick |SDDF_INHRMV 2576*53901Smckusick |SDDF_ERASEOFF); 2577*53901Smckusick /* fall through */ 2578*53901Smckusick 2579*53901Smckusick case 0x29: /* Power On or Reset or Bus Device Reset */ 2580*53901Smckusick if (sdc->sdc_firmware & SDCFW_RMB) { 2581*53901Smckusick /***************************/ 2582*53901Smckusick /* medium removable device */ 2583*53901Smckusick /***************************/ 2584*53901Smckusick sdc->sdc_state = SDCS_PREVRMB; 2585*53901Smckusick im->im_tab.b_active = 2; 2586*53901Smckusick scop_medrmv(intr, sc, slave, 2587*53901Smckusick SCSI_INTEN, SDRMV_PREV); 2588*53901Smckusick return; 2589*53901Smckusick } 2590*53901Smckusick 2591*53901Smckusick case 0x2a: /* Mode Select Parameter Changed */ 2592*53901Smckusick case 0x47: /* SCSI interface bus parity error */ 2593*53901Smckusick if (sdc->sdc_state & SDCS_ECC) { 2594*53901Smckusick sdc->sdc_state = SDCS_RETRY; 2595*53901Smckusick goto sdintr_msel_reset; 2596*53901Smckusick } 2597*53901Smckusick sdc->sdc_state = SDCS_NORMAL; 2598*53901Smckusick goto sdintr_exec; 2599*53901Smckusick 2600*53901Smckusick /********************************/ 2601*53901Smckusick /* set error flag */ 2602*53901Smckusick /********************************/ 2603*53901Smckusick case 0x40: /* RAM failure */ 2604*53901Smckusick case 0x41: /* Data Path diagnostic failure */ 2605*53901Smckusick case 0x42: /* Power On diagnostic failure */ 2606*53901Smckusick 2607*53901Smckusick case 0xb2: /* Caddy load/eject failed */ 2608*53901Smckusick case 0xb4: /* Focus servo failure */ 2609*53901Smckusick case 0xb5: /* Spindle servo failure */ 2610*53901Smckusick case 0xb6: /* Caddy load mechanism failed */ 2611*53901Smckusick goto sdintr_error; 2612*53901Smckusick 2613*53901Smckusick /*MO*/ case 0x80: /* Limit Laser Life */ 2614*53901Smckusick /*MO*/ case 0x81: /* Focus Coil Over-current Failure */ 2615*53901Smckusick /*MO*/ case 0x82: /* Tracking Coil Over-current Failure */ 2616*53901Smckusick /*MO*/ case 0x83: /* Temperature Alarm */ 2617*53901Smckusick /*CD*/ /* case 0x80: */ /* Prevent bit is set */ 2618*53901Smckusick /*CD*/ /* case 0x81: */ /* Logical unit is reserved */ 2619*53901Smckusick /*CD*/ /* case 0x82: */ /* End of usr area encountered */ 2620*53901Smckusick /*CD*/ /* case 0x83: */ /* Overlapped commands attempted */ 2621*53901Smckusick goto sdintr_error; 2622*53901Smckusick 2623*53901Smckusick default: 2624*53901Smckusick /* 2625*53901Smckusick * error detect, but what shall we do ? 2626*53901Smckusick */ 2627*53901Smckusick /* case 0x05: */ /* Drive Not Selected */ 2628*53901Smckusick /* case 0x07: */ /* Multiple Drives Selected */ 2629*53901Smckusick /* case 0x0a: */ /* No disk */ 2630*53901Smckusick /* case 0x1a: */ /* Parameter overrun */ 2631*53901Smckusick /* case 0x1b: */ /* Synchronous transfer error */ 2632*53901Smckusick /* case 0x1d: */ /* Compare error */ 2633*53901Smckusick /* case 0x22: */ /* Illegal function for device type */ 2634*53901Smckusick /* case 0x23: */ /* Illegal function for Medium type */ 2635*53901Smckusick /* case 0x25: */ /* Illegal LUN */ 2636*53901Smckusick /* case 0x27: */ /* Write Protected */ 2637*53901Smckusick /* case 0x2b: */ /* Firmware has been downloaded */ 2638*53901Smckusick /* case 0x39: */ /* Automatic Reallocation Failure */ 2639*53901Smckusick /* case 0x43: */ /* Message Reject Error */ 2640*53901Smckusick /* case 0x45: */ /* Selection/Reselection failure */ 2641*53901Smckusick /* case 0x48: */ /* Initiator detected error */ 2642*53901Smckusick /* case 0x49: */ /* Inappropriate/illegal message */ 2643*53901Smckusick /* case 0x60: */ /* COPY: STATUS error */ 2644*53901Smckusick /* case 0x85: */ /* Audio address not valid */ 2645*53901Smckusick /* case 0xb0: */ /* Caddy not inserted in drive */ 2646*53901Smckusick /* case 0xb1: */ /* Unable to recover TOC */ 2647*53901Smckusick /* case 0xb3: */ /* CIRC unrecovered data error(L-EC off) */ 2648*53901Smckusick /* case 0xc3: */ /* COPY: Illegale CDB length */ 2649*53901Smckusick /* case 0xc5: */ /* COPY: Catastrophic error */ 2650*53901Smckusick /* case 0xc6: */ /* COPY: Illegal phase change */ 2651*53901Smckusick /* case 0xfc: */ /* COPY: MODE SENSE failed */ 2652*53901Smckusick 2653*53901Smckusick /* 2654*53901Smckusick * medium error 2655*53901Smckusick */ 2656*53901Smckusick /* case 0x19: */ /* Defect list error */ 2657*53901Smckusick /* case 0x1c: */ /* Primary Defect List not found */ 2658*53901Smckusick /* case 0x30: */ /* Incompatible Cartridge */ 2659*53901Smckusick /* case 0x32: */ /* No Spare Defect Location Available */ 2660*53901Smckusick /* case 0x3a: */ /* Defect List Update Failure */ 2661*53901Smckusick /* case 0x3d: */ /* Defect List Not Available */ 2662*53901Smckusick goto sdintr_error; 2663*53901Smckusick } 2664*53901Smckusick /* 2665*53901Smckusick * No error detected or ignored. 2666*53901Smckusick */ 2667*53901Smckusick break; 2668*53901Smckusick 2669*53901Smckusick /************************************************/ 2670*53901Smckusick /* */ 2671*53901Smckusick /* PREVENT MEDIUM REMOVABLE COMMAND */ 2672*53901Smckusick /* */ 2673*53901Smckusick /************************************************/ 2674*53901Smckusick case SDCS_PREVRMB: 2675*53901Smckusick if (tstatus == TGST_CC) { 2676*53901Smckusick sdc->sdc_state = SDCS_PREVRMB|SDCS_RSENSE; 2677*53901Smckusick goto sdintr_rsense; 2678*53901Smckusick } 2679*53901Smckusick sdd->sdd_flags |= SDDF_INHRMV; 2680*53901Smckusick if (sdc->sdc_state & SDCS_ECC) { 2681*53901Smckusick sdc->sdc_state = SDCS_RETRY; 2682*53901Smckusick goto sdintr_msel_reset; 2683*53901Smckusick } 2684*53901Smckusick sdc->sdc_state = SDCS_NORMAL; 2685*53901Smckusick goto sdintr_exec; 2686*53901Smckusick break; 2687*53901Smckusick 2688*53901Smckusick /****************************************/ 2689*53901Smckusick /* */ 2690*53901Smckusick /* REZERO done & RETRY COMMAND */ 2691*53901Smckusick /* */ 2692*53901Smckusick /****************************************/ 2693*53901Smckusick case SDCS_ECC|SDCS_ECC_HOLD|SDCS_REZERO: 2694*53901Smckusick if (sdc->sdc_firmware & SDCFW_DEFMODE) { 2695*53901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY; 2696*53901Smckusick goto sdintr_stst; 2697*53901Smckusick } 2698*53901Smckusick 2699*53901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD; 2700*53901Smckusick goto sdintr_msel_set; 2701*53901Smckusick 2702*53901Smckusick /********************************/ 2703*53901Smckusick /* */ 2704*53901Smckusick /* RETRY COMMAND */ 2705*53901Smckusick /* */ 2706*53901Smckusick /********************************/ 2707*53901Smckusick case SDCS_RETRY: 2708*53901Smckusick sdc->sdc_state = SDCS_NORMAL; 2709*53901Smckusick goto sdintr_exec; 2710*53901Smckusick 2711*53901Smckusick /************************************************/ 2712*53901Smckusick /* */ 2713*53901Smckusick /* ERROR CORRECTION ON MODE SELECT result */ 2714*53901Smckusick /* */ 2715*53901Smckusick /************************************************/ 2716*53901Smckusick case SDCS_ECC: 2717*53901Smckusick if (tstatus != TGST_GOOD) { 2718*53901Smckusick printf("sd%d: bad target status 0x%x\n", 2719*53901Smckusick unit, sc->sc_tstatus); 2720*53901Smckusick goto sdintr_error; 2721*53901Smckusick } 2722*53901Smckusick sdintr_ecc: 2723*53901Smckusick if (bp->b_flags & B_READ) { 2724*53901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASREAD; 2725*53901Smckusick im->im_tab.b_active = 2; 2726*53901Smckusick scop_rdwr(intr, sc, slave, SCSI_INTEN, 2727*53901Smckusick B_READ, sdwork, 2728*53901Smckusick sdd->sdd_badsect, sdd->sdd_sectsize); 2729*53901Smckusick return; 2730*53901Smckusick } 2731*53901Smckusick goto sdintr_rasblk; 2732*53901Smckusick 2733*53901Smckusick /************************************************/ 2734*53901Smckusick /* */ 2735*53901Smckusick /* READ DATA from BAD BLOCK result */ 2736*53901Smckusick /* */ 2737*53901Smckusick /************************************************/ 2738*53901Smckusick case SDCS_ECC|SDCS_RASREAD: 2739*53901Smckusick if (tstatus == TGST_CC) { 2740*53901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASREAD|SDCS_RSENSE; 2741*53901Smckusick goto sdintr_rsense; 2742*53901Smckusick } else if (tstatus != TGST_GOOD) { 2743*53901Smckusick printf("sd%d: bad target status 0x%x\n", 2744*53901Smckusick unit, sc->sc_tstatus); 2745*53901Smckusick printf("sd%d: cannot read block\n", unit); 2746*53901Smckusick goto sdintr_error; 2747*53901Smckusick } 2748*53901Smckusick sdintr_rasblk: 2749*53901Smckusick if (sdd->sdd_flags & SDDF_WPROTECT) 2750*53901Smckusick goto sdintr_error; 2751*53901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASBLK; 2752*53901Smckusick im->im_tab.b_active = 2; 2753*53901Smckusick scop_rasblk(intr, sc, slave, SCSI_INTEN, sdd->sdd_badsect); 2754*53901Smckusick sdd->sdd_flags &= ~SDDF_VBADSECT; 2755*53901Smckusick return; 2756*53901Smckusick 2757*53901Smckusick /****************************************/ 2758*53901Smckusick /* */ 2759*53901Smckusick /* REASSIGN BLOCK result */ 2760*53901Smckusick /* */ 2761*53901Smckusick /****************************************/ 2762*53901Smckusick case SDCS_ECC|SDCS_RASBLK: 2763*53901Smckusick if (tstatus == TGST_CC) { 2764*53901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE; 2765*53901Smckusick goto sdintr_rsense; 2766*53901Smckusick } else if (tstatus != TGST_GOOD) { 2767*53901Smckusick printf("sd%d: bad target status 0x%x\n", 2768*53901Smckusick unit, sc->sc_tstatus); 2769*53901Smckusick goto sdintr_error; 2770*53901Smckusick } 2771*53901Smckusick printf("sd%d: block %d is reassigned\n", 2772*53901Smckusick unit, sdd->sdd_badsect); 2773*53901Smckusick if (bp->b_flags & B_READ) { 2774*53901Smckusick sdintr_raswrite: 2775*53901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASWRITE; 2776*53901Smckusick im->im_tab.b_active = 2; 2777*53901Smckusick scop_rdwr(intr, sc, slave, SCSI_INTEN, 2778*53901Smckusick B_WRITE, sdwork, 2779*53901Smckusick sdd->sdd_badsect, sdd->sdd_sectsize); 2780*53901Smckusick return; 2781*53901Smckusick } 2782*53901Smckusick sdc->sdc_state = SDCS_RETRY; 2783*53901Smckusick goto sdintr_msel_reset; 2784*53901Smckusick 2785*53901Smckusick /************************************************/ 2786*53901Smckusick /* */ 2787*53901Smckusick /* WRITE DATA to REASSIGNED BLOCK result */ 2788*53901Smckusick /* */ 2789*53901Smckusick /************************************************/ 2790*53901Smckusick case SDCS_ECC|SDCS_RASWRITE: 2791*53901Smckusick if (tstatus == TGST_CC) { 2792*53901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_RASWRITE|SDCS_RSENSE; 2793*53901Smckusick goto sdintr_rsense; 2794*53901Smckusick } else if (tstatus != TGST_GOOD) { 2795*53901Smckusick printf("sd%d: bad target status 0x%x\n", 2796*53901Smckusick unit, sc->sc_tstatus); 2797*53901Smckusick goto sdintr_error; 2798*53901Smckusick } 2799*53901Smckusick sdc->sdc_state = SDCS_RETRY; 2800*53901Smckusick goto sdintr_msel_reset; 2801*53901Smckusick 2802*53901Smckusick /****************************************/ 2803*53901Smckusick /* */ 2804*53901Smckusick /* reset ECC & RETRY TIMES */ 2805*53901Smckusick /* */ 2806*53901Smckusick /****************************************/ 2807*53901Smckusick case SDCS_ECCOFF|SDCS_RETRY: 2808*53901Smckusick sdc->sdc_state = SDCS_RETRY; 2809*53901Smckusick goto sdintr_msel_reset; 2810*53901Smckusick 2811*53901Smckusick /********************************************************/ 2812*53901Smckusick /* */ 2813*53901Smckusick /* READ DATA from BAD BLOCK result in faliure */ 2814*53901Smckusick /* */ 2815*53901Smckusick /********************************************************/ 2816*53901Smckusick case SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA: 2817*53901Smckusick if (tstatus == TGST_CC) { 2818*53901Smckusick sdc->sdc_state = 2819*53901Smckusick SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE; 2820*53901Smckusick goto sdintr_rsense; 2821*53901Smckusick } else if (tstatus != TGST_GOOD) { 2822*53901Smckusick printf("sd%d: rasblk: bad target status 0x%x\n", 2823*53901Smckusick unit, sc->sc_tstatus); 2824*53901Smckusick goto sdintr_error; 2825*53901Smckusick } 2826*53901Smckusick bzero(sdwork, sdd->sdd_sectsize); 2827*53901Smckusick scop_rdwr(intr, sc, slave, SCSI_INTDIS, 2828*53901Smckusick B_WRITE, sdwork, sdd->sdd_badsect, sdd->sdd_sectsize); 2829*53901Smckusick printf("sd%d: block %d is reassigned (lost data)\n", 2830*53901Smckusick unit, sdd->sdd_badsect); 2831*53901Smckusick goto sdintr_error; 2832*53901Smckusick 2833*53901Smckusick /****************************************/ 2834*53901Smckusick /* */ 2835*53901Smckusick /* issue START UNIT command */ 2836*53901Smckusick /* */ 2837*53901Smckusick /****************************************/ 2838*53901Smckusick case SDCS_ECC|SDCS_ECC_HOLD: 2839*53901Smckusick /* 2840*53901Smckusick * Drive not ready... so start.. 2841*53901Smckusick */ 2842*53901Smckusick sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY; 2843*53901Smckusick sdintr_stst: 2844*53901Smckusick timeout(delay_start, (caddr_t)ii, hz); 2845*53901Smckusick return; 2846*53901Smckusick 2847*53901Smckusick /****************************************/ 2848*53901Smckusick /* */ 2849*53901Smckusick /* RETRY with ECC & more RETRYS */ 2850*53901Smckusick /* */ 2851*53901Smckusick /****************************************/ 2852*53901Smckusick case SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY: 2853*53901Smckusick sdc->sdc_state = SDCS_ECCOFF; 2854*53901Smckusick sdintr_exec: 2855*53901Smckusick if (sdc->sdc_countcc++ > MAXRETRYCNT) 2856*53901Smckusick goto sdintr_error; 2857*53901Smckusick sdexec(bp); 2858*53901Smckusick return; 2859*53901Smckusick 2860*53901Smckusick /****************************************/ 2861*53901Smckusick /* */ 2862*53901Smckusick /* reset ECC & RETRY TIMES */ 2863*53901Smckusick /* */ 2864*53901Smckusick /****************************************/ 2865*53901Smckusick case SDCS_ECCOFF: 2866*53901Smckusick if (tstatus == TGST_CC) { 2867*53901Smckusick sdc->sdc_state = SDCS_ECCOFF|SDCS_RSENSE; 2868*53901Smckusick goto sdintr_rsense; 2869*53901Smckusick } else if (tstatus != TGST_GOOD) { 2870*53901Smckusick printf("sd%d: bad target status 0x%x\n", 2871*53901Smckusick unit, sc->sc_tstatus); 2872*53901Smckusick goto sdintr_error; 2873*53901Smckusick } 2874*53901Smckusick sdc->sdc_state = SDCS_NORMAL; 2875*53901Smckusick goto sdintr_msel_reset; 2876*53901Smckusick 2877*53901Smckusick sdintr_msel_set: 2878*53901Smckusick /* 2879*53901Smckusick * set more ERROR RECOVERY PARAMETERS 2880*53901Smckusick */ 2881*53901Smckusick if ((erp_page = sdi->max_ERP_page) == NULL) 2882*53901Smckusick goto check_target_status; 2883*53901Smckusick bzero((caddr_t)sc->sc_param, 4); 2884*53901Smckusick len = *(erp_page + 1) + 2; 2885*53901Smckusick bcopy(erp_page, &sc->sc_param[4], len); 2886*53901Smckusick 2887*53901Smckusick im->im_tab.b_active = 2; 2888*53901Smckusick scop_mselect(intr, sc, slave, SCSI_INTEN, 2889*53901Smckusick (SDM_PF<<24) + len +4, (caddr_t)0); 2890*53901Smckusick return; 2891*53901Smckusick 2892*53901Smckusick sdintr_msel_reset: 2893*53901Smckusick if (sdc->sdc_firmware & SDCFW_DEFMODE) 2894*53901Smckusick goto sdintr_exec; 2895*53901Smckusick 2896*53901Smckusick /* 2897*53901Smckusick * set normal ERROR RECOVERY PARAMETERS 2898*53901Smckusick */ 2899*53901Smckusick erp_page = sdi->ERP_page; 2900*53901Smckusick bzero((caddr_t)sc->sc_param, 4); 2901*53901Smckusick len = *(erp_page + 1) + 2; 2902*53901Smckusick bcopy(erp_page, &sc->sc_param[4], len); 2903*53901Smckusick 2904*53901Smckusick im->im_tab.b_active = 2; 2905*53901Smckusick scop_mselect(intr, sc, slave, SCSI_INTEN, 2906*53901Smckusick (SDM_PF<<24) + len +4, (caddr_t)0); 2907*53901Smckusick return; 2908*53901Smckusick 2909*53901Smckusick sdintr_error: 2910*53901Smckusick bp->b_flags |= B_ERROR; 2911*53901Smckusick if (sdc->sdc_state & SDCS_ECC) { 2912*53901Smckusick sdc->sdc_state = SDCS_NORMAL; 2913*53901Smckusick goto sdintr_msel_reset; 2914*53901Smckusick } 2915*53901Smckusick break; 2916*53901Smckusick 2917*53901Smckusick /* 2918*53901Smckusick * UNKNOWN STATUS 2919*53901Smckusick */ 2920*53901Smckusick default: 2921*53901Smckusick printf("sd%d: unknown status (0x%x)\n", unit, sdc->sdc_state); 2922*53901Smckusick goto sdintr_error; 2923*53901Smckusick } 2924*53901Smckusick 2925*53901Smckusick sdintr_done: 2926*53901Smckusick 2927*53901Smckusick if (bp->b_flags & B_ERROR) { 2928*53901Smckusick printf("%s%d%c: hard error sn%d ", "sd", 2929*53901Smckusick minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 2930*53901Smckusick printf("\n"); 2931*53901Smckusick } 2932*53901Smckusick sdd->sdd_lastblk = dkblock(bp) + btodb(bp->b_bcount - bp->b_resid); 2933*53901Smckusick sdc->sdc_countcc = 0; 2934*53901Smckusick sdc->sdc_retrycnt = 0; 2935*53901Smckusick sdd->sdd_flags &= ~SDDF_VBADSECT; 2936*53901Smckusick 2937*53901Smckusick if (im->im_tab.b_active) { 2938*53901Smckusick im->im_tab.b_active = 0; 2939*53901Smckusick im->im_tab.b_errcnt = 0; 2940*53901Smckusick im->im_tab.b_actf = dp->b_forw; 2941*53901Smckusick dp->b_active = 0; 2942*53901Smckusick dp->b_errcnt = 0; 2943*53901Smckusick dp->b_actf = bp->av_forw; 2944*53901Smckusick if (bp == &csdbuf[unit]) { 2945*53901Smckusick register struct scsi *ksc = &kernscsi[unit]; 2946*53901Smckusick /* copy result */ 2947*53901Smckusick bcopy((caddr_t)sc, (caddr_t)ksc, sizeof(struct scsi)); 2948*53901Smckusick } 2949*53901Smckusick 2950*53901Smckusick iodone(bp); 2951*53901Smckusick 2952*53901Smckusick /* 2953*53901Smckusick * If this unit has more work to do, 2954*53901Smckusick * then start it up right away. 2955*53901Smckusick */ 2956*53901Smckusick if (dp->b_actf) 2957*53901Smckusick sdustart(ii); 2958*53901Smckusick } 2959*53901Smckusick as &= ~(1 << slave); 2960*53901Smckusick 2961*53901Smckusick sdc->sdc_state = SDCS_NORMAL; 2962*53901Smckusick 2963*53901Smckusick /* 2964*53901Smckusick * UNLOCK SCSI access 2965*53901Smckusick */ 2966*53901Smckusick sdc->sdc_firmware &= ~SDCFW_BUSY; 2967*53901Smckusick 2968*53901Smckusick start: 2969*53901Smckusick /* 2970*53901Smckusick * Process other units which need attention. 2971*53901Smckusick * For each unit which needs attention, call 2972*53901Smckusick * the unit start routine to place the slave 2973*53901Smckusick * on the controller device queue. 2974*53901Smckusick */ 2975*53901Smckusick sdc->sdc_softas = 0; 2976*53901Smckusick while (unit = ffs(as)) { 2977*53901Smckusick unit--; 2978*53901Smckusick as &= ~(1 << unit); 2979*53901Smckusick sdustart(sdip[im->im_ctlr][unit]); 2980*53901Smckusick } 2981*53901Smckusick /* 2982*53901Smckusick * If the controller is not transferring, 2983*53901Smckusick * but there are devices ready to transfer, 2984*53901Smckusick * start the controller. 2985*53901Smckusick */ 2986*53901Smckusick if (im->im_tab.b_actf && im->im_tab.b_active == 0) 2987*53901Smckusick (void) sdstart(im); 2988*53901Smckusick } 2989*53901Smckusick 2990*53901Smckusick wait_re_init_done(bp) 2991*53901Smckusick register struct buf *bp; 2992*53901Smckusick { 2993*53901Smckusick if (re_init_done >= 2) 2994*53901Smckusick sdexec(bp); 2995*53901Smckusick else 2996*53901Smckusick timeout(wait_re_init_done, bp, 10*hz); 2997*53901Smckusick } 2998*53901Smckusick 2999*53901Smckusick delay_start(ii) 3000*53901Smckusick struct iop/**/_device *ii; 3001*53901Smckusick { 3002*53901Smckusick ii->ii_mi->im_tab.b_active = 2; 3003*53901Smckusick scop_stst(ii->ii_intr, get_scsi(ii->ii_intr), ii->ii_slave, 3004*53901Smckusick SCSI_INTEN, SDSS_START); 3005*53901Smckusick } 3006*53901Smckusick 3007*53901Smckusick delay_medrmv(ii) 3008*53901Smckusick struct iop/**/_device *ii; 3009*53901Smckusick { 3010*53901Smckusick ii->ii_mi->im_tab.b_active = 2; 3011*53901Smckusick scop_medrmv(ii->ii_intr, get_scsi(ii->ii_intr), ii->ii_slave, 3012*53901Smckusick SCSI_INTEN, SDRMV_PREV); 3013*53901Smckusick } 3014*53901Smckusick 3015*53901Smckusick sderrordisp(rsen_data, ii) 3016*53901Smckusick u_char *rsen_data; 3017*53901Smckusick struct iop/**/_device *ii; 3018*53901Smckusick { 3019*53901Smckusick register struct sc_extnd *sce; 3020*53901Smckusick register struct sdc_softc *sdc; 3021*53901Smckusick register struct sdd_softc *sdd; 3022*53901Smckusick register int unit; 3023*53901Smckusick register int code; 3024*53901Smckusick struct sc_nextnd *scn; 3025*53901Smckusick struct msg_list *ml; 3026*53901Smckusick 3027*53901Smckusick unit = ii->ii_unit; 3028*53901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 3029*53901Smckusick sdd = &sdd_softc[unit]; 3030*53901Smckusick 3031*53901Smckusick sce = (struct sc_extnd *)rsen_data; 3032*53901Smckusick 3033*53901Smckusick if (sce->sce_extend == 0x70) { 3034*53901Smckusick /* 3035*53901Smckusick * Extended Sense data 3036*53901Smckusick */ 3037*53901Smckusick code = sce->sce_sdecode; 3038*53901Smckusick 3039*53901Smckusick if (code & 0x80) 3040*53901Smckusick ml = ecodelist_mo; 3041*53901Smckusick else 3042*53901Smckusick ml = ecodelist; 3043*53901Smckusick 3044*53901Smckusick if (sce->sce_advalid) { 3045*53901Smckusick if ((sdd->sdd_flags & SDDF_VBADSECT) == 0) { 3046*53901Smckusick #ifdef mips 3047*53901Smckusick sdd->sdd_badsect = (sce->sce_infob1 << 24) + 3048*53901Smckusick (sce->sce_infob2 << 16) + 3049*53901Smckusick (sce->sce_infob3 << 8) + 3050*53901Smckusick (sce->sce_infob4); 3051*53901Smckusick #else 3052*53901Smckusick sdd->sdd_badsect = *((int *)&sce->sce_infob1); 3053*53901Smckusick #endif 3054*53901Smckusick sdd->sdd_flags |= SDDF_VBADSECT; 3055*53901Smckusick } 3056*53901Smckusick } 3057*53901Smckusick 3058*53901Smckusick if (!rsense_msg_disp && !isdispmsg(code, ml, sdc->sdc_countcc)) 3059*53901Smckusick return (code); 3060*53901Smckusick 3061*53901Smckusick if (sce->sce_advalid) { 3062*53901Smckusick int sn; 3063*53901Smckusick #ifdef mips 3064*53901Smckusick sn = (sce->sce_infob1 << 24) + 3065*53901Smckusick (sce->sce_infob2 << 16) + 3066*53901Smckusick (sce->sce_infob3 << 8) + 3067*53901Smckusick (sce->sce_infob4); 3068*53901Smckusick #else 3069*53901Smckusick sn = *((int *)&sce->sce_infob1); 3070*53901Smckusick #endif 3071*53901Smckusick if (sce->sce_addlen >= 5) { 3072*53901Smckusick printf("sd%d(sn %d): skey=0x%x, code=0x%x\n", 3073*53901Smckusick unit, sn, sce->sce_skey, code); 3074*53901Smckusick } else { 3075*53901Smckusick printf("sd%d(sn %d): skey=0x%x\n", 3076*53901Smckusick unit, sn, sce->sce_skey); 3077*53901Smckusick } 3078*53901Smckusick } else { 3079*53901Smckusick if (sce->sce_addlen >= 5) 3080*53901Smckusick printf("sd%d: skey=0x%x, code=0x%x\n", 3081*53901Smckusick unit, sce->sce_skey, code); 3082*53901Smckusick else 3083*53901Smckusick printf("sd%d: skey=0x%x\n", 3084*53901Smckusick unit, sce->sce_skey); 3085*53901Smckusick } 3086*53901Smckusick if (sce->sce_addlen >= 6) 3087*53901Smckusick printf("sd%d: ASCQ=0x%x\n", unit, sce->sce_ascq); 3088*53901Smckusick { 3089*53901Smckusick u_char *p; 3090*53901Smckusick int len; 3091*53901Smckusick 3092*53901Smckusick len = 8 + sce->sce_addlen; 3093*53901Smckusick if (len > RSEN_CNT) 3094*53901Smckusick len = RSEN_CNT; 3095*53901Smckusick p = (u_char *)sce; 3096*53901Smckusick printf("sd%d: ", unit); 3097*53901Smckusick while (len--) 3098*53901Smckusick printf("%x ", *p++); 3099*53901Smckusick printf("\n"); 3100*53901Smckusick } 3101*53901Smckusick } else { 3102*53901Smckusick /* 3103*53901Smckusick * Non-extended Sense data 3104*53901Smckusick */ 3105*53901Smckusick scn = (struct sc_nextnd *)rsen_data; 3106*53901Smckusick 3107*53901Smckusick code = scn->scn_ecode; 3108*53901Smckusick ml = ecodelist; 3109*53901Smckusick if (sce->sce_advalid) { 3110*53901Smckusick if ((sdd->sdd_flags & SDDF_VBADSECT) == 0) { 3111*53901Smckusick sdd->sdd_badsect = scn->scn_secno; 3112*53901Smckusick sdd->sdd_flags |= SDDF_VBADSECT; 3113*53901Smckusick } 3114*53901Smckusick } 3115*53901Smckusick if (rsense_msg_disp || isdispmsg(code, ml, sdc->sdc_countcc)) { 3116*53901Smckusick if (sce->sce_advalid) 3117*53901Smckusick printf("sd%d(sn %d): code=0x%x\n", 3118*53901Smckusick unit, scn->scn_secno, code); 3119*53901Smckusick else 3120*53901Smckusick printf("sd%d: code=0x%x\n", unit, code); 3121*53901Smckusick } 3122*53901Smckusick } 3123*53901Smckusick return (code); 3124*53901Smckusick } 3125*53901Smckusick 3126*53901Smckusick void 3127*53901Smckusick sdminphys(bp) 3128*53901Smckusick struct buf *bp; 3129*53901Smckusick { 3130*53901Smckusick if (bp->b_bcount > MAXSDPHYS) 3131*53901Smckusick bp->b_bcount = MAXSDPHYS; 3132*53901Smckusick } 3133*53901Smckusick 3134*53901Smckusick 3135*53901Smckusick #define sdphysio physio 3136*53901Smckusick 3137*53901Smckusick sdread(dev, uio, flag) 3138*53901Smckusick register dev_t dev; 3139*53901Smckusick struct uio *uio; 3140*53901Smckusick int flag; 3141*53901Smckusick { 3142*53901Smckusick register struct iop/**/_device *ii; 3143*53901Smckusick register int unit; 3144*53901Smckusick 3145*53901Smckusick unit = dev2unit(dev); 3146*53901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0) 3147*53901Smckusick return (ENXIO); 3148*53901Smckusick 3149*53901Smckusick return (sdphysio(sdstrategy, &rsdbuf[unit], dev, B_READ, sdminphys, uio)); 3150*53901Smckusick } 3151*53901Smckusick 3152*53901Smckusick sdwrite(dev, uio, flag) 3153*53901Smckusick register dev_t dev; 3154*53901Smckusick struct uio *uio; 3155*53901Smckusick int flag; 3156*53901Smckusick { 3157*53901Smckusick register struct iop/**/_device *ii; 3158*53901Smckusick register int unit; 3159*53901Smckusick 3160*53901Smckusick unit = dev2unit(dev); 3161*53901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0) 3162*53901Smckusick return (ENXIO); 3163*53901Smckusick 3164*53901Smckusick return (sdphysio(sdstrategy, &rsdbuf[unit], dev, B_WRITE, sdminphys, uio)); 3165*53901Smckusick } 3166*53901Smckusick 3167*53901Smckusick #define MAXBL 256 3168*53901Smckusick 3169*53901Smckusick /*ARGSUSED*/ 3170*53901Smckusick sdioctl(dev, cmd, data, flag) 3171*53901Smckusick dev_t dev; 3172*53901Smckusick int cmd; 3173*53901Smckusick caddr_t data; 3174*53901Smckusick int flag; 3175*53901Smckusick { 3176*53901Smckusick register struct iop/**/_device *ii; 3177*53901Smckusick register struct sc_ureq *scu; 3178*53901Smckusick register struct sdst *st; 3179*53901Smckusick register struct scsi *sc; 3180*53901Smckusick register int unit; 3181*53901Smckusick register int ctlr; 3182*53901Smckusick register int slave; 3183*53901Smckusick struct sdc_softc *sdc; 3184*53901Smckusick struct sdd_softc *sdd; 3185*53901Smckusick struct Partinfo *pi; 3186*53901Smckusick struct dkst *di; 3187*53901Smckusick struct buf *bp; 3188*53901Smckusick struct sddevinfo *sdi; 3189*53901Smckusick struct sdst *stp; 3190*53901Smckusick struct scsi uscsi; 3191*53901Smckusick int error; 3192*53901Smckusick int i; 3193*53901Smckusick int s; 3194*53901Smckusick int tstatus; 3195*53901Smckusick char *p; 3196*53901Smckusick int blkno, count; 3197*53901Smckusick 3198*53901Smckusick unit = dev2unit(dev); 3199*53901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) 3200*53901Smckusick return (ENXIO); 3201*53901Smckusick 3202*53901Smckusick slave = ii->ii_slave; 3203*53901Smckusick ctlr = ii->ii_ctlr; 3204*53901Smckusick sdc = &sdc_softc[ctlr]; 3205*53901Smckusick sdd = &sdd_softc[unit]; 3206*53901Smckusick sc = &uscsi; 3207*53901Smckusick 3208*53901Smckusick error = 0; 3209*53901Smckusick switch (cmd) { 3210*53901Smckusick 3211*53901Smckusick case DIOCWLABEL: 3212*53901Smckusick if (*(int *)data & SD_F_ENW) 3213*53901Smckusick ii->ii_flags |= SD_F_ENW; 3214*53901Smckusick else 3215*53901Smckusick ii->ii_flags &= ~SD_F_ENW; 3216*53901Smckusick break; 3217*53901Smckusick 3218*53901Smckusick case DIOCGDINFO: 3219*53901Smckusick *(struct disklabel *)data = sdlabel[unit]; 3220*53901Smckusick break; 3221*53901Smckusick 3222*53901Smckusick case DIOCSDINFO: 3223*53901Smckusick sdlabel[unit] = *(struct disklabel *)data; 3224*53901Smckusick disklabel2sdst(unit, &sdlabel[unit], &sdstdrv[unit]); 3225*53901Smckusick break; 3226*53901Smckusick 3227*53901Smckusick case DIOCWDINFO: 3228*53901Smckusick case DKIOCRGEOM: 3229*53901Smckusick switch (cmd) { 3230*53901Smckusick case DKIOCRGEOM: 3231*53901Smckusick st = &sdstdrv[unit]; 3232*53901Smckusick sdi = &sddevinfo[ii->ii_type]; 3233*53901Smckusick stp = sdi->sdstp; 3234*53901Smckusick 3235*53901Smckusick st->ncyl = stp->ncyl; /* # cylinders / drive */ 3236*53901Smckusick st->ntrak = stp->ntrak; /* # tracks / cylinder */ 3237*53901Smckusick st->nsect = stp->nsect; /* # sectors / track */ 3238*53901Smckusick st->rps = stp->rps; /* # revolutions / second */ 3239*53901Smckusick 3240*53901Smckusick sdst2disklabel(unit, st, &sdlabel[unit]); 3241*53901Smckusick 3242*53901Smckusick if (*(int *)data == RGEOM_SDINFO) 3243*53901Smckusick goto done; 3244*53901Smckusick 3245*53901Smckusick break; 3246*53901Smckusick 3247*53901Smckusick case DIOCWDINFO: 3248*53901Smckusick sdlabel[unit] = *(struct disklabel *)data; 3249*53901Smckusick 3250*53901Smckusick break; 3251*53901Smckusick } 3252*53901Smckusick 3253*53901Smckusick /* 3254*53901Smckusick * Common code for DIOCWDINFO and DKIOCRGEOM 3255*53901Smckusick */ 3256*53901Smckusick 3257*53901Smckusick /**** READ sector 0 ****/ 3258*53901Smckusick /* 3259*53901Smckusick * LOCK sdtmp buffer 3260*53901Smckusick */ 3261*53901Smckusick s = splclock(); 3262*53901Smckusick while (sdtmp_stat & B_BUSY) { 3263*53901Smckusick sdtmp_stat |= B_WANTED; 3264*53901Smckusick sleep((caddr_t)sdtmp, PRIBIO); 3265*53901Smckusick } 3266*53901Smckusick sdtmp_stat |= B_BUSY; 3267*53901Smckusick splx(s); 3268*53901Smckusick 3269*53901Smckusick bzero(sdtmp, DEV_BSIZE); 3270*53901Smckusick 3271*53901Smckusick if ((sdd->sdd_flags & SDDF_NONFMT) == 0) { 3272*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 3273*53901Smckusick uscsi.sc_cpoint = sdtmp; 3274*53901Smckusick uscsi.sc_ctrnscnt = DEV_BSIZE; 3275*53901Smckusick uscsi.sc_opcode = SCOP_READ; 3276*53901Smckusick uscsi.sc_lad = 0; 3277*53901Smckusick uscsi.sc_count = 1; 3278*53901Smckusick error = sdcmd(dev, &uscsi); 3279*53901Smckusick } else { 3280*53901Smckusick error = EIO; 3281*53901Smckusick } 3282*53901Smckusick 3283*53901Smckusick if (error) { 3284*53901Smckusick /* 3285*53901Smckusick * UNLOCK sdtmp buffer 3286*53901Smckusick */ 3287*53901Smckusick s = splclock(); 3288*53901Smckusick if (sdtmp_stat & B_WANTED) 3289*53901Smckusick wakeup((caddr_t)sdtmp); 3290*53901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 3291*53901Smckusick splx(s); 3292*53901Smckusick 3293*53901Smckusick break; 3294*53901Smckusick } 3295*53901Smckusick 3296*53901Smckusick *(struct disklabel *)(sdtmp + LABELOFFSET) = sdlabel[unit]; 3297*53901Smckusick disklabel2diskinfo(unit, &sdlabel[unit], 3298*53901Smckusick &((struct firstsector *)sdtmp)->diskinfo); 3299*53901Smckusick 3300*53901Smckusick /**** WRITE sector 0 ****/ 3301*53901Smckusick 3302*53901Smckusick if (error == 0) { 3303*53901Smckusick if ((sdd->sdd_flags & SDDF_NONFMT) == 0) { 3304*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 3305*53901Smckusick uscsi.sc_cpoint = sdtmp; 3306*53901Smckusick uscsi.sc_ctrnscnt = DEV_BSIZE; 3307*53901Smckusick uscsi.sc_opcode = SCOP_WRITE; 3308*53901Smckusick 3309*53901Smckusick uscsi.sc_lad = 0; 3310*53901Smckusick uscsi.sc_count = 1; 3311*53901Smckusick 3312*53901Smckusick error = sdcmd(dev, &uscsi); 3313*53901Smckusick } else 3314*53901Smckusick error = EIO; 3315*53901Smckusick } 3316*53901Smckusick 3317*53901Smckusick /* 3318*53901Smckusick * UNLOCK sdtmp buffer 3319*53901Smckusick */ 3320*53901Smckusick s = splclock(); 3321*53901Smckusick if (sdtmp_stat & B_WANTED) 3322*53901Smckusick wakeup((caddr_t)sdtmp); 3323*53901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 3324*53901Smckusick splx(s); 3325*53901Smckusick 3326*53901Smckusick disklabel2sdst(unit, &sdlabel[unit], &sdstdrv[unit]); 3327*53901Smckusick 3328*53901Smckusick break; 3329*53901Smckusick 3330*53901Smckusick case DKIOCGGEOM: 3331*53901Smckusick st = &sdstdrv[unit]; 3332*53901Smckusick di = (struct dkst *)data; 3333*53901Smckusick 3334*53901Smckusick di->dks_ncyl = st->ncyl; /* # cylinders / drive */ 3335*53901Smckusick di->dks_ntrak = st->ntrak; /* # tracks / cylinder */ 3336*53901Smckusick di->dks_nsect = st->nsect; /* # sectors / track */ 3337*53901Smckusick di->dks_rps = st->rps; /* # revolutions / second */ 3338*53901Smckusick 3339*53901Smckusick break; 3340*53901Smckusick 3341*53901Smckusick case DKIOCSGEOM: 3342*53901Smckusick st = &sdstdrv[unit]; 3343*53901Smckusick di = (struct dkst *)data; 3344*53901Smckusick 3345*53901Smckusick st->ncyl = di->dks_ncyl; /* # cylinders / drive */ 3346*53901Smckusick st->ntrak = di->dks_ntrak; /* # tracks / cylinder */ 3347*53901Smckusick st->nsect = di->dks_nsect; /* # sectors / track */ 3348*53901Smckusick st->rps = di->dks_rps; /* # revolutions / second */ 3349*53901Smckusick 3350*53901Smckusick sdst2disklabel(unit, st, &sdlabel[unit]); 3351*53901Smckusick break; 3352*53901Smckusick 3353*53901Smckusick case DKIOCGPART: 3354*53901Smckusick case DKIOCSPART: 3355*53901Smckusick /* 3356*53901Smckusick * partition information 3357*53901Smckusick */ 3358*53901Smckusick st = &sdstdrv[unit]; 3359*53901Smckusick pi = (struct Partinfo *)data; 3360*53901Smckusick 3361*53901Smckusick if (cmd == DKIOCGPART) { 3362*53901Smckusick pi->dp_nblocks = st->sizes[dev2part(dev)].sd_nblocks; 3363*53901Smckusick pi->dp_blkoff = st->sizes[dev2part(dev)].sd_blkoff; 3364*53901Smckusick } else { 3365*53901Smckusick st->sizes[dev2part(dev)].sd_nblocks = pi->dp_nblocks; 3366*53901Smckusick st->sizes[dev2part(dev)].sd_blkoff = pi->dp_blkoff; 3367*53901Smckusick 3368*53901Smckusick sdst2disklabel(unit, st, &sdlabel[unit]); 3369*53901Smckusick } 3370*53901Smckusick break; 3371*53901Smckusick 3372*53901Smckusick case DKIOCGUNIT: 3373*53901Smckusick *(int *)data = slave; 3374*53901Smckusick break; 3375*53901Smckusick 3376*53901Smckusick case DKIOCGCHAN: 3377*53901Smckusick *(int *)data = ii->ii_intr; 3378*53901Smckusick break; 3379*53901Smckusick 3380*53901Smckusick case DKIOCSEEK: 3381*53901Smckusick scinit(sc, slave, sdd->sdd_sectsize); 3382*53901Smckusick sc->sc_opcode = SCOP_SEEK; 3383*53901Smckusick sc->sc_lad = *(int *)data; 3384*53901Smckusick 3385*53901Smckusick (void) sdcmd(dev, sc); 3386*53901Smckusick tstatus = sc->sc_tstatus & TGSTMASK; 3387*53901Smckusick if ((sc->sc_istatus != INST_EP) || (tstatus != TGST_GOOD)) 3388*53901Smckusick error = ESPIPE; 3389*53901Smckusick break; 3390*53901Smckusick 3391*53901Smckusick case DKIOCRSEC0: 3392*53901Smckusick case DKIOCRBOOT1: 3393*53901Smckusick case DKIOCRBOOT: 3394*53901Smckusick if (sdd->sdd_flags & SDDF_NONFMT) { 3395*53901Smckusick error = EIO; 3396*53901Smckusick break; 3397*53901Smckusick } 3398*53901Smckusick switch (cmd) { 3399*53901Smckusick 3400*53901Smckusick case DKIOCRSEC0: 3401*53901Smckusick blkno = 0; 3402*53901Smckusick count = 1; 3403*53901Smckusick break; 3404*53901Smckusick 3405*53901Smckusick case DKIOCRBOOT1: 3406*53901Smckusick blkno = 1; 3407*53901Smckusick count = 15; 3408*53901Smckusick break; 3409*53901Smckusick 3410*53901Smckusick default: 3411*53901Smckusick blkno = 0; 3412*53901Smckusick count = 16; 3413*53901Smckusick } 3414*53901Smckusick p = (char *)*(int *)data; 3415*53901Smckusick for (i = 0; !error && i < count; i++) { 3416*53901Smckusick s = splclock(); 3417*53901Smckusick while (sdtmp_stat & B_BUSY) { 3418*53901Smckusick sdtmp_stat |= B_WANTED; 3419*53901Smckusick sleep((caddr_t)sdtmp, PRIBIO); 3420*53901Smckusick } 3421*53901Smckusick sdtmp_stat |= B_BUSY; 3422*53901Smckusick splx(s); 3423*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 3424*53901Smckusick uscsi.sc_cpoint = sdtmp; 3425*53901Smckusick uscsi.sc_ctrnscnt = DEV_BSIZE; 3426*53901Smckusick uscsi.sc_opcode = SCOP_READ; 3427*53901Smckusick uscsi.sc_lad = blkno; 3428*53901Smckusick uscsi.sc_count = 1; 3429*53901Smckusick if (error = sdcmd(dev, &uscsi)) 3430*53901Smckusick goto dkior_done; 3431*53901Smckusick if (error = copyout(sdtmp, p, DEV_BSIZE)) 3432*53901Smckusick goto dkior_done; 3433*53901Smckusick blkno++; 3434*53901Smckusick p += DEV_BSIZE; 3435*53901Smckusick 3436*53901Smckusick dkior_done: 3437*53901Smckusick s = splclock(); 3438*53901Smckusick if (sdtmp_stat & B_WANTED) 3439*53901Smckusick wakeup((caddr_t)sdtmp); 3440*53901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 3441*53901Smckusick splx(s); 3442*53901Smckusick } 3443*53901Smckusick break; 3444*53901Smckusick 3445*53901Smckusick case DKIOCWSEC0: 3446*53901Smckusick case DKIOCWBOOT1: 3447*53901Smckusick case DKIOCWBOOT: 3448*53901Smckusick if (sdd->sdd_flags & SDDF_NONFMT) { 3449*53901Smckusick error = EIO; 3450*53901Smckusick break; 3451*53901Smckusick } 3452*53901Smckusick switch (cmd) { 3453*53901Smckusick 3454*53901Smckusick case DKIOCWSEC0: 3455*53901Smckusick blkno = 0; 3456*53901Smckusick count = 1; 3457*53901Smckusick break; 3458*53901Smckusick 3459*53901Smckusick case DKIOCWBOOT1: 3460*53901Smckusick blkno = 1; 3461*53901Smckusick count = 15; 3462*53901Smckusick break; 3463*53901Smckusick 3464*53901Smckusick default: 3465*53901Smckusick blkno = 0; 3466*53901Smckusick count = 16; 3467*53901Smckusick } 3468*53901Smckusick p = (char *)*(int *)data; 3469*53901Smckusick for (i = 0; !error && i < count; i++) { 3470*53901Smckusick s = splclock(); 3471*53901Smckusick while (sdtmp_stat & B_BUSY) { 3472*53901Smckusick sdtmp_stat |= B_WANTED; 3473*53901Smckusick sleep(sdtmp, PRIBIO); 3474*53901Smckusick } 3475*53901Smckusick sdtmp_stat |= B_BUSY; 3476*53901Smckusick splx(s); 3477*53901Smckusick if (error = copyin(p, sdtmp, DEV_BSIZE)) 3478*53901Smckusick goto dkiow_done; 3479*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 3480*53901Smckusick uscsi.sc_cpoint = sdtmp; 3481*53901Smckusick uscsi.sc_ctrnscnt = DEV_BSIZE; 3482*53901Smckusick uscsi.sc_opcode = SCOP_WRITE; 3483*53901Smckusick uscsi.sc_lad = blkno; 3484*53901Smckusick uscsi.sc_count = 1; 3485*53901Smckusick if (error = sdcmd(dev, &uscsi)) 3486*53901Smckusick goto dkiow_done; 3487*53901Smckusick blkno++; 3488*53901Smckusick p += DEV_BSIZE; 3489*53901Smckusick 3490*53901Smckusick dkiow_done: 3491*53901Smckusick s = splclock(); 3492*53901Smckusick if (sdtmp_stat & B_WANTED) 3493*53901Smckusick wakeup(sdtmp); 3494*53901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 3495*53901Smckusick splx(s); 3496*53901Smckusick } 3497*53901Smckusick break; 3498*53901Smckusick 3499*53901Smckusick case SDIOC_PRVRMV: 3500*53901Smckusick case SDIOC_ALWRMV: 3501*53901Smckusick /* 3502*53901Smckusick * prevent/allow medium removal 3503*53901Smckusick */ 3504*53901Smckusick scinit(sc, ii->ii_slave, sdd->sdd_sectsize); 3505*53901Smckusick sc->sc_opcode = SCOP_MEDRMV; 3506*53901Smckusick sc->sc_count = (cmd==SDIOC_PRVRMV)? SDRMV_PREV : SDRMV_ALLOW; 3507*53901Smckusick if (cmd == SDIOC_PRVRMV) 3508*53901Smckusick sdd->sdd_flags |= SDDF_INHRMV; 3509*53901Smckusick else 3510*53901Smckusick sdd->sdd_flags &= ~SDDF_INHRMV; 3511*53901Smckusick 3512*53901Smckusick error = sdcmd(dev, sc); 3513*53901Smckusick break; 3514*53901Smckusick 3515*53901Smckusick case SDIOC_SXUSE: 3516*53901Smckusick if (isalone(unit) != ONLY_ONE) 3517*53901Smckusick return (EBUSY); 3518*53901Smckusick sdd->sdd_flags |= SDDF_XUSE; 3519*53901Smckusick break; 3520*53901Smckusick 3521*53901Smckusick case SDIOC_RXUSE: 3522*53901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 3523*53901Smckusick break; 3524*53901Smckusick 3525*53901Smckusick case SDIOC_ERSON: 3526*53901Smckusick sdd->sdd_flags &= ~SDDF_ERASEOFF; 3527*53901Smckusick break; 3528*53901Smckusick 3529*53901Smckusick case SDIOC_ERSOFF: 3530*53901Smckusick if ((sdd->sdd_flags & SDDF_XUSE) != 0) 3531*53901Smckusick return (EBUSY); 3532*53901Smckusick sdd->sdd_flags |= SDDF_ERASEOFF; 3533*53901Smckusick sdd->sdd_flags &= ~SDDF_NONFMT; 3534*53901Smckusick break; 3535*53901Smckusick 3536*53901Smckusick case SDIOC_FORMAT: 3537*53901Smckusick /* 3538*53901Smckusick * format unit 3539*53901Smckusick */ 3540*53901Smckusick if ((flag & FWRITE) == 0) 3541*53901Smckusick return (EINVAL); 3542*53901Smckusick if (isalone(unit) != ONLY_ONE) 3543*53901Smckusick return (EBUSY); 3544*53901Smckusick sdd->sdd_flags |= SDDF_XUSE; 3545*53901Smckusick sdd->sdd_flags &= ~(SDDF_NONFMT|SDDF_FMTDONE|SDDF_SAMEDSK); 3546*53901Smckusick scinit(sc, ii->ii_slave, sdd->sdd_sectsize); 3547*53901Smckusick sc->sc_ctrnscnt = 4; 3548*53901Smckusick sc->sc_opcode = SCOP_FMT; 3549*53901Smckusick 3550*53901Smckusick sc->sc_lad = ((sddevinfo[ii->ii_type].fmt_opts & FMT_DLFMT) 3551*53901Smckusick | SDF_FMTDAT) << 16; 3552*53901Smckusick 3553*53901Smckusick switch (sddevinfo[ii->ii_type].type) { 3554*53901Smckusick 3555*53901Smckusick case SMO_S501: 3556*53901Smckusick case SMO_S501_ISO: 3557*53901Smckusick case SMO_S501_ISO2: 3558*53901Smckusick sc->sc_lad |= ((SDF_MKCDA|SDF_MKPLST) << 8); 3559*53901Smckusick break; 3560*53901Smckusick 3561*53901Smckusick default: 3562*53901Smckusick break; 3563*53901Smckusick } 3564*53901Smckusick 3565*53901Smckusick { 3566*53901Smckusick struct fmt_data *fdata = (struct fmt_data *)data; 3567*53901Smckusick 3568*53901Smckusick error = copyin((caddr_t)fdata->dlh, sc->sc_param, 4); 3569*53901Smckusick if (error != 0) { 3570*53901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 3571*53901Smckusick break; 3572*53901Smckusick } 3573*53901Smckusick if (fdata->noglist) 3574*53901Smckusick sc->sc_lad |= (SDF_CMPLST<<16); 3575*53901Smckusick } 3576*53901Smckusick 3577*53901Smckusick if (sdd->sdd_flags & SDDF_ERASEOFF) 3578*53901Smckusick sc->sc_ctrl = 0x40; 3579*53901Smckusick 3580*53901Smckusick error = sdcmd(dev, sc); 3581*53901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 3582*53901Smckusick break; 3583*53901Smckusick 3584*53901Smckusick case SDIOC_FORMAT2: 3585*53901Smckusick /* 3586*53901Smckusick * format unit 3587*53901Smckusick */ 3588*53901Smckusick if ((flag & FWRITE) == 0) 3589*53901Smckusick return (EINVAL); 3590*53901Smckusick if (isalone(unit) != ONLY_ONE) 3591*53901Smckusick return (EBUSY); 3592*53901Smckusick sdd->sdd_flags |= SDDF_XUSE; 3593*53901Smckusick sdd->sdd_flags &= ~(SDDF_NONFMT|SDDF_FMTDONE|SDDF_SAMEDSK); 3594*53901Smckusick 3595*53901Smckusick scu = (struct sc_ureq *)data; 3596*53901Smckusick error = sd_scu_exec(dev, scu, sc); 3597*53901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 3598*53901Smckusick break; 3599*53901Smckusick 3600*53901Smckusick case SDIOC_GSTOPT: 3601*53901Smckusick case SDIOC_SSTOPT: 3602*53901Smckusick /* 3603*53901Smckusick * get/set stop-unit timer 3604*53901Smckusick */ 3605*53901Smckusick if (cmd == SDIOC_GSTOPT) 3606*53901Smckusick *(int *)data = sdd->sdd_stoptime; 3607*53901Smckusick else { 3608*53901Smckusick if (*(int *)data == 0) 3609*53901Smckusick return (EINVAL); 3610*53901Smckusick sdd->sdd_stoptime = *(int *)data; 3611*53901Smckusick } 3612*53901Smckusick break; 3613*53901Smckusick 3614*53901Smckusick case SDIOC_SEJECT: 3615*53901Smckusick /* 3616*53901Smckusick * set auto eject flag 3617*53901Smckusick */ 3618*53901Smckusick sdd->sdd_flags |= SDDF_REQ_EJECT; 3619*53901Smckusick break; 3620*53901Smckusick 3621*53901Smckusick case SDIOC_GFLAGS: 3622*53901Smckusick /* 3623*53901Smckusick * get ii->ii_flags 3624*53901Smckusick */ 3625*53901Smckusick *(int *)data = ii->ii_flags; 3626*53901Smckusick break; 3627*53901Smckusick 3628*53901Smckusick case SDIOC_SFLAGS: 3629*53901Smckusick /* 3630*53901Smckusick * set ii->ii_flags 3631*53901Smckusick */ 3632*53901Smckusick ii->ii_flags = *(int *)data; 3633*53901Smckusick break; 3634*53901Smckusick 3635*53901Smckusick case SDIOC_RASBLK: 3636*53901Smckusick /* 3637*53901Smckusick * reassign block 3638*53901Smckusick */ 3639*53901Smckusick { 3640*53901Smckusick struct sc_rab *sca = (struct sc_rab *)sc->sc_param; 3641*53901Smckusick 3642*53901Smckusick scinit(sc, ii->ii_slave, sdd->sdd_sectsize); 3643*53901Smckusick sc->sc_opcode = SCOP_RASBLK; 3644*53901Smckusick sc->sc_ctrnscnt = 8; 3645*53901Smckusick 3646*53901Smckusick sca->sca_dllen = 4; 3647*53901Smckusick sca->sca_dlad[0] = *(int *)data; 3648*53901Smckusick 3649*53901Smckusick error = sdcmd(dev, sc); 3650*53901Smckusick } 3651*53901Smckusick break; 3652*53901Smckusick 3653*53901Smckusick case SDIOC_GNICKNAME: 3654*53901Smckusick { 3655*53901Smckusick int len; 3656*53901Smckusick 3657*53901Smckusick len = strlen(sddevinfo[ii->ii_type].call_name); 3658*53901Smckusick 3659*53901Smckusick if (len > IOCPARM_MASK) 3660*53901Smckusick len = IOCPARM_MASK; 3661*53901Smckusick 3662*53901Smckusick error = copyout( 3663*53901Smckusick (caddr_t) sddevinfo[ii->ii_type].call_name, 3664*53901Smckusick (caddr_t) *(int *)data, 3665*53901Smckusick len); 3666*53901Smckusick } 3667*53901Smckusick break; 3668*53901Smckusick 3669*53901Smckusick case SDIOC_GTYPINDEX: 3670*53901Smckusick *(int *)data = (int)ii->ii_type; 3671*53901Smckusick break; 3672*53901Smckusick 3673*53901Smckusick #ifdef SDIOC_SSYNCPARAM 3674*53901Smckusick case SDIOC_SSYNCPARAM: 3675*53901Smckusick { 3676*53901Smckusick struct sync_param *syncp; 3677*53901Smckusick 3678*53901Smckusick syncp = (struct sync_param *)data; 3679*53901Smckusick scinit(sc, ii->ii_slave, sdd->sdd_sectsize); 3680*53901Smckusick sc->sc_opcode = SCOP_TST; 3681*53901Smckusick sc->sc_message = MSG_EXTND; /* extended message */ 3682*53901Smckusick sc->sc_param[0] = MSG_EXTND; 3683*53901Smckusick sc->sc_param[1] = 0x03; 3684*53901Smckusick sc->sc_param[2] = 0x01; /* synchronous transfer */ 3685*53901Smckusick sc->sc_param[3] = syncp->tr_period; /* transfer period */ 3686*53901Smckusick sc->sc_param[4] = syncp->tr_offset; /* REQ offset */ 3687*53901Smckusick 3688*53901Smckusick (void) sdcmd(dev, sc); 3689*53901Smckusick 3690*53901Smckusick syncp = &sd_sync_param[unit]; 3691*53901Smckusick syncp->tr_period = sc->sc_param[3]; 3692*53901Smckusick syncp->tr_offset = sc->sc_param[4]; 3693*53901Smckusick 3694*53901Smckusick if (syncp->tr_offset) 3695*53901Smckusick sdd->sdd_flags |= SDDF_SYNCTR; 3696*53901Smckusick else 3697*53901Smckusick sdd->sdd_flags &= ~SDDF_SYNCTR; 3698*53901Smckusick } 3699*53901Smckusick break; 3700*53901Smckusick 3701*53901Smckusick case SDIOC_GSYNCPARAM: 3702*53901Smckusick { 3703*53901Smckusick struct sync_param *syncp = (struct sync_param *)data; 3704*53901Smckusick 3705*53901Smckusick syncp->tr_period = sd_sync_param[unit].tr_period; 3706*53901Smckusick syncp->tr_offset = sd_sync_param[unit].tr_offset; 3707*53901Smckusick } 3708*53901Smckusick break; 3709*53901Smckusick #endif /* SDIOC_SSYNCPARAM */ 3710*53901Smckusick 3711*53901Smckusick case MTIOCTOP: 3712*53901Smckusick { 3713*53901Smckusick register struct mtop *mtop = (struct mtop *)data; 3714*53901Smckusick register int lba; 3715*53901Smckusick int rest; 3716*53901Smckusick int blength; 3717*53901Smckusick 3718*53901Smckusick switch (mtop->mt_op) { 3719*53901Smckusick 3720*53901Smckusick case MTOFFL: 3721*53901Smckusick /* 3722*53901Smckusick * set auto eject flag 3723*53901Smckusick */ 3724*53901Smckusick sdd->sdd_flags |= SDDF_REQ_EJECT; 3725*53901Smckusick break; 3726*53901Smckusick 3727*53901Smckusick #ifdef MTERASE 3728*53901Smckusick case MTERASE: 3729*53901Smckusick if (isalone(unit) != ONLY_ONE) 3730*53901Smckusick return (EBUSY); 3731*53901Smckusick sdd->sdd_flags |= SDDF_XUSE; 3732*53901Smckusick st = &sdstdrv[unit]; 3733*53901Smckusick /* 3734*53901Smckusick * MO disk erase 3735*53901Smckusick * block 0 to end (C partition) 3736*53901Smckusick */ 3737*53901Smckusick lba = 0; 3738*53901Smckusick rest = sdd->sdd_nsect; /* C part size */ 3739*53901Smckusick while (rest > 0) { 3740*53901Smckusick blength = (rest > MAXBL)? MAXBL : rest; 3741*53901Smckusick scinit(sc, ii->ii_slave, 3742*53901Smckusick sdd->sdd_sectsize); 3743*53901Smckusick sc->sc_opcode = SCOP_MOERASE; 3744*53901Smckusick sc->sc_lad = lba; 3745*53901Smckusick sc->sc_count = (blength % MAXBL); 3746*53901Smckusick 3747*53901Smckusick (void) sdcmd(dev, sc); 3748*53901Smckusick lba += blength; 3749*53901Smckusick rest -= blength; 3750*53901Smckusick } 3751*53901Smckusick sdd->sdd_flags &= ~SDDF_XUSE; 3752*53901Smckusick break; 3753*53901Smckusick #endif /* MTERASE */ 3754*53901Smckusick 3755*53901Smckusick default: 3756*53901Smckusick return (EINVAL); 3757*53901Smckusick } 3758*53901Smckusick } 3759*53901Smckusick break; 3760*53901Smckusick 3761*53901Smckusick case SCSIIOCCMD: 3762*53901Smckusick scu = (struct sc_ureq *)data; 3763*53901Smckusick if ((scu->scu_count > 0) && scu->scu_addr) { 3764*53901Smckusick if (useracc(scu->scu_addr, scu->scu_count, B_WRITE) 3765*53901Smckusick == NULL) { 3766*53901Smckusick error = EFAULT; 3767*53901Smckusick break; 3768*53901Smckusick } 3769*53901Smckusick } 3770*53901Smckusick error = sd_scu_exec(dev, scu, sc); 3771*53901Smckusick break; 3772*53901Smckusick 3773*53901Smckusick 3774*53901Smckusick case SDIOC_INQUIRY: 3775*53901Smckusick /* 3776*53901Smckusick * LOCK sdtmp buffer 3777*53901Smckusick */ 3778*53901Smckusick s = splclock(); 3779*53901Smckusick while (sdtmp_stat & B_BUSY) { 3780*53901Smckusick sdtmp_stat |= B_WANTED; 3781*53901Smckusick sleep((caddr_t)sdtmp, PRIBIO); 3782*53901Smckusick } 3783*53901Smckusick sdtmp_stat |= B_BUSY; 3784*53901Smckusick splx(s); 3785*53901Smckusick 3786*53901Smckusick bzero((caddr_t)sdtmp, sizeof(struct sc_inq)); 3787*53901Smckusick scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 3788*53901Smckusick uscsi.sc_cpoint = sdtmp; 3789*53901Smckusick uscsi.sc_ctrnscnt = sizeof(struct sc_inq); 3790*53901Smckusick uscsi.sc_opcode = SCOP_INQUIRY; 3791*53901Smckusick uscsi.sc_count = sizeof(struct sc_inq); 3792*53901Smckusick 3793*53901Smckusick if ((error = sdcmd(dev, &uscsi)) == 0) 3794*53901Smckusick bcopy((caddr_t)sdtmp, data, sizeof(struct sc_inq)); 3795*53901Smckusick /* 3796*53901Smckusick * UNLOCK open 3797*53901Smckusick */ 3798*53901Smckusick s = splclock(); 3799*53901Smckusick if (sdtmp_stat & B_WANTED) 3800*53901Smckusick wakeup((caddr_t)sdtmp); 3801*53901Smckusick sdtmp_stat &= ~(B_BUSY|B_WANTED); 3802*53901Smckusick splx(s); 3803*53901Smckusick break; 3804*53901Smckusick 3805*53901Smckusick 3806*53901Smckusick case SCSIIOCGTIMEO: 3807*53901Smckusick *(int *)data = sdc->sdc_timeo; 3808*53901Smckusick break; 3809*53901Smckusick 3810*53901Smckusick case SCSIIOCSTIMEO: 3811*53901Smckusick if (*(int *)data == 0) 3812*53901Smckusick return (EINVAL); 3813*53901Smckusick sdc->sdc_timeo = *(int *)data; 3814*53901Smckusick sdc->sdc_wticks = 0; 3815*53901Smckusick break; 3816*53901Smckusick 3817*53901Smckusick default: 3818*53901Smckusick error = EINVAL; 3819*53901Smckusick break; 3820*53901Smckusick } 3821*53901Smckusick 3822*53901Smckusick done: 3823*53901Smckusick return (error); 3824*53901Smckusick } 3825*53901Smckusick 3826*53901Smckusick static 3827*53901Smckusick sd_scu_exec(dev, scu, sc) 3828*53901Smckusick dev_t dev; 3829*53901Smckusick register struct sc_ureq *scu; 3830*53901Smckusick register struct scsi *sc; 3831*53901Smckusick { 3832*53901Smckusick struct sdd_softc *sdd; 3833*53901Smckusick int error; 3834*53901Smckusick 3835*53901Smckusick sdd = &sdd_softc[dev2unit(dev)]; 3836*53901Smckusick 3837*53901Smckusick if (((scu->scu_identify & MSG_IDENT) == 0) 3838*53901Smckusick || (scu->scu_identify & ~(MSG_IDENT|IDT_DISCON|IDT_DRMASK)) 3839*53901Smckusick || (scu->scu_addr && (scu->scu_bytesec == 0))) { 3840*53901Smckusick return (EINVAL); 3841*53901Smckusick } 3842*53901Smckusick 3843*53901Smckusick bzero((caddr_t)sc, sizeof(struct scsi)); 3844*53901Smckusick sc->sc_tstatus = scu->scu_tstatus; 3845*53901Smckusick sc->sc_identify = scu->scu_identify; 3846*53901Smckusick sc->sc_message = scu->scu_message; 3847*53901Smckusick sc->sc_bytesec = scu->scu_bytesec; 3848*53901Smckusick sc->sc_cpoint = scu->scu_addr; 3849*53901Smckusick sc->sc_ctrnscnt = scu->scu_count; 3850*53901Smckusick bcopy((caddr_t)scu->scu_cdb, &sc->sc_cdb, sizeof(sc->sc_cdb)); 3851*53901Smckusick 3852*53901Smckusick bcopy((caddr_t)scu->scu_param, (caddr_t)sc->sc_param, 3853*53901Smckusick sizeof(sc->sc_param)); 3854*53901Smckusick 3855*53901Smckusick sdd->sdd_flags |= SDDF_SKIPCHECK; 3856*53901Smckusick error = sdcmd(dev, sc); 3857*53901Smckusick sdd->sdd_flags &= ~SDDF_SKIPCHECK; 3858*53901Smckusick 3859*53901Smckusick scu->scu_istatus = sc->sc_istatus; 3860*53901Smckusick scu->scu_tstatus = sc->sc_tstatus; 3861*53901Smckusick scu->scu_message = sc->sc_message; 3862*53901Smckusick bcopy((caddr_t)sc->sc_param, (caddr_t)scu->scu_param, 3863*53901Smckusick sizeof(sc->sc_param)); 3864*53901Smckusick return (error); 3865*53901Smckusick } 3866*53901Smckusick 3867*53901Smckusick /*ARGSUSED*/ 3868*53901Smckusick sddump(dev) 3869*53901Smckusick dev_t dev; 3870*53901Smckusick { 3871*53901Smckusick return (ENXIO); 3872*53901Smckusick } 3873*53901Smckusick 3874*53901Smckusick sdsize(dev) 3875*53901Smckusick register dev_t dev; 3876*53901Smckusick { 3877*53901Smckusick register struct iop/**/_device *ii; 3878*53901Smckusick register struct sdd_softc *sdd; 3879*53901Smckusick register struct sdst *st; 3880*53901Smckusick register int unit; 3881*53901Smckusick int i; 3882*53901Smckusick 3883*53901Smckusick unit = dev2unit(dev); 3884*53901Smckusick if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0) 3885*53901Smckusick return (-1); 3886*53901Smckusick 3887*53901Smckusick sdd = &sdd_softc[unit]; 3888*53901Smckusick switch (sdc_softc[ii->ii_ctlr].sdc_firmware & SDCFW_DEVMASK) { 3889*53901Smckusick 3890*53901Smckusick case SDCFW_HD: /* Hard Disk */ 3891*53901Smckusick st = &sdstdrv[unit]; 3892*53901Smckusick break; 3893*53901Smckusick 3894*53901Smckusick case SDCFW_MO: /* MO only */ 3895*53901Smckusick if ((sdd->sdd_flags & SDDF_SAMEDSK) == SDDF_DSKCHGD) { 3896*53901Smckusick /* 3897*53901Smckusick * read partition information, 3898*53901Smckusick * and set up sdstdrv[unit] 3899*53901Smckusick */ 3900*53901Smckusick if (sd_b_open(dev, FREAD|FWRITE) != 0) { 3901*53901Smckusick /* 3902*53901Smckusick * block device open error 3903*53901Smckusick */ 3904*53901Smckusick return (-1); 3905*53901Smckusick } else { 3906*53901Smckusick /* 3907*53901Smckusick * use disk partition information 3908*53901Smckusick */ 3909*53901Smckusick st = &sdstdrv[unit]; 3910*53901Smckusick if (isalone(unit) == ONLY_ONE) 3911*53901Smckusick sd_b_close(dev, 0); 3912*53901Smckusick } 3913*53901Smckusick } else if (sdd->sdd_flags & SDDF_NONFMT) { 3914*53901Smckusick /* 3915*53901Smckusick * medium is not initialized. 3916*53901Smckusick */ 3917*53901Smckusick return (-1); 3918*53901Smckusick } else { 3919*53901Smckusick st = &sdstdrv[unit]; 3920*53901Smckusick } 3921*53901Smckusick break; 3922*53901Smckusick 3923*53901Smckusick default: 3924*53901Smckusick /* case SDCFW_CD: */ 3925*53901Smckusick return (-1); 3926*53901Smckusick 3927*53901Smckusick } 3928*53901Smckusick 3929*53901Smckusick if (st->sizes == NULL) 3930*53901Smckusick return (-1); /* XXX */ 3931*53901Smckusick else 3932*53901Smckusick return (st->sizes[dev2part(dev)].sd_nblocks); /* XXX */ 3933*53901Smckusick } 3934*53901Smckusick 3935*53901Smckusick /* 3936*53901Smckusick * Reset driver. 3937*53901Smckusick * Cancel software state of all pending transfers, 3938*53901Smckusick * and restart all units and the controller. 3939*53901Smckusick */ 3940*53901Smckusick sdreset() 3941*53901Smckusick { 3942*53901Smckusick register struct iop/**/_ctlr *im; 3943*53901Smckusick register struct iop/**/_device *ii; 3944*53901Smckusick register struct sdc_softc *sdc; 3945*53901Smckusick register struct sdd_softc *sdd; 3946*53901Smckusick register int i; 3947*53901Smckusick register int unit; 3948*53901Smckusick 3949*53901Smckusick re_init_done = 1; 3950*53901Smckusick for (i = 0; i < nsdc; i++) { 3951*53901Smckusick im = sdminfo[i]; 3952*53901Smckusick if (im == 0) 3953*53901Smckusick continue; 3954*53901Smckusick if (im->im_alive == 0) 3955*53901Smckusick continue; 3956*53901Smckusick printf(" sdc%d: ", i); 3957*53901Smckusick sdc = &sdc_softc[i]; 3958*53901Smckusick sdc->sdc_wticks = 0; 3959*53901Smckusick 3960*53901Smckusick /* scop_init() is already called by screset() */ 3961*53901Smckusick 3962*53901Smckusick sdtmp_stat &= ~B_BUSY; 3963*53901Smckusick 3964*53901Smckusick for (unit = 0; unit < nsd; unit++) { 3965*53901Smckusick ii = sddinfo[unit]; 3966*53901Smckusick if (ii == 0) 3967*53901Smckusick continue; 3968*53901Smckusick if (ii->ii_alive == 0) 3969*53901Smckusick continue; 3970*53901Smckusick if (ii->ii_mi != im) 3971*53901Smckusick continue; 3972*53901Smckusick 3973*53901Smckusick csdbuf[unit].b_flags &= ~B_BUSY; 3974*53901Smckusick 3975*53901Smckusick sdd = &sdd_softc[unit]; 3976*53901Smckusick sdd->sdd_flags = 0; 3977*53901Smckusick 3978*53901Smckusick /* 3979*53901Smckusick * UNLOCK SCSI access 3980*53901Smckusick */ 3981*53901Smckusick sdc->sdc_firmware &= ~SDCFW_BUSY; 3982*53901Smckusick 3983*53901Smckusick if (sdslave(ii, ii->ii_addr, im->im_intr) == 0) { 3984*53901Smckusick printf("sd%d: not ready\n", ii->ii_slave); 3985*53901Smckusick continue; 3986*53901Smckusick } 3987*53901Smckusick sdattach(ii); 3988*53901Smckusick } 3989*53901Smckusick } 3990*53901Smckusick re_init_done = 2; 3991*53901Smckusick } 3992*53901Smckusick 3993*53901Smckusick int sd_long_timeout = 24 * 60 * 60; /* 24 hours */ 3994*53901Smckusick 3995*53901Smckusick #define max(a, b) (((a)>(b))?(a):(b)) 3996*53901Smckusick 3997*53901Smckusick /* 3998*53901Smckusick * Wake up every second and if interrupt is pending 3999*53901Smckusick * but nothing has happened increment a counter. 4000*53901Smckusick * If nothing happens for sdc_timeo seconds, reset the IOP 4001*53901Smckusick * and begin anew. 4002*53901Smckusick */ 4003*53901Smckusick sdwatch() 4004*53901Smckusick { 4005*53901Smckusick register struct iop/**/_ctlr *im; 4006*53901Smckusick register struct sdc_softc *sdc; 4007*53901Smckusick register int i; 4008*53901Smckusick register int unit; 4009*53901Smckusick int timeo; 4010*53901Smckusick 4011*53901Smckusick extern int Scsi_Disconnect; 4012*53901Smckusick 4013*53901Smckusick timeout(sdwatch, (caddr_t)0, hz); 4014*53901Smckusick for (i = 0; i < nsdc; i++) { 4015*53901Smckusick im = sdminfo[i]; 4016*53901Smckusick if (im == 0) 4017*53901Smckusick continue; 4018*53901Smckusick if (im->im_alive == 0) 4019*53901Smckusick continue; 4020*53901Smckusick sdc = &sdc_softc[i]; 4021*53901Smckusick 4022*53901Smckusick if (im->im_tab.b_active) 4023*53901Smckusick goto active; 4024*53901Smckusick 4025*53901Smckusick for (unit = 0; unit < nsd; unit++) 4026*53901Smckusick if (sdutab[unit].b_active && sddinfo[unit]->ii_mi == im) 4027*53901Smckusick goto active; 4028*53901Smckusick 4029*53901Smckusick sdc->sdc_wticks = 0; 4030*53901Smckusick continue; 4031*53901Smckusick active: 4032*53901Smckusick if (Scsi_Disconnect) 4033*53901Smckusick timeo = sdc->sdc_timeo; 4034*53901Smckusick else 4035*53901Smckusick timeo = max(sdc->sdc_timeo, sd_long_timeout); 4036*53901Smckusick 4037*53901Smckusick if (sdc->sdc_wticks++ >= timeo) { 4038*53901Smckusick register struct scsi *sc; 4039*53901Smckusick 4040*53901Smckusick sc = get_scsi(im->im_intr); 4041*53901Smckusick sdc->sdc_wticks = 0; 4042*53901Smckusick printf("sdc%d: lost interrupt\n", i); 4043*53901Smckusick 4044*53901Smckusick screset(im->im_intr); 4045*53901Smckusick } 4046*53901Smckusick } 4047*53901Smckusick } 4048*53901Smckusick 4049*53901Smckusick /* 4050*53901Smckusick * sdstop() is timer interrupt routine. 4051*53901Smckusick * So, can't use sleep(). 4052*53901Smckusick */ 4053*53901Smckusick sdstop() 4054*53901Smckusick { 4055*53901Smckusick register struct iop/**/_ctlr *im; 4056*53901Smckusick register struct iop/**/_device *ii; 4057*53901Smckusick register struct sdc_softc *sdc; 4058*53901Smckusick register struct sdd_softc *sdd; 4059*53901Smckusick register int unit; 4060*53901Smckusick register int intr; 4061*53901Smckusick register int i; 4062*53901Smckusick struct scsi *sc; 4063*53901Smckusick int eject_sw; 4064*53901Smckusick 4065*53901Smckusick timeout(sdstop, (caddr_t)0, hz); 4066*53901Smckusick 4067*53901Smckusick for (i = 0; i < nsdc; i++) { 4068*53901Smckusick im = sdminfo[i]; 4069*53901Smckusick if (im == 0) 4070*53901Smckusick continue; 4071*53901Smckusick if (im->im_alive == 0) 4072*53901Smckusick continue; 4073*53901Smckusick for (unit = 0; unit < nsd; unit++) { 4074*53901Smckusick if ((ii = sddinfo[unit]) == 0) 4075*53901Smckusick continue; 4076*53901Smckusick if (ii->ii_mi != im) 4077*53901Smckusick continue; 4078*53901Smckusick sdc = &sdc_softc[ii->ii_ctlr]; 4079*53901Smckusick if ((sdc->sdc_firmware & SDCFW_RMB) == 0) 4080*53901Smckusick continue; 4081*53901Smckusick intr = ii->ii_intr; 4082*53901Smckusick if (isalone(unit)) 4083*53901Smckusick continue; 4084*53901Smckusick /**********************/ 4085*53901Smckusick /* MO & CD-ROM */ 4086*53901Smckusick /**********************/ 4087*53901Smckusick /* 4088*53901Smckusick * there is no process which open the unit. 4089*53901Smckusick */ 4090*53901Smckusick sdd = &sdd_softc[unit]; 4091*53901Smckusick sc = get_scsi(intr); 4092*53901Smckusick if (sdd->sdd_start > 0) 4093*53901Smckusick sdd->sdd_start--; 4094*53901Smckusick else if (sdd->sdd_start == 0) { 4095*53901Smckusick /* 4096*53901Smckusick * Now stop the unit. 4097*53901Smckusick * check SCSI access 4098*53901Smckusick */ 4099*53901Smckusick if (sdc->sdc_firmware & SDCFW_BUSY) 4100*53901Smckusick continue; 4101*53901Smckusick sdc->sdc_firmware |= SDCFW_BUSY; 4102*53901Smckusick sdc->sdc_state |= SDCS_IOCTL|SDCS_SCUNLOCK; 4103*53901Smckusick 4104*53901Smckusick eject_sw = (sdd->sdd_flags & SDDF_REQ_EJECT) ? 4105*53901Smckusick SDSS_EJECT : SDSS_STOP; 4106*53901Smckusick scop_stst(intr, sc, ii->ii_slave, 4107*53901Smckusick SCSI_INTEN, eject_sw); 4108*53901Smckusick sdd->sdd_start = -2; 4109*53901Smckusick } 4110*53901Smckusick } 4111*53901Smckusick } 4112*53901Smckusick } 4113*53901Smckusick 4114*53901Smckusick isalone(unit) 4115*53901Smckusick register int unit; 4116*53901Smckusick { 4117*53901Smckusick register int i, n; 4118*53901Smckusick 4119*53901Smckusick n = 0; 4120*53901Smckusick for (i = 0; i < PNUM; i++) 4121*53901Smckusick n += (sd_b_openf[unit][i] + sd_c_openf[unit][i]); 4122*53901Smckusick return (n); 4123*53901Smckusick } 4124*53901Smckusick 4125*53901Smckusick /************************************************ 4126*53901Smckusick * Convert Hex and RS code table definition * 4127*53901Smckusick ************************************************/ 4128*53901Smckusick 4129*53901Smckusick #define X8_L 0x001d 4130*53901Smckusick #define X8_H 0x1d00 4131*53901Smckusick 4132*53901Smckusick 4133*53901Smckusick #define hextors(data) hxtable[(int)((data) & 0xff)] 4134*53901Smckusick #define XORMASK(code) xortable[(unsigned int)(code)] 4135*53901Smckusick 4136*53901Smckusick int hxtable[256] = { 4137*53901Smckusick 0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 4138*53901Smckusick 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, 4139*53901Smckusick 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 4140*53901Smckusick 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71, 4141*53901Smckusick 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 4142*53901Smckusick 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, 4143*53901Smckusick 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 4144*53901Smckusick 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6, 4145*53901Smckusick 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 4146*53901Smckusick 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, 4147*53901Smckusick 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 4148*53901Smckusick 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, 4149*53901Smckusick 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 4150*53901Smckusick 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d, 4151*53901Smckusick 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 4152*53901Smckusick 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, 4153*53901Smckusick 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 4154*53901Smckusick 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18, 4155*53901Smckusick 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 4156*53901Smckusick 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, 4157*53901Smckusick 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 4158*53901Smckusick 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, 4159*53901Smckusick 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 4160*53901Smckusick 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2, 4161*53901Smckusick 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 4162*53901Smckusick 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6, 4163*53901Smckusick 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 4164*53901Smckusick 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a, 4165*53901Smckusick 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 4166*53901Smckusick 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, 4167*53901Smckusick 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 4168*53901Smckusick 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf, 4169*53901Smckusick }; 4170*53901Smckusick 4171*53901Smckusick int xortable[256] = { 4172*53901Smckusick 0x00000000, 0x90910101, 0x91210201, 0x01b00300, 4173*53901Smckusick 0x92410401, 0x02d00500, 0x03600600, 0x93f10701, 4174*53901Smckusick 0x94810801, 0x04100900, 0x05a00a00, 0x95310b01, 4175*53901Smckusick 0x06c00c00, 0x96510d01, 0x97e10e01, 0x07700f00, 4176*53901Smckusick 0x99011001, 0x09901100, 0x08201200, 0x98b11301, 4177*53901Smckusick 0x0b401400, 0x9bd11501, 0x9a611601, 0x0af01700, 4178*53901Smckusick 0x0d801800, 0x9d111901, 0x9ca11a01, 0x0c301b00, 4179*53901Smckusick 0x9fc11c01, 0x0f501d00, 0x0ee01e00, 0x9e711f01, 4180*53901Smckusick 0x82012001, 0x12902100, 0x13202200, 0x83b12301, 4181*53901Smckusick 0x10402400, 0x80d12501, 0x81612601, 0x11f02700, 4182*53901Smckusick 0x16802800, 0x86112901, 0x87a12a01, 0x17302b00, 4183*53901Smckusick 0x84c12c01, 0x14502d00, 0x15e02e00, 0x85712f01, 4184*53901Smckusick 0x1b003000, 0x8b913101, 0x8a213201, 0x1ab03300, 4185*53901Smckusick 0x89413401, 0x19d03500, 0x18603600, 0x88f13701, 4186*53901Smckusick 0x8f813801, 0x1f103900, 0x1ea03a00, 0x8e313b01, 4187*53901Smckusick 0x1dc03c00, 0x8d513d01, 0x8ce13e01, 0x1c703f00, 4188*53901Smckusick 0xb4014001, 0x24904100, 0x25204200, 0xb5b14301, 4189*53901Smckusick 0x26404400, 0xb6d14501, 0xb7614601, 0x27f04700, 4190*53901Smckusick 0x20804800, 0xb0114901, 0xb1a14a01, 0x21304b00, 4191*53901Smckusick 0xb2c14c01, 0x22504d00, 0x23e04e00, 0xb3714f01, 4192*53901Smckusick 0x2d005000, 0xbd915101, 0xbc215201, 0x2cb05300, 4193*53901Smckusick 0xbf415401, 0x2fd05500, 0x2e605600, 0xbef15701, 4194*53901Smckusick 0xb9815801, 0x29105900, 0x28a05a00, 0xb8315b01, 4195*53901Smckusick 0x2bc05c00, 0xbb515d01, 0xbae15e01, 0x2a705f00, 4196*53901Smckusick 0x36006000, 0xa6916101, 0xa7216201, 0x37b06300, 4197*53901Smckusick 0xa4416401, 0x34d06500, 0x35606600, 0xa5f16701, 4198*53901Smckusick 0xa2816801, 0x32106900, 0x33a06a00, 0xa3316b01, 4199*53901Smckusick 0x30c06c00, 0xa0516d01, 0xa1e16e01, 0x31706f00, 4200*53901Smckusick 0xaf017001, 0x3f907100, 0x3e207200, 0xaeb17301, 4201*53901Smckusick 0x3d407400, 0xadd17501, 0xac617601, 0x3cf07700, 4202*53901Smckusick 0x3b807800, 0xab117901, 0xaaa17a01, 0x3a307b00, 4203*53901Smckusick 0xa9c17c01, 0x39507d00, 0x38e07e00, 0xa8717f01, 4204*53901Smckusick 0xd8018001, 0x48908100, 0x49208200, 0xd9b18301, 4205*53901Smckusick 0x4a408400, 0xdad18501, 0xdb618601, 0x4bf08700, 4206*53901Smckusick 0x4c808800, 0xdc118901, 0xdda18a01, 0x4d308b00, 4207*53901Smckusick 0xdec18c01, 0x4e508d00, 0x4fe08e00, 0xdf718f01, 4208*53901Smckusick 0x41009000, 0xd1919101, 0xd0219201, 0x40b09300, 4209*53901Smckusick 0xd3419401, 0x43d09500, 0x42609600, 0xd2f19701, 4210*53901Smckusick 0xd5819801, 0x45109900, 0x44a09a00, 0xd4319b01, 4211*53901Smckusick 0x47c09c00, 0xd7519d01, 0xd6e19e01, 0x46709f00, 4212*53901Smckusick 0x5a00a000, 0xca91a101, 0xcb21a201, 0x5bb0a300, 4213*53901Smckusick 0xc841a401, 0x58d0a500, 0x5960a600, 0xc9f1a701, 4214*53901Smckusick 0xce81a801, 0x5e10a900, 0x5fa0aa00, 0xcf31ab01, 4215*53901Smckusick 0x5cc0ac00, 0xcc51ad01, 0xcde1ae01, 0x5d70af00, 4216*53901Smckusick 0xc301b001, 0x5390b100, 0x5220b200, 0xc2b1b301, 4217*53901Smckusick 0x5140b400, 0xc1d1b501, 0xc061b601, 0x50f0b700, 4218*53901Smckusick 0x5780b800, 0xc711b901, 0xc6a1ba01, 0x5630bb00, 4219*53901Smckusick 0xc5c1bc01, 0x5550bd00, 0x54e0be00, 0xc471bf01, 4220*53901Smckusick 0x6c00c000, 0xfc91c101, 0xfd21c201, 0x6db0c300, 4221*53901Smckusick 0xfe41c401, 0x6ed0c500, 0x6f60c600, 0xfff1c701, 4222*53901Smckusick 0xf881c801, 0x6810c900, 0x69a0ca00, 0xf931cb01, 4223*53901Smckusick 0x6ac0cc00, 0xfa51cd01, 0xfbe1ce01, 0x6b70cf00, 4224*53901Smckusick 0xf501d001, 0x6590d100, 0x6420d200, 0xf4b1d301, 4225*53901Smckusick 0x6740d400, 0xf7d1d501, 0xf661d601, 0x66f0d700, 4226*53901Smckusick 0x6180d800, 0xf111d901, 0xf0a1da01, 0x6030db00, 4227*53901Smckusick 0xf3c1dc01, 0x6350dd00, 0x62e0de00, 0xf271df01, 4228*53901Smckusick 0xee01e001, 0x7e90e100, 0x7f20e200, 0xefb1e301, 4229*53901Smckusick 0x7c40e400, 0xecd1e501, 0xed61e601, 0x7df0e700, 4230*53901Smckusick 0x7a80e800, 0xea11e901, 0xeba1ea01, 0x7b30eb00, 4231*53901Smckusick 0xe8c1ec01, 0x7850ed00, 0x79e0ee00, 0xe971ef01, 4232*53901Smckusick 0x7700f000, 0xe791f101, 0xe621f201, 0x76b0f300, 4233*53901Smckusick 0xe541f401, 0x75d0f500, 0x7460f600, 0xe4f1f701, 4234*53901Smckusick 0xe381f801, 0x7310f900, 0x72a0fa00, 0xe231fb01, 4235*53901Smckusick 0x71c0fc00, 0xe151fd01, 0xe0e1fe01, 0x7070ff00 4236*53901Smckusick }; 4237*53901Smckusick 4238*53901Smckusick /******************************************************** 4239*53901Smckusick * EDC (Error Detection Code) check * 4240*53901Smckusick * (using CRC code) * 4241*53901Smckusick * MODE 1 : Sync + Header + User data + edc * 4242*53901Smckusick * MODE 2 : Sub header + User data + edc * 4243*53901Smckusick ********************************************************/ 4244*53901Smckusick 4245*53901Smckusick #define SYNC_EDC 0x908eff4e /* sector sync EDC value */ 4246*53901Smckusick #define HEADER 4 /* header length 4 bytes */ 4247*53901Smckusick #define SUB_H 8 /* Subheader length 8 bytes */ 4248*53901Smckusick #define USER_DATA 2048 /* User data length 2048 bytes */ 4249*53901Smckusick #define EDC_LEN 4 /* EDC code length 4 bytes */ 4250*53901Smckusick 4251*53901Smckusick cal_edc1(db, mode) 4252*53901Smckusick register unsigned char *db; 4253*53901Smckusick int mode; 4254*53901Smckusick { 4255*53901Smckusick register int j; 4256*53901Smckusick register unsigned int work; 4257*53901Smckusick 4258*53901Smckusick j = USER_DATA + EDC_LEN; 4259*53901Smckusick if (mode == 2) { 4260*53901Smckusick j += SUB_H; 4261*53901Smckusick work = 0; 4262*53901Smckusick } else { 4263*53901Smckusick j += HEADER; 4264*53901Smckusick work = SYNC_EDC; 4265*53901Smckusick } 4266*53901Smckusick while (--j >= 0) 4267*53901Smckusick work = ((work >> 8) | (*db++ << 24)) ^ XORMASK(work & 0xff); 4268*53901Smckusick 4269*53901Smckusick return (work); 4270*53901Smckusick } 4271*53901Smckusick 4272*53901Smckusick 4273*53901Smckusick /************************************************/ 4274*53901Smckusick /* error detection & correction */ 4275*53901Smckusick /* if form 1 */ 4276*53901Smckusick /* header area should be zero */ 4277*53901Smckusick /************************************************/ 4278*53901Smckusick 4279*53901Smckusick /* 4280*53901Smckusick * error detection & correction P-direction 4281*53901Smckusick */ 4282*53901Smckusick p_dir(dbuf) 4283*53901Smckusick register unsigned short *dbuf; 4284*53901Smckusick { 4285*53901Smckusick unsigned short s0, s1, d; 4286*53901Smckusick register int col, row; 4287*53901Smckusick register int x; 4288*53901Smckusick unsigned char s0l, s0h, s1l, s1h; 4289*53901Smckusick 4290*53901Smckusick /* 4291*53901Smckusick * calculate syndrome S0 S1 4292*53901Smckusick */ 4293*53901Smckusick for (col = 0; col < 43; col++) { 4294*53901Smckusick s0 = s1 = 0; 4295*53901Smckusick 4296*53901Smckusick for (row = 0; row < 26; row++) { 4297*53901Smckusick d = dbuf[43 * row + col]; 4298*53901Smckusick s0 ^= d; 4299*53901Smckusick s1 = rsshift(s1) ^ d; 4300*53901Smckusick } 4301*53901Smckusick 4302*53901Smckusick s0h = s0 & 0x00ff; 4303*53901Smckusick s1h = s1 & 0x00ff; 4304*53901Smckusick s0l = (s0 >> 8) & 0x00ff; 4305*53901Smckusick s1l = (s1 >> 8) & 0x00ff; 4306*53901Smckusick /* 4307*53901Smckusick * calculate error position & correction 4308*53901Smckusick */ 4309*53901Smckusick if (s0l != 0) { 4310*53901Smckusick if((x = hextors(s1l) - hextors(s0l)) < 0) 4311*53901Smckusick x += 255; 4312*53901Smckusick if ((x >= 0) && (x < 26)) { 4313*53901Smckusick x = 25 - x; 4314*53901Smckusick /* 4315*53901Smckusick * correction 4316*53901Smckusick */ 4317*53901Smckusick dbuf[43 * x + col] ^= (s0 & 0xff00); 4318*53901Smckusick } 4319*53901Smckusick } 4320*53901Smckusick 4321*53901Smckusick /* 4322*53901Smckusick * calculate error position & correction 4323*53901Smckusick */ 4324*53901Smckusick if (s0h != 0) { 4325*53901Smckusick if((x = hextors(s1h) - hextors(s0h)) < 0) 4326*53901Smckusick x += 255; 4327*53901Smckusick if ((x >= 0) && (x < 26)) { 4328*53901Smckusick x = 25 - x; 4329*53901Smckusick /* 4330*53901Smckusick * correction 4331*53901Smckusick */ 4332*53901Smckusick dbuf[43 * x + col] ^= (s0 & 0x00ff); 4333*53901Smckusick } 4334*53901Smckusick } 4335*53901Smckusick } 4336*53901Smckusick } 4337*53901Smckusick 4338*53901Smckusick /* 4339*53901Smckusick * error detection & correction Q-direction 4340*53901Smckusick */ 4341*53901Smckusick q_dir(dbuf) 4342*53901Smckusick register unsigned short *dbuf; 4343*53901Smckusick { 4344*53901Smckusick unsigned short s0, s1, d; 4345*53901Smckusick register int col, row; 4346*53901Smckusick register int x; 4347*53901Smckusick unsigned char s0l, s0h, s1l, s1h; 4348*53901Smckusick 4349*53901Smckusick /* 4350*53901Smckusick * calculate syndrome S0 S1 4351*53901Smckusick */ 4352*53901Smckusick for (row = 0; row < 26; row++) { 4353*53901Smckusick s0 = s1 = 0; 4354*53901Smckusick 4355*53901Smckusick for (col = 0; col < 45; col++) { 4356*53901Smckusick if (col < 43) 4357*53901Smckusick d = dbuf[(44 * col + 43 * row) % 1118]; 4358*53901Smckusick else if (col == 43) 4359*53901Smckusick d = dbuf[43 * 26 + row]; 4360*53901Smckusick else 4361*53901Smckusick d = dbuf[44 * 26 + row]; 4362*53901Smckusick s0 ^= d; 4363*53901Smckusick s1 = rsshift(s1) ^ d; 4364*53901Smckusick } 4365*53901Smckusick 4366*53901Smckusick s0h = s0 & 0x00ff; 4367*53901Smckusick s1h = s1 & 0x00ff; 4368*53901Smckusick s0l = (s0 >> 8) & 0x00ff; 4369*53901Smckusick s1l = (s1 >> 8) & 0x00ff; 4370*53901Smckusick /* 4371*53901Smckusick * calculate error position & correction 4372*53901Smckusick */ 4373*53901Smckusick if (s0l != 0) { 4374*53901Smckusick if((x = hextors(s1l) - hextors(s0l)) < 0) 4375*53901Smckusick x += 255; 4376*53901Smckusick if (x >= 0 && x < 45) { 4377*53901Smckusick x = 44 - x; 4378*53901Smckusick /* 4379*53901Smckusick * correction 4380*53901Smckusick */ 4381*53901Smckusick if (x < 43) 4382*53901Smckusick dbuf[(44 * x + 43 * row) % 1118] 4383*53901Smckusick ^= s0 & 0xff00; 4384*53901Smckusick else if (x == 43) 4385*53901Smckusick dbuf[43 * 26 + row] ^= s0 & 0xff00; 4386*53901Smckusick else 4387*53901Smckusick dbuf[44 * 26 + row] ^= s0 & 0xff00; 4388*53901Smckusick } 4389*53901Smckusick } 4390*53901Smckusick 4391*53901Smckusick /* 4392*53901Smckusick * calculate error position & correction 4393*53901Smckusick */ 4394*53901Smckusick if (s0h != 0) { 4395*53901Smckusick if((x = hextors(s1h) - hextors(s0h)) < 0) 4396*53901Smckusick x += 255; 4397*53901Smckusick if ((x >= 0) && (x < 45)) { 4398*53901Smckusick x = 44 - x; 4399*53901Smckusick /* 4400*53901Smckusick * correction 4401*53901Smckusick */ 4402*53901Smckusick if (x < 43) 4403*53901Smckusick dbuf[(44 * x + 43 * row) % 1118] 4404*53901Smckusick ^= s0 & 0x00ff; 4405*53901Smckusick else if ( x == 43) 4406*53901Smckusick dbuf[43 * 26 + row] ^= s0 & 0x00ff; 4407*53901Smckusick else 4408*53901Smckusick dbuf[44 * 26 + row] ^= s0 & 0x00ff; 4409*53901Smckusick } 4410*53901Smckusick } 4411*53901Smckusick } 4412*53901Smckusick } 4413*53901Smckusick 4414*53901Smckusick /* 4415*53901Smckusick * shift high & low byte at the same time 4416*53901Smckusick */ 4417*53901Smckusick rsshift(d) 4418*53901Smckusick unsigned short d; 4419*53901Smckusick { 4420*53901Smckusick register int x; 4421*53901Smckusick register int dmy; /* This way is faster */ 4422*53901Smckusick 4423*53901Smckusick dmy = (int)d; 4424*53901Smckusick x = (dmy << 1) & 0xfefe; /* clear LSB of high & low byte */ 4425*53901Smckusick if ((dmy & 0x0080) != 0) 4426*53901Smckusick x ^= X8_L; 4427*53901Smckusick if ((dmy & 0x8000) != 0) 4428*53901Smckusick x ^= X8_H; 4429*53901Smckusick return(x); 4430*53901Smckusick } 4431*53901Smckusick #endif /* NSD > 0 */ 4432