1*54007Sfujita /* 2*54007Sfujita * Copyright (c) 1992 OMRON Corporation. 3*54007Sfujita * Copyright (c) 1992 The Regents of the University of California. 4*54007Sfujita * All rights reserved. 5*54007Sfujita * 6*54007Sfujita * This code is derived from software contributed to Berkeley by 7*54007Sfujita * OMRON Corporation. 8*54007Sfujita * 9*54007Sfujita * %sccs.include.redist.c% 10*54007Sfujita * 11*54007Sfujita * @(#)sd.c 7.1 (Berkeley) 06/15/92 12*54007Sfujita */ 13*54007Sfujita 14*54007Sfujita /* 15*54007Sfujita * sd.c -- SCSI Disk Device Driver 16*54007Sfujita * remaked by A.Fujita, MAR-22-1992 17*54007Sfujita */ 18*54007Sfujita 19*54007Sfujita /* 20*54007Sfujita * SCSI CCS (Command Command Set) disk driver. 21*54007Sfujita */ 22*54007Sfujita #include "sd.h" 23*54007Sfujita #if NSD > 0 24*54007Sfujita 25*54007Sfujita #include "sys/param.h" 26*54007Sfujita #include "sys/buf.h" 27*54007Sfujita #include "sys/dkstat.h" 28*54007Sfujita #include "sys/proc.h" 29*54007Sfujita #include "sys/disklabel.h" 30*54007Sfujita 31*54007Sfujita #include "device.h" 32*54007Sfujita #include "scsireg.h" 33*54007Sfujita #include "scsivar.h" 34*54007Sfujita 35*54007Sfujita int sdinit(), sdstrategy(), sdstart(), sdintr(); 36*54007Sfujita 37*54007Sfujita struct driver sddriver = { 38*54007Sfujita sdinit, "sd", sdstart, (int (*)()) 0, sdintr, (int (*)()) 0 39*54007Sfujita }; 40*54007Sfujita 41*54007Sfujita struct disklabel sdlabel[NSD]; 42*54007Sfujita 43*54007Sfujita struct sd_softc { 44*54007Sfujita struct hp_device *sc_hd; 45*54007Sfujita struct scsi_queue sc_dq; 46*54007Sfujita short sc_flags; 47*54007Sfujita short sc_type; /* drive type */ 48*54007Sfujita short sc_punit; /* physical unit (scsi lun) */ 49*54007Sfujita u_int sc_blks; /* number of blocks on device */ 50*54007Sfujita int sc_blksize; /* device block size in bytes */ 51*54007Sfujita u_int sc_wpms; /* average xfer rate in 16 bit wds/sec. */ 52*54007Sfujita } sd_softc[NSD]; 53*54007Sfujita 54*54007Sfujita /* sc_flags values */ 55*54007Sfujita #define SDF_ALIVE 0x1 56*54007Sfujita 57*54007Sfujita struct buf sdtab[NSD]; 58*54007Sfujita struct scsi_fmt_sense sdsense[NSD]; 59*54007Sfujita 60*54007Sfujita static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT }; 61*54007Sfujita static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT }; 62*54007Sfujita 63*54007Sfujita #define sdunit(x) ((minor(x) >> 3) & 0x7) 64*54007Sfujita #define sdpart(x) (minor(x) & 0x7) 65*54007Sfujita #define sdpunit(x) ((x) & 7) 66*54007Sfujita #define sdminor(unit, part) (((unit) << 3) | (part)) 67*54007Sfujita 68*54007Sfujita #define b_lba b_resid 69*54007Sfujita 70*54007Sfujita #define SDRETRY 3 /* IO retry count */ 71*54007Sfujita 72*54007Sfujita struct sd_iostat { 73*54007Sfujita int imax; 74*54007Sfujita int imin; 75*54007Sfujita int omax; 76*54007Sfujita int omin; 77*54007Sfujita }; 78*54007Sfujita 79*54007Sfujita struct sd_iostat sd_iostat[NSD] = { 80*54007Sfujita { 14000, -1, 100, -1 }, 81*54007Sfujita }; 82*54007Sfujita 83*54007Sfujita /* 84*54007Sfujita * Initialize 85*54007Sfujita */ 86*54007Sfujita 87*54007Sfujita int 88*54007Sfujita sdinit(hd) 89*54007Sfujita register struct hp_device *hd; 90*54007Sfujita { 91*54007Sfujita register struct sd_softc *sc = &sd_softc[hd->hp_unit]; 92*54007Sfujita register struct disklabel *lp; 93*54007Sfujita char *msg, *sdreadlabel(); 94*54007Sfujita 95*54007Sfujita sc->sc_hd = hd; 96*54007Sfujita sc->sc_punit = sdpunit(hd->hp_flags); 97*54007Sfujita sc->sc_type = sdident(sc, hd); 98*54007Sfujita if (sc->sc_type < 0) 99*54007Sfujita return(0); 100*54007Sfujita sc->sc_dq.dq_ctlr = hd->hp_ctlr; 101*54007Sfujita sc->sc_dq.dq_unit = hd->hp_unit; 102*54007Sfujita sc->sc_dq.dq_slave = hd->hp_slave; 103*54007Sfujita sc->sc_dq.dq_driver = &sddriver; 104*54007Sfujita 105*54007Sfujita /* 106*54007Sfujita * Use the default sizes until we've read the label, 107*54007Sfujita * or longer if there isn't one there. 108*54007Sfujita */ 109*54007Sfujita lp = &sdlabel[hd->hp_unit]; 110*54007Sfujita 111*54007Sfujita if (lp->d_secpercyl == 0) { 112*54007Sfujita lp->d_secsize = DEV_BSIZE; 113*54007Sfujita lp->d_nsectors = 32; 114*54007Sfujita lp->d_ntracks = 20; 115*54007Sfujita lp->d_secpercyl = 32*20; 116*54007Sfujita lp->d_npartitions = 1; 117*54007Sfujita lp->d_partitions[0].p_offset = 0; 118*54007Sfujita lp->d_partitions[0].p_size = LABELSECTOR + 1; 119*54007Sfujita } 120*54007Sfujita 121*54007Sfujita /* 122*54007Sfujita * read disklabel 123*54007Sfujita */ 124*54007Sfujita if (msg = sdreadlabel(makedev(4, (hd->hp_unit<<3)), sdstrategy, lp)) { 125*54007Sfujita if (msg != NULL) { 126*54007Sfujita printf("sd%d: %s\n", hd->hp_unit, msg); 127*54007Sfujita return(0); 128*54007Sfujita } 129*54007Sfujita } 130*54007Sfujita 131*54007Sfujita sc->sc_flags = SDF_ALIVE; 132*54007Sfujita return(1); 133*54007Sfujita } 134*54007Sfujita 135*54007Sfujita static struct scsi_inquiry inqbuf; 136*54007Sfujita static struct scsi_fmt_cdb inq = { 137*54007Sfujita 6, 138*54007Sfujita CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 139*54007Sfujita }; 140*54007Sfujita 141*54007Sfujita static u_long capbuf[2]; 142*54007Sfujita struct scsi_fmt_cdb cap = { 143*54007Sfujita 10, 144*54007Sfujita CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 145*54007Sfujita }; 146*54007Sfujita 147*54007Sfujita int 148*54007Sfujita sdident(sc, hd) 149*54007Sfujita struct sd_softc *sc; 150*54007Sfujita struct hp_device *hd; 151*54007Sfujita { 152*54007Sfujita char idstr[32]; 153*54007Sfujita int unit; 154*54007Sfujita register int ctlr, slave; 155*54007Sfujita register int i; 156*54007Sfujita register int tries = 10; 157*54007Sfujita 158*54007Sfujita ctlr = hd->hp_ctlr; 159*54007Sfujita slave = hd->hp_slave; 160*54007Sfujita unit = sc->sc_punit; 161*54007Sfujita 162*54007Sfujita /* 163*54007Sfujita * See if unit exists and is a disk then read block size & nblocks. 164*54007Sfujita */ 165*54007Sfujita while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) { 166*54007Sfujita if (i < 0 || --tries < 0) 167*54007Sfujita return (-1); 168*54007Sfujita if (i == STS_CHECKCOND) { 169*54007Sfujita u_char sensebuf[8]; 170*54007Sfujita struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; 171*54007Sfujita 172*54007Sfujita scsi_request_sense(ctlr, slave, unit, sensebuf, 8); 173*54007Sfujita if (sp->class == 7 && sp->key == 6) 174*54007Sfujita /* drive doing an RTZ -- give it a while */ 175*54007Sfujita DELAY(1000000); 176*54007Sfujita } 177*54007Sfujita DELAY(1000); 178*54007Sfujita } 179*54007Sfujita if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf, 180*54007Sfujita sizeof(inqbuf)) || 181*54007Sfujita scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf, 182*54007Sfujita sizeof(capbuf))) 183*54007Sfujita /* doesn't exist or not a CCS device */ 184*54007Sfujita return (-1); 185*54007Sfujita 186*54007Sfujita switch (inqbuf.type) { 187*54007Sfujita case 0: /* disk */ 188*54007Sfujita case 4: /* WORM */ 189*54007Sfujita case 5: /* CD-ROM */ 190*54007Sfujita case 7: /* Magneto-optical */ 191*54007Sfujita break; 192*54007Sfujita default: /* not a disk */ 193*54007Sfujita return (-1); 194*54007Sfujita } 195*54007Sfujita sc->sc_blks = capbuf[0]; 196*54007Sfujita sc->sc_blksize = capbuf[1]; 197*54007Sfujita 198*54007Sfujita bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); 199*54007Sfujita for (i = 27; i > 23; --i) 200*54007Sfujita if (idstr[i] != ' ') 201*54007Sfujita break; 202*54007Sfujita idstr[i+1] = 0; 203*54007Sfujita for (i = 23; i > 7; --i) 204*54007Sfujita if (idstr[i] != ' ') 205*54007Sfujita break; 206*54007Sfujita idstr[i+1] = 0; 207*54007Sfujita for (i = 7; i >= 0; --i) 208*54007Sfujita if (idstr[i] != ' ') 209*54007Sfujita break; 210*54007Sfujita idstr[i+1] = 0; 211*54007Sfujita printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8], 212*54007Sfujita &idstr[24]); 213*54007Sfujita 214*54007Sfujita printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize); 215*54007Sfujita if (sc->sc_blksize != DEV_BSIZE) { 216*54007Sfujita printf("sd%d: need %d byte blocks - drive ignored\n", unit, DEV_BSIZE); 217*54007Sfujita return(1); 218*54007Sfujita } 219*54007Sfujita 220*54007Sfujita sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 221*54007Sfujita return(inqbuf.type); 222*54007Sfujita } 223*54007Sfujita 224*54007Sfujita 225*54007Sfujita /* 226*54007Sfujita * Open 227*54007Sfujita */ 228*54007Sfujita 229*54007Sfujita int 230*54007Sfujita sdopen(dev, flags, mode, p) 231*54007Sfujita dev_t dev; 232*54007Sfujita int flags, mode; 233*54007Sfujita struct proc *p; 234*54007Sfujita { 235*54007Sfujita register int unit = sdunit(dev); 236*54007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 237*54007Sfujita 238*54007Sfujita if (unit >= NSD) 239*54007Sfujita return(ENXIO); 240*54007Sfujita if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag)) 241*54007Sfujita return(ENXIO); 242*54007Sfujita 243*54007Sfujita if (sc->sc_hd->hp_dk >= 0) 244*54007Sfujita dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms; 245*54007Sfujita return(0); 246*54007Sfujita } 247*54007Sfujita 248*54007Sfujita 249*54007Sfujita /* 250*54007Sfujita * Strategy 251*54007Sfujita */ 252*54007Sfujita 253*54007Sfujita int 254*54007Sfujita sdstrategy(bp) 255*54007Sfujita register struct buf *bp; 256*54007Sfujita { 257*54007Sfujita register int unit = sdunit(bp->b_dev); 258*54007Sfujita register int part = sdpart(bp->b_dev); 259*54007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 260*54007Sfujita register struct disklabel *lp = &sdlabel[unit]; 261*54007Sfujita register struct partition *pp = &(lp->d_partitions[part]); 262*54007Sfujita register struct buf *dp = &sdtab[unit]; 263*54007Sfujita register daddr_t bn; 264*54007Sfujita register int sz, s; 265*54007Sfujita 266*54007Sfujita #ifdef DEBUG 267*54007Sfujita printf("sdstrategy: bp->b_blkno = %d, bp->bcount = %d\n", 268*54007Sfujita bp->b_blkno, bp->b_bcount); 269*54007Sfujita #endif 270*54007Sfujita bn = bp->b_blkno; 271*54007Sfujita sz = howmany(bp->b_bcount, DEV_BSIZE); 272*54007Sfujita 273*54007Sfujita /* check that tracsfer is within a drive's partition */ 274*54007Sfujita 275*54007Sfujita if (bn < 0 || (bn + sz) > pp->p_size) { 276*54007Sfujita sz = pp->p_size - bn; 277*54007Sfujita if (sz == 0) { 278*54007Sfujita bp->b_resid = bp->b_bcount; 279*54007Sfujita goto done; 280*54007Sfujita } 281*54007Sfujita if (sz < 0) { 282*54007Sfujita bp->b_error = EINVAL; 283*54007Sfujita bp->b_flags |= B_ERROR; 284*54007Sfujita goto done; 285*54007Sfujita } 286*54007Sfujita bp->b_bcount = dbtob(sz); 287*54007Sfujita } 288*54007Sfujita 289*54007Sfujita /* calculate LBA for transfer */ 290*54007Sfujita 291*54007Sfujita bp->b_lba = bn + pp->p_offset; 292*54007Sfujita 293*54007Sfujita /* raise priority to block sdintr */ 294*54007Sfujita 295*54007Sfujita s = splbio(); 296*54007Sfujita 297*54007Sfujita /* call disksort to sort request into drive queue */ 298*54007Sfujita 299*54007Sfujita disksort(dp, bp); 300*54007Sfujita 301*54007Sfujita #ifdef DEBUG 302*54007Sfujita printf("sdstrategy: dp->b_active = %d\n", dp->b_active); 303*54007Sfujita #endif 304*54007Sfujita if (dp->b_active == 0) { /* */ 305*54007Sfujita dp->b_active = 1; 306*54007Sfujita sdustart(unit); 307*54007Sfujita } 308*54007Sfujita 309*54007Sfujita /* lower priority */ 310*54007Sfujita 311*54007Sfujita splx(s); 312*54007Sfujita 313*54007Sfujita return; 314*54007Sfujita 315*54007Sfujita done: 316*54007Sfujita biodone(bp); 317*54007Sfujita } 318*54007Sfujita 319*54007Sfujita int 320*54007Sfujita sdustart(unit) 321*54007Sfujita register int unit; 322*54007Sfujita { 323*54007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 324*54007Sfujita register struct hp_device *hp = sc->sc_hd; 325*54007Sfujita register struct scsi_queue *dq = &sc->sc_dq; 326*54007Sfujita register struct buf *bp = sdtab[unit].b_actf; 327*54007Sfujita register struct scsi_fmt_cdb *cmd; 328*54007Sfujita 329*54007Sfujita cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd; 330*54007Sfujita *(int *)(&cmd->cdb[2]) = bp->b_lba; 331*54007Sfujita *(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE); 332*54007Sfujita 333*54007Sfujita dq->dq_cdb = cmd; 334*54007Sfujita dq->dq_bp = bp; 335*54007Sfujita dq->dq_flags = DQ_DISCONNECT; /* SCSI Disconnect */ 336*54007Sfujita 337*54007Sfujita if (screq(dq)) 338*54007Sfujita sdstart(unit); 339*54007Sfujita } 340*54007Sfujita 341*54007Sfujita int 342*54007Sfujita sdstart(unit) 343*54007Sfujita register int unit; 344*54007Sfujita { 345*54007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 346*54007Sfujita register struct hp_device *hp = sc->sc_hd; 347*54007Sfujita 348*54007Sfujita if (hp->hp_dk >= 0) { 349*54007Sfujita dk_busy |= 1 << hp->hp_dk; 350*54007Sfujita } 351*54007Sfujita 352*54007Sfujita scstart(hp->hp_ctlr); 353*54007Sfujita } 354*54007Sfujita 355*54007Sfujita 356*54007Sfujita /* 357*54007Sfujita * Return: 358*54007Sfujita * 0 if not really an error 359*54007Sfujita * <0 if we should do a retry 360*54007Sfujita * >0 if a fatal error 361*54007Sfujita */ 362*54007Sfujita static int 363*54007Sfujita sderror(unit, sc, hp, stat) 364*54007Sfujita int unit, stat; 365*54007Sfujita register struct sd_softc *sc; 366*54007Sfujita register struct hp_device *hp; 367*54007Sfujita { 368*54007Sfujita int cond = 1; 369*54007Sfujita 370*54007Sfujita sdsense[unit].status = stat; 371*54007Sfujita if (stat & STS_CHECKCOND) { 372*54007Sfujita struct scsi_xsense *sp; 373*54007Sfujita 374*54007Sfujita scsi_request_sense(hp->hp_ctlr, hp->hp_slave, 375*54007Sfujita sc->sc_punit, sdsense[unit].sense, 376*54007Sfujita sizeof(sdsense[unit].sense)); 377*54007Sfujita sp = (struct scsi_xsense *)sdsense[unit].sense; 378*54007Sfujita printf("sd%d: scsi sense class %d, code %d", unit, 379*54007Sfujita sp->class, sp->code); 380*54007Sfujita if (sp->class == 7) { 381*54007Sfujita printf(", key %d", sp->key); 382*54007Sfujita if (sp->valid) 383*54007Sfujita printf(", blk %d", *(int *)&sp->info1); 384*54007Sfujita switch (sp->key) { 385*54007Sfujita /* no sense, try again */ 386*54007Sfujita case 0: 387*54007Sfujita cond = -1; 388*54007Sfujita break; 389*54007Sfujita /* recovered error, not a problem */ 390*54007Sfujita case 1: 391*54007Sfujita cond = 0; 392*54007Sfujita break; 393*54007Sfujita } 394*54007Sfujita } 395*54007Sfujita printf("\n"); 396*54007Sfujita } 397*54007Sfujita return(cond); 398*54007Sfujita } 399*54007Sfujita 400*54007Sfujita /* 401*54007Sfujita * Interrupt 402*54007Sfujita */ 403*54007Sfujita 404*54007Sfujita int 405*54007Sfujita sdintr(unit, stat) 406*54007Sfujita register int unit; 407*54007Sfujita int stat; 408*54007Sfujita { 409*54007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 410*54007Sfujita register struct hp_device *hp = sc->sc_hd; 411*54007Sfujita register struct scsi_queue *dq = &sc->sc_dq; 412*54007Sfujita register struct buf *bp = dq->dq_bp; 413*54007Sfujita int cond; 414*54007Sfujita 415*54007Sfujita #ifdef DEBUG 416*54007Sfujita printf("sdintr(unit = %d, stat = %d)\n", unit, stat); 417*54007Sfujita #endif 418*54007Sfujita 419*54007Sfujita if (stat == SC_IO_TIMEOUT) { 420*54007Sfujita printf("sdintr: sd%d timeout error\n", unit, stat); 421*54007Sfujita } 422*54007Sfujita 423*54007Sfujita if (hp->hp_dk >= 0) { 424*54007Sfujita dk_busy &=~ (1 << hp->hp_dk); 425*54007Sfujita if (stat == 0) { 426*54007Sfujita ++dk_seek[hp->hp_dk]; 427*54007Sfujita ++dk_xfer[hp->hp_dk]; 428*54007Sfujita dk_wds[hp->hp_dk] += bp->b_bcount >> 6; 429*54007Sfujita } 430*54007Sfujita } 431*54007Sfujita 432*54007Sfujita if (bp->b_flags & B_READ) { 433*54007Sfujita sd_iostat[unit].imin = MIN(dq->dq_imin, sd_iostat[unit].imin); 434*54007Sfujita if (dq->dq_imax > sd_iostat[unit].imax) { 435*54007Sfujita sd_iostat[unit].imax = dq->dq_imax; 436*54007Sfujita #ifdef SD_IOSTAT 437*54007Sfujita printf("sdintr: sd%d INPUT MAX = %d, MIN = %d\n", 438*54007Sfujita unit, sd_iostat[unit].imax, sd_iostat[unit].imin); 439*54007Sfujita #endif 440*54007Sfujita } 441*54007Sfujita } else { 442*54007Sfujita sd_iostat[unit].omin = MIN(dq->dq_omin, sd_iostat[unit].omin); 443*54007Sfujita if (dq->dq_omax > sd_iostat[unit].omax) { 444*54007Sfujita sd_iostat[unit].omax = dq->dq_omax; 445*54007Sfujita #ifdef SD_IOSTAT 446*54007Sfujita printf("sdintr: sd%d OUTPUT MAX = %d, MIN = %d\n", 447*54007Sfujita unit, sd_iostat[unit].omax, sd_iostat[unit].omin); 448*54007Sfujita #endif 449*54007Sfujita } 450*54007Sfujita } 451*54007Sfujita 452*54007Sfujita if (stat != 0) { 453*54007Sfujita if (stat > 0) { 454*54007Sfujita #ifdef DEBUGPRINT 455*54007Sfujita dbgprintall(); 456*54007Sfujita printf("\n"); 457*54007Sfujita #endif 458*54007Sfujita cond = sderror(unit, sc, hp, stat); 459*54007Sfujita if (cond) { 460*54007Sfujita if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) { 461*54007Sfujita sdstart(unit); 462*54007Sfujita return; 463*54007Sfujita } 464*54007Sfujita } 465*54007Sfujita } else { 466*54007Sfujita if (sdtab[unit].b_errcnt++ < SDRETRY) { 467*54007Sfujita printf("sdintr: sd%d restart IO request\n", unit); 468*54007Sfujita sdstart(unit); 469*54007Sfujita return; 470*54007Sfujita } 471*54007Sfujita } 472*54007Sfujita bp->b_flags |= B_ERROR; 473*54007Sfujita bp->b_error = EIO; 474*54007Sfujita } 475*54007Sfujita 476*54007Sfujita sdtab[unit].b_errcnt = 0; 477*54007Sfujita sdtab[unit].b_actf = bp->b_actf; 478*54007Sfujita 479*54007Sfujita bp->b_resid = 0; 480*54007Sfujita 481*54007Sfujita biodone(bp); 482*54007Sfujita 483*54007Sfujita scfree(dq); 484*54007Sfujita 485*54007Sfujita if (sdtab[unit].b_actf) { 486*54007Sfujita sdustart(unit); 487*54007Sfujita } else { 488*54007Sfujita sdtab[unit].b_active = 0; 489*54007Sfujita } 490*54007Sfujita } 491*54007Sfujita 492*54007Sfujita 493*54007Sfujita /* 494*54007Sfujita * RAW Device Routines 495*54007Sfujita */ 496*54007Sfujita 497*54007Sfujita int 498*54007Sfujita sdread(dev, uio, flags) 499*54007Sfujita dev_t dev; 500*54007Sfujita struct uio *uio; 501*54007Sfujita int flags; 502*54007Sfujita { 503*54007Sfujita register int unit = sdunit(dev); 504*54007Sfujita 505*54007Sfujita return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio)); 506*54007Sfujita } 507*54007Sfujita 508*54007Sfujita int 509*54007Sfujita sdwrite(dev, uio, flags) 510*54007Sfujita dev_t dev; 511*54007Sfujita struct uio *uio; 512*54007Sfujita int flags; 513*54007Sfujita { 514*54007Sfujita register int unit = sdunit(dev); 515*54007Sfujita 516*54007Sfujita return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio)); 517*54007Sfujita } 518*54007Sfujita 519*54007Sfujita int 520*54007Sfujita sdioctl(dev, cmd, data, flag, p) 521*54007Sfujita dev_t dev; 522*54007Sfujita int cmd; 523*54007Sfujita caddr_t data; 524*54007Sfujita int flag; 525*54007Sfujita struct proc *p; 526*54007Sfujita { 527*54007Sfujita int unit = sdunit(dev); 528*54007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 529*54007Sfujita register struct disklabel *lp = &sdlabel[unit]; 530*54007Sfujita int error = 0; 531*54007Sfujita 532*54007Sfujita switch (cmd) { 533*54007Sfujita 534*54007Sfujita case DIOCGDINFO: 535*54007Sfujita *(struct disklabel *)data = *lp; 536*54007Sfujita break; 537*54007Sfujita 538*54007Sfujita case DIOCGPART: 539*54007Sfujita ((struct partinfo *)data)->disklab = lp; 540*54007Sfujita ((struct partinfo *)data)->part = 541*54007Sfujita &lp->d_partitions[sdpart(dev)]; 542*54007Sfujita break; 543*54007Sfujita 544*54007Sfujita default: 545*54007Sfujita error = ENOTTY; 546*54007Sfujita break; 547*54007Sfujita } 548*54007Sfujita return (error); 549*54007Sfujita } 550*54007Sfujita 551*54007Sfujita 552*54007Sfujita /* 553*54007Sfujita * Size 554*54007Sfujita */ 555*54007Sfujita 556*54007Sfujita int 557*54007Sfujita sdsize(dev) 558*54007Sfujita dev_t dev; 559*54007Sfujita { 560*54007Sfujita register int unit = sdunit(dev); 561*54007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 562*54007Sfujita 563*54007Sfujita if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0) 564*54007Sfujita return(-1); 565*54007Sfujita 566*54007Sfujita return(sdlabel[unit].d_partitions[sdpart(dev)].p_size); 567*54007Sfujita } 568*54007Sfujita 569*54007Sfujita 570*54007Sfujita /* 571*54007Sfujita * Dump 572*54007Sfujita */ 573*54007Sfujita 574*54007Sfujita int 575*54007Sfujita sddump(dev) 576*54007Sfujita dev_t dev; 577*54007Sfujita { 578*54007Sfujita } 579*54007Sfujita 580*54007Sfujita /* 581*54007Sfujita * Disk Subs 582*54007Sfujita */ 583*54007Sfujita 584*54007Sfujita /* 585*54007Sfujita * Attempt to read a disk label from a device 586*54007Sfujita * using the indicated stategy routine. 587*54007Sfujita * The label must be partly set up before this: 588*54007Sfujita * secpercyl and anything required in the strategy routine 589*54007Sfujita * (e.g., sector size) must be filled in before calling us. 590*54007Sfujita * Returns null on success and an error string on failure. 591*54007Sfujita */ 592*54007Sfujita char * 593*54007Sfujita sdreadlabel(dev, strat, lp) 594*54007Sfujita dev_t dev; 595*54007Sfujita int (*strat)(); 596*54007Sfujita register struct disklabel *lp; 597*54007Sfujita { 598*54007Sfujita register struct buf *bp; 599*54007Sfujita struct disklabel *dlp; 600*54007Sfujita char *msg = NULL; 601*54007Sfujita 602*54007Sfujita if (lp->d_secperunit == 0) 603*54007Sfujita lp->d_secperunit = 0x1fffffff; 604*54007Sfujita lp->d_npartitions = 1; 605*54007Sfujita if (lp->d_partitions[0].p_size == 0) 606*54007Sfujita lp->d_partitions[0].p_size = 0x1fffffff; 607*54007Sfujita lp->d_partitions[0].p_offset = 0; 608*54007Sfujita 609*54007Sfujita bp = geteblk((int)lp->d_secsize); 610*54007Sfujita bp->b_dev = dev; 611*54007Sfujita bp->b_blkno = LABELSECTOR; 612*54007Sfujita bp->b_bcount = lp->d_secsize; 613*54007Sfujita bp->b_flags = B_BUSY | B_READ; 614*54007Sfujita (*strat)(bp); 615*54007Sfujita if (biowait(bp)) { 616*54007Sfujita msg = "I/O error"; 617*54007Sfujita } else { 618*54007Sfujita for (dlp = (struct disklabel *)bp->b_un.b_addr; 619*54007Sfujita dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp)); 620*54007Sfujita dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 621*54007Sfujita if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { 622*54007Sfujita if (msg == NULL) 623*54007Sfujita msg = "no disk label"; 624*54007Sfujita } else if (dlp->d_npartitions > MAXPARTITIONS || 625*54007Sfujita dkcksum(dlp) != 0) 626*54007Sfujita msg = "disk label corrupted"; 627*54007Sfujita else { 628*54007Sfujita *lp = *dlp; 629*54007Sfujita msg = NULL; 630*54007Sfujita break; 631*54007Sfujita } 632*54007Sfujita } 633*54007Sfujita } 634*54007Sfujita bp->b_flags = B_INVAL | B_AGE; 635*54007Sfujita brelse(bp); 636*54007Sfujita return (msg); 637*54007Sfujita } 638*54007Sfujita 639*54007Sfujita #ifdef notyet 640*54007Sfujita 641*54007Sfujita /* 642*54007Sfujita * Checksum routine for OMRON native disklabel 643*54007Sfujita */ 644*54007Sfujita 645*54007Sfujita #define OMRON_LBLSIZE 512 646*54007Sfujita 647*54007Sfujita u_short 648*54007Sfujita omcksum(omp) 649*54007Sfujita register char *omp; 650*54007Sfujita { 651*54007Sfujita register u_short *start, *end; 652*54007Sfujita register u_short sum = 0; 653*54007Sfujita 654*54007Sfujita start = (u_short *) omp; 655*54007Sfujita end = (u_short *) &start[(OMRON_LBLSIZE/sizeof(u_short) - 1)]; 656*54007Sfujita while (start < end) 657*54007Sfujita sum ^= *start++; 658*54007Sfujita 659*54007Sfujita printf("omcksum: saved ... 0x%s\n", hexstr(*end, 4)); 660*54007Sfujita printf("omcksum: calced ... 0x%s\n", hexstr(sum, 4)); 661*54007Sfujita 662*54007Sfujita return (sum); 663*54007Sfujita } 664*54007Sfujita 665*54007Sfujita /* 666*54007Sfujita * Write disk label back to device after modification. 667*54007Sfujita */ 668*54007Sfujita sdwritelabel(dev, strat, lp) 669*54007Sfujita dev_t dev; 670*54007Sfujita int (*strat)(); 671*54007Sfujita register struct disklabel *lp; 672*54007Sfujita { 673*54007Sfujita struct buf *bp; 674*54007Sfujita struct disklabel *dlp; 675*54007Sfujita int labelpart; 676*54007Sfujita int error = 0; 677*54007Sfujita 678*54007Sfujita labelpart = sdpart(dev); 679*54007Sfujita if (lp->d_partitions[labelpart].p_offset != 0) { 680*54007Sfujita if (lp->d_partitions[0].p_offset != 0) 681*54007Sfujita return (EXDEV); /* not quite right */ 682*54007Sfujita labelpart = 0; 683*54007Sfujita } 684*54007Sfujita 685*54007Sfujita bp = geteblk((int)lp->d_secsize); 686*54007Sfujita bp->b_dev = makedev(major(dev), sdminor(sdunit(dev), labelpart)); 687*54007Sfujita bp->b_blkno = LABELSECTOR; 688*54007Sfujita bp->b_bcount = lp->d_secsize; 689*54007Sfujita bp->b_flags = B_READ; 690*54007Sfujita (*strat)(bp); 691*54007Sfujita if (error = biowait(bp)) 692*54007Sfujita goto done; 693*54007Sfujita 694*54007Sfujita for (dlp = (struct disklabel *)bp->b_un.b_addr; 695*54007Sfujita dlp <= (struct disklabel *) 696*54007Sfujita (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp)); 697*54007Sfujita dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 698*54007Sfujita if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && 699*54007Sfujita dkcksum(dlp) == 0) { 700*54007Sfujita omcksum(bp->b_un.b_addr); 701*54007Sfujita /* 702*54007Sfujita *dlp = *lp; 703*54007Sfujita bp->b_flags = B_WRITE; 704*54007Sfujita (*strat)(bp); 705*54007Sfujita error = biowait(bp); 706*54007Sfujita goto done; 707*54007Sfujita */ 708*54007Sfujita } 709*54007Sfujita } 710*54007Sfujita error = ESRCH; 711*54007Sfujita done: 712*54007Sfujita brelse(bp); 713*54007Sfujita return (error); 714*54007Sfujita } 715*54007Sfujita #endif 716*54007Sfujita 717*54007Sfujita #endif 718