154007Sfujita /* 254007Sfujita * Copyright (c) 1992 OMRON Corporation. 354007Sfujita * Copyright (c) 1992 The Regents of the University of California. 454007Sfujita * All rights reserved. 554007Sfujita * 654007Sfujita * This code is derived from software contributed to Berkeley by 754007Sfujita * OMRON Corporation. 854007Sfujita * 954007Sfujita * %sccs.include.redist.c% 1054007Sfujita * 11*55176Saki * @(#)sd.c 7.2 (Berkeley) 07/13/92 1254007Sfujita */ 1354007Sfujita 1454007Sfujita /* 1554007Sfujita * sd.c -- SCSI Disk Device Driver 1654007Sfujita * remaked by A.Fujita, MAR-22-1992 1754007Sfujita */ 1854007Sfujita 1954007Sfujita /* 2054007Sfujita * SCSI CCS (Command Command Set) disk driver. 2154007Sfujita */ 2254007Sfujita #include "sd.h" 2354007Sfujita #if NSD > 0 2454007Sfujita 2554007Sfujita #include "sys/param.h" 2654007Sfujita #include "sys/buf.h" 2754007Sfujita #include "sys/dkstat.h" 2854007Sfujita #include "sys/proc.h" 2954007Sfujita #include "sys/disklabel.h" 3054007Sfujita 3154007Sfujita #include "device.h" 3254007Sfujita #include "scsireg.h" 3354007Sfujita #include "scsivar.h" 3454007Sfujita 3554007Sfujita int sdinit(), sdstrategy(), sdstart(), sdintr(); 3654007Sfujita 3754007Sfujita struct driver sddriver = { 3854007Sfujita sdinit, "sd", sdstart, (int (*)()) 0, sdintr, (int (*)()) 0 3954007Sfujita }; 4054007Sfujita 4154007Sfujita struct disklabel sdlabel[NSD]; 4254007Sfujita 4354007Sfujita struct sd_softc { 4454007Sfujita struct hp_device *sc_hd; 4554007Sfujita struct scsi_queue sc_dq; 4654007Sfujita short sc_flags; 4754007Sfujita short sc_type; /* drive type */ 4854007Sfujita short sc_punit; /* physical unit (scsi lun) */ 4954007Sfujita u_int sc_blks; /* number of blocks on device */ 5054007Sfujita int sc_blksize; /* device block size in bytes */ 5154007Sfujita u_int sc_wpms; /* average xfer rate in 16 bit wds/sec. */ 5254007Sfujita } sd_softc[NSD]; 5354007Sfujita 5454007Sfujita /* sc_flags values */ 5554007Sfujita #define SDF_ALIVE 0x1 5654007Sfujita 5754007Sfujita struct buf sdtab[NSD]; 5854007Sfujita struct scsi_fmt_sense sdsense[NSD]; 5954007Sfujita 6054007Sfujita static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT }; 6154007Sfujita static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT }; 6254007Sfujita 6354007Sfujita #define sdunit(x) ((minor(x) >> 3) & 0x7) 6454007Sfujita #define sdpart(x) (minor(x) & 0x7) 6554007Sfujita #define sdpunit(x) ((x) & 7) 6654007Sfujita #define sdminor(unit, part) (((unit) << 3) | (part)) 6754007Sfujita 6854007Sfujita #define b_lba b_resid 6954007Sfujita 7054007Sfujita #define SDRETRY 3 /* IO retry count */ 7154007Sfujita 7254007Sfujita struct sd_iostat { 7354007Sfujita int imax; 7454007Sfujita int imin; 7554007Sfujita int omax; 7654007Sfujita int omin; 7754007Sfujita }; 7854007Sfujita 7954007Sfujita struct sd_iostat sd_iostat[NSD] = { 8054007Sfujita { 14000, -1, 100, -1 }, 8154007Sfujita }; 8254007Sfujita 8354007Sfujita /* 8454007Sfujita * Initialize 8554007Sfujita */ 8654007Sfujita 8754007Sfujita int 8854007Sfujita sdinit(hd) 8954007Sfujita register struct hp_device *hd; 9054007Sfujita { 9154007Sfujita register struct sd_softc *sc = &sd_softc[hd->hp_unit]; 9254007Sfujita register struct disklabel *lp; 9354007Sfujita char *msg, *sdreadlabel(); 9454007Sfujita 9554007Sfujita sc->sc_hd = hd; 9654007Sfujita sc->sc_punit = sdpunit(hd->hp_flags); 9754007Sfujita sc->sc_type = sdident(sc, hd); 9854007Sfujita if (sc->sc_type < 0) 9954007Sfujita return(0); 10054007Sfujita sc->sc_dq.dq_ctlr = hd->hp_ctlr; 10154007Sfujita sc->sc_dq.dq_unit = hd->hp_unit; 10254007Sfujita sc->sc_dq.dq_slave = hd->hp_slave; 10354007Sfujita sc->sc_dq.dq_driver = &sddriver; 10454007Sfujita 10554007Sfujita /* 10654007Sfujita * Use the default sizes until we've read the label, 10754007Sfujita * or longer if there isn't one there. 10854007Sfujita */ 10954007Sfujita lp = &sdlabel[hd->hp_unit]; 11054007Sfujita 11154007Sfujita if (lp->d_secpercyl == 0) { 11254007Sfujita lp->d_secsize = DEV_BSIZE; 11354007Sfujita lp->d_nsectors = 32; 11454007Sfujita lp->d_ntracks = 20; 11554007Sfujita lp->d_secpercyl = 32*20; 11654007Sfujita lp->d_npartitions = 1; 11754007Sfujita lp->d_partitions[0].p_offset = 0; 11854007Sfujita lp->d_partitions[0].p_size = LABELSECTOR + 1; 11954007Sfujita } 12054007Sfujita 12154007Sfujita /* 12254007Sfujita * read disklabel 12354007Sfujita */ 12454007Sfujita if (msg = sdreadlabel(makedev(4, (hd->hp_unit<<3)), sdstrategy, lp)) { 12554007Sfujita if (msg != NULL) { 12654007Sfujita printf("sd%d: %s\n", hd->hp_unit, msg); 12754007Sfujita return(0); 12854007Sfujita } 12954007Sfujita } 13054007Sfujita 13154007Sfujita sc->sc_flags = SDF_ALIVE; 13254007Sfujita return(1); 13354007Sfujita } 13454007Sfujita 13554007Sfujita static struct scsi_inquiry inqbuf; 13654007Sfujita static struct scsi_fmt_cdb inq = { 13754007Sfujita 6, 13854007Sfujita CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 13954007Sfujita }; 14054007Sfujita 14154007Sfujita static u_long capbuf[2]; 14254007Sfujita struct scsi_fmt_cdb cap = { 14354007Sfujita 10, 14454007Sfujita CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 14554007Sfujita }; 14654007Sfujita 14754007Sfujita int 14854007Sfujita sdident(sc, hd) 14954007Sfujita struct sd_softc *sc; 15054007Sfujita struct hp_device *hd; 15154007Sfujita { 15254007Sfujita char idstr[32]; 15354007Sfujita int unit; 15454007Sfujita register int ctlr, slave; 15554007Sfujita register int i; 15654007Sfujita register int tries = 10; 15754007Sfujita 15854007Sfujita ctlr = hd->hp_ctlr; 15954007Sfujita slave = hd->hp_slave; 16054007Sfujita unit = sc->sc_punit; 16154007Sfujita 16254007Sfujita /* 16354007Sfujita * See if unit exists and is a disk then read block size & nblocks. 16454007Sfujita */ 16554007Sfujita while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) { 16654007Sfujita if (i < 0 || --tries < 0) 16754007Sfujita return (-1); 16854007Sfujita if (i == STS_CHECKCOND) { 16954007Sfujita u_char sensebuf[8]; 17054007Sfujita struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; 17154007Sfujita 17254007Sfujita scsi_request_sense(ctlr, slave, unit, sensebuf, 8); 17354007Sfujita if (sp->class == 7 && sp->key == 6) 17454007Sfujita /* drive doing an RTZ -- give it a while */ 17554007Sfujita DELAY(1000000); 17654007Sfujita } 17754007Sfujita DELAY(1000); 17854007Sfujita } 17954007Sfujita if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf, 18054007Sfujita sizeof(inqbuf)) || 18154007Sfujita scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf, 18254007Sfujita sizeof(capbuf))) 18354007Sfujita /* doesn't exist or not a CCS device */ 18454007Sfujita return (-1); 18554007Sfujita 18654007Sfujita switch (inqbuf.type) { 18754007Sfujita case 0: /* disk */ 18854007Sfujita case 4: /* WORM */ 18954007Sfujita case 5: /* CD-ROM */ 19054007Sfujita case 7: /* Magneto-optical */ 19154007Sfujita break; 19254007Sfujita default: /* not a disk */ 19354007Sfujita return (-1); 19454007Sfujita } 19554007Sfujita sc->sc_blks = capbuf[0]; 19654007Sfujita sc->sc_blksize = capbuf[1]; 19754007Sfujita 19854007Sfujita bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); 19954007Sfujita for (i = 27; i > 23; --i) 20054007Sfujita if (idstr[i] != ' ') 20154007Sfujita break; 20254007Sfujita idstr[i+1] = 0; 20354007Sfujita for (i = 23; i > 7; --i) 20454007Sfujita if (idstr[i] != ' ') 20554007Sfujita break; 20654007Sfujita idstr[i+1] = 0; 20754007Sfujita for (i = 7; i >= 0; --i) 20854007Sfujita if (idstr[i] != ' ') 20954007Sfujita break; 21054007Sfujita idstr[i+1] = 0; 21154007Sfujita printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8], 21254007Sfujita &idstr[24]); 21354007Sfujita 21454007Sfujita printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize); 21554007Sfujita if (sc->sc_blksize != DEV_BSIZE) { 21654007Sfujita printf("sd%d: need %d byte blocks - drive ignored\n", unit, DEV_BSIZE); 21754007Sfujita return(1); 21854007Sfujita } 21954007Sfujita 22054007Sfujita sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 22154007Sfujita return(inqbuf.type); 22254007Sfujita } 22354007Sfujita 22454007Sfujita 22554007Sfujita /* 22654007Sfujita * Open 22754007Sfujita */ 22854007Sfujita 22954007Sfujita int 23054007Sfujita sdopen(dev, flags, mode, p) 23154007Sfujita dev_t dev; 23254007Sfujita int flags, mode; 23354007Sfujita struct proc *p; 23454007Sfujita { 23554007Sfujita register int unit = sdunit(dev); 23654007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 23754007Sfujita 23854007Sfujita if (unit >= NSD) 23954007Sfujita return(ENXIO); 24054007Sfujita if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag)) 24154007Sfujita return(ENXIO); 24254007Sfujita 24354007Sfujita if (sc->sc_hd->hp_dk >= 0) 24454007Sfujita dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms; 24554007Sfujita return(0); 24654007Sfujita } 24754007Sfujita 24854007Sfujita 24954007Sfujita /* 25054007Sfujita * Strategy 25154007Sfujita */ 25254007Sfujita 25354007Sfujita int 25454007Sfujita sdstrategy(bp) 25554007Sfujita register struct buf *bp; 25654007Sfujita { 25754007Sfujita register int unit = sdunit(bp->b_dev); 25854007Sfujita register int part = sdpart(bp->b_dev); 25954007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 26054007Sfujita register struct disklabel *lp = &sdlabel[unit]; 26154007Sfujita register struct partition *pp = &(lp->d_partitions[part]); 26254007Sfujita register struct buf *dp = &sdtab[unit]; 26354007Sfujita register daddr_t bn; 26454007Sfujita register int sz, s; 26554007Sfujita 26654007Sfujita #ifdef DEBUG 26754007Sfujita printf("sdstrategy: bp->b_blkno = %d, bp->bcount = %d\n", 26854007Sfujita bp->b_blkno, bp->b_bcount); 26954007Sfujita #endif 27054007Sfujita bn = bp->b_blkno; 27154007Sfujita sz = howmany(bp->b_bcount, DEV_BSIZE); 27254007Sfujita 27354007Sfujita /* check that tracsfer is within a drive's partition */ 27454007Sfujita 27554007Sfujita if (bn < 0 || (bn + sz) > pp->p_size) { 27654007Sfujita sz = pp->p_size - bn; 27754007Sfujita if (sz == 0) { 27854007Sfujita bp->b_resid = bp->b_bcount; 27954007Sfujita goto done; 28054007Sfujita } 28154007Sfujita if (sz < 0) { 28254007Sfujita bp->b_error = EINVAL; 28354007Sfujita bp->b_flags |= B_ERROR; 28454007Sfujita goto done; 28554007Sfujita } 28654007Sfujita bp->b_bcount = dbtob(sz); 28754007Sfujita } 28854007Sfujita 28954007Sfujita /* calculate LBA for transfer */ 29054007Sfujita 29154007Sfujita bp->b_lba = bn + pp->p_offset; 29254007Sfujita 29354007Sfujita /* raise priority to block sdintr */ 29454007Sfujita 29554007Sfujita s = splbio(); 29654007Sfujita 29754007Sfujita /* call disksort to sort request into drive queue */ 29854007Sfujita 29954007Sfujita disksort(dp, bp); 30054007Sfujita 30154007Sfujita #ifdef DEBUG 30254007Sfujita printf("sdstrategy: dp->b_active = %d\n", dp->b_active); 30354007Sfujita #endif 30454007Sfujita if (dp->b_active == 0) { /* */ 30554007Sfujita dp->b_active = 1; 30654007Sfujita sdustart(unit); 30754007Sfujita } 30854007Sfujita 30954007Sfujita /* lower priority */ 31054007Sfujita 31154007Sfujita splx(s); 31254007Sfujita 31354007Sfujita return; 31454007Sfujita 31554007Sfujita done: 31654007Sfujita biodone(bp); 31754007Sfujita } 31854007Sfujita 31954007Sfujita int 32054007Sfujita sdustart(unit) 32154007Sfujita register int unit; 32254007Sfujita { 32354007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 32454007Sfujita register struct hp_device *hp = sc->sc_hd; 32554007Sfujita register struct scsi_queue *dq = &sc->sc_dq; 32654007Sfujita register struct buf *bp = sdtab[unit].b_actf; 32754007Sfujita register struct scsi_fmt_cdb *cmd; 32854007Sfujita 32954007Sfujita cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd; 33054007Sfujita *(int *)(&cmd->cdb[2]) = bp->b_lba; 33154007Sfujita *(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE); 33254007Sfujita 33354007Sfujita dq->dq_cdb = cmd; 33454007Sfujita dq->dq_bp = bp; 33554007Sfujita dq->dq_flags = DQ_DISCONNECT; /* SCSI Disconnect */ 33654007Sfujita 33754007Sfujita if (screq(dq)) 33854007Sfujita sdstart(unit); 33954007Sfujita } 34054007Sfujita 34154007Sfujita int 34254007Sfujita sdstart(unit) 34354007Sfujita register int unit; 34454007Sfujita { 34554007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 34654007Sfujita register struct hp_device *hp = sc->sc_hd; 34754007Sfujita 34854007Sfujita if (hp->hp_dk >= 0) { 34954007Sfujita dk_busy |= 1 << hp->hp_dk; 35054007Sfujita } 35154007Sfujita 35254007Sfujita scstart(hp->hp_ctlr); 35354007Sfujita } 35454007Sfujita 35554007Sfujita 35654007Sfujita /* 35754007Sfujita * Return: 35854007Sfujita * 0 if not really an error 35954007Sfujita * <0 if we should do a retry 36054007Sfujita * >0 if a fatal error 36154007Sfujita */ 36254007Sfujita static int 36354007Sfujita sderror(unit, sc, hp, stat) 36454007Sfujita int unit, stat; 36554007Sfujita register struct sd_softc *sc; 36654007Sfujita register struct hp_device *hp; 36754007Sfujita { 36854007Sfujita int cond = 1; 36954007Sfujita 37054007Sfujita sdsense[unit].status = stat; 37154007Sfujita if (stat & STS_CHECKCOND) { 37254007Sfujita struct scsi_xsense *sp; 37354007Sfujita 37454007Sfujita scsi_request_sense(hp->hp_ctlr, hp->hp_slave, 37554007Sfujita sc->sc_punit, sdsense[unit].sense, 37654007Sfujita sizeof(sdsense[unit].sense)); 37754007Sfujita sp = (struct scsi_xsense *)sdsense[unit].sense; 37854007Sfujita printf("sd%d: scsi sense class %d, code %d", unit, 37954007Sfujita sp->class, sp->code); 38054007Sfujita if (sp->class == 7) { 38154007Sfujita printf(", key %d", sp->key); 38254007Sfujita if (sp->valid) 38354007Sfujita printf(", blk %d", *(int *)&sp->info1); 38454007Sfujita switch (sp->key) { 38554007Sfujita /* no sense, try again */ 38654007Sfujita case 0: 38754007Sfujita cond = -1; 38854007Sfujita break; 38954007Sfujita /* recovered error, not a problem */ 39054007Sfujita case 1: 39154007Sfujita cond = 0; 39254007Sfujita break; 39354007Sfujita } 39454007Sfujita } 39554007Sfujita printf("\n"); 39654007Sfujita } 39754007Sfujita return(cond); 39854007Sfujita } 39954007Sfujita 40054007Sfujita /* 40154007Sfujita * Interrupt 40254007Sfujita */ 40354007Sfujita 40454007Sfujita int 40554007Sfujita sdintr(unit, stat) 40654007Sfujita register int unit; 40754007Sfujita int stat; 40854007Sfujita { 40954007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 41054007Sfujita register struct hp_device *hp = sc->sc_hd; 41154007Sfujita register struct scsi_queue *dq = &sc->sc_dq; 41254007Sfujita register struct buf *bp = dq->dq_bp; 41354007Sfujita int cond; 41454007Sfujita 41554007Sfujita #ifdef DEBUG 41654007Sfujita printf("sdintr(unit = %d, stat = %d)\n", unit, stat); 41754007Sfujita #endif 41854007Sfujita 41954007Sfujita if (stat == SC_IO_TIMEOUT) { 42054007Sfujita printf("sdintr: sd%d timeout error\n", unit, stat); 42154007Sfujita } 42254007Sfujita 42354007Sfujita if (hp->hp_dk >= 0) { 42454007Sfujita dk_busy &=~ (1 << hp->hp_dk); 42554007Sfujita if (stat == 0) { 42654007Sfujita ++dk_seek[hp->hp_dk]; 42754007Sfujita ++dk_xfer[hp->hp_dk]; 42854007Sfujita dk_wds[hp->hp_dk] += bp->b_bcount >> 6; 42954007Sfujita } 43054007Sfujita } 43154007Sfujita 43254007Sfujita if (bp->b_flags & B_READ) { 433*55176Saki sd_iostat[unit].imin = min(dq->dq_imin, sd_iostat[unit].imin); 43454007Sfujita if (dq->dq_imax > sd_iostat[unit].imax) { 43554007Sfujita sd_iostat[unit].imax = dq->dq_imax; 43654007Sfujita #ifdef SD_IOSTAT 43754007Sfujita printf("sdintr: sd%d INPUT MAX = %d, MIN = %d\n", 43854007Sfujita unit, sd_iostat[unit].imax, sd_iostat[unit].imin); 43954007Sfujita #endif 44054007Sfujita } 44154007Sfujita } else { 442*55176Saki sd_iostat[unit].omin = min(dq->dq_omin, sd_iostat[unit].omin); 44354007Sfujita if (dq->dq_omax > sd_iostat[unit].omax) { 44454007Sfujita sd_iostat[unit].omax = dq->dq_omax; 44554007Sfujita #ifdef SD_IOSTAT 44654007Sfujita printf("sdintr: sd%d OUTPUT MAX = %d, MIN = %d\n", 44754007Sfujita unit, sd_iostat[unit].omax, sd_iostat[unit].omin); 44854007Sfujita #endif 44954007Sfujita } 45054007Sfujita } 45154007Sfujita 45254007Sfujita if (stat != 0) { 45354007Sfujita if (stat > 0) { 45454007Sfujita #ifdef DEBUGPRINT 45554007Sfujita dbgprintall(); 45654007Sfujita printf("\n"); 45754007Sfujita #endif 45854007Sfujita cond = sderror(unit, sc, hp, stat); 45954007Sfujita if (cond) { 46054007Sfujita if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) { 46154007Sfujita sdstart(unit); 46254007Sfujita return; 46354007Sfujita } 46454007Sfujita } 46554007Sfujita } else { 46654007Sfujita if (sdtab[unit].b_errcnt++ < SDRETRY) { 46754007Sfujita printf("sdintr: sd%d restart IO request\n", unit); 46854007Sfujita sdstart(unit); 46954007Sfujita return; 47054007Sfujita } 47154007Sfujita } 47254007Sfujita bp->b_flags |= B_ERROR; 47354007Sfujita bp->b_error = EIO; 47454007Sfujita } 47554007Sfujita 47654007Sfujita sdtab[unit].b_errcnt = 0; 47754007Sfujita sdtab[unit].b_actf = bp->b_actf; 47854007Sfujita 47954007Sfujita bp->b_resid = 0; 48054007Sfujita 48154007Sfujita biodone(bp); 48254007Sfujita 48354007Sfujita scfree(dq); 48454007Sfujita 48554007Sfujita if (sdtab[unit].b_actf) { 48654007Sfujita sdustart(unit); 48754007Sfujita } else { 48854007Sfujita sdtab[unit].b_active = 0; 48954007Sfujita } 49054007Sfujita } 49154007Sfujita 49254007Sfujita 49354007Sfujita /* 49454007Sfujita * RAW Device Routines 49554007Sfujita */ 49654007Sfujita 49754007Sfujita int 49854007Sfujita sdread(dev, uio, flags) 49954007Sfujita dev_t dev; 50054007Sfujita struct uio *uio; 50154007Sfujita int flags; 50254007Sfujita { 50354007Sfujita register int unit = sdunit(dev); 50454007Sfujita 50554007Sfujita return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio)); 50654007Sfujita } 50754007Sfujita 50854007Sfujita int 50954007Sfujita sdwrite(dev, uio, flags) 51054007Sfujita dev_t dev; 51154007Sfujita struct uio *uio; 51254007Sfujita int flags; 51354007Sfujita { 51454007Sfujita register int unit = sdunit(dev); 51554007Sfujita 51654007Sfujita return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio)); 51754007Sfujita } 51854007Sfujita 51954007Sfujita int 52054007Sfujita sdioctl(dev, cmd, data, flag, p) 52154007Sfujita dev_t dev; 52254007Sfujita int cmd; 52354007Sfujita caddr_t data; 52454007Sfujita int flag; 52554007Sfujita struct proc *p; 52654007Sfujita { 52754007Sfujita int unit = sdunit(dev); 52854007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 52954007Sfujita register struct disklabel *lp = &sdlabel[unit]; 53054007Sfujita int error = 0; 53154007Sfujita 53254007Sfujita switch (cmd) { 53354007Sfujita 53454007Sfujita case DIOCGDINFO: 53554007Sfujita *(struct disklabel *)data = *lp; 53654007Sfujita break; 53754007Sfujita 53854007Sfujita case DIOCGPART: 53954007Sfujita ((struct partinfo *)data)->disklab = lp; 54054007Sfujita ((struct partinfo *)data)->part = 54154007Sfujita &lp->d_partitions[sdpart(dev)]; 54254007Sfujita break; 54354007Sfujita 54454007Sfujita default: 54554007Sfujita error = ENOTTY; 54654007Sfujita break; 54754007Sfujita } 54854007Sfujita return (error); 54954007Sfujita } 55054007Sfujita 55154007Sfujita 55254007Sfujita /* 55354007Sfujita * Size 55454007Sfujita */ 55554007Sfujita 55654007Sfujita int 55754007Sfujita sdsize(dev) 55854007Sfujita dev_t dev; 55954007Sfujita { 56054007Sfujita register int unit = sdunit(dev); 56154007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 56254007Sfujita 56354007Sfujita if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0) 56454007Sfujita return(-1); 56554007Sfujita 56654007Sfujita return(sdlabel[unit].d_partitions[sdpart(dev)].p_size); 56754007Sfujita } 56854007Sfujita 56954007Sfujita 57054007Sfujita /* 57154007Sfujita * Dump 57254007Sfujita */ 57354007Sfujita 57454007Sfujita int 57554007Sfujita sddump(dev) 57654007Sfujita dev_t dev; 57754007Sfujita { 57854007Sfujita } 57954007Sfujita 58054007Sfujita /* 58154007Sfujita * Disk Subs 58254007Sfujita */ 58354007Sfujita 58454007Sfujita /* 58554007Sfujita * Attempt to read a disk label from a device 58654007Sfujita * using the indicated stategy routine. 58754007Sfujita * The label must be partly set up before this: 58854007Sfujita * secpercyl and anything required in the strategy routine 58954007Sfujita * (e.g., sector size) must be filled in before calling us. 59054007Sfujita * Returns null on success and an error string on failure. 59154007Sfujita */ 59254007Sfujita char * 59354007Sfujita sdreadlabel(dev, strat, lp) 59454007Sfujita dev_t dev; 59554007Sfujita int (*strat)(); 59654007Sfujita register struct disklabel *lp; 59754007Sfujita { 59854007Sfujita register struct buf *bp; 59954007Sfujita struct disklabel *dlp; 60054007Sfujita char *msg = NULL; 60154007Sfujita 60254007Sfujita if (lp->d_secperunit == 0) 60354007Sfujita lp->d_secperunit = 0x1fffffff; 60454007Sfujita lp->d_npartitions = 1; 60554007Sfujita if (lp->d_partitions[0].p_size == 0) 60654007Sfujita lp->d_partitions[0].p_size = 0x1fffffff; 60754007Sfujita lp->d_partitions[0].p_offset = 0; 60854007Sfujita 60954007Sfujita bp = geteblk((int)lp->d_secsize); 61054007Sfujita bp->b_dev = dev; 61154007Sfujita bp->b_blkno = LABELSECTOR; 61254007Sfujita bp->b_bcount = lp->d_secsize; 61354007Sfujita bp->b_flags = B_BUSY | B_READ; 61454007Sfujita (*strat)(bp); 61554007Sfujita if (biowait(bp)) { 61654007Sfujita msg = "I/O error"; 61754007Sfujita } else { 61854007Sfujita for (dlp = (struct disklabel *)bp->b_un.b_addr; 61954007Sfujita dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp)); 62054007Sfujita dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 62154007Sfujita if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { 62254007Sfujita if (msg == NULL) 62354007Sfujita msg = "no disk label"; 62454007Sfujita } else if (dlp->d_npartitions > MAXPARTITIONS || 62554007Sfujita dkcksum(dlp) != 0) 62654007Sfujita msg = "disk label corrupted"; 62754007Sfujita else { 62854007Sfujita *lp = *dlp; 62954007Sfujita msg = NULL; 63054007Sfujita break; 63154007Sfujita } 63254007Sfujita } 63354007Sfujita } 63454007Sfujita bp->b_flags = B_INVAL | B_AGE; 63554007Sfujita brelse(bp); 63654007Sfujita return (msg); 63754007Sfujita } 63854007Sfujita 63954007Sfujita #ifdef notyet 64054007Sfujita 64154007Sfujita /* 64254007Sfujita * Checksum routine for OMRON native disklabel 64354007Sfujita */ 64454007Sfujita 64554007Sfujita #define OMRON_LBLSIZE 512 64654007Sfujita 64754007Sfujita u_short 64854007Sfujita omcksum(omp) 64954007Sfujita register char *omp; 65054007Sfujita { 65154007Sfujita register u_short *start, *end; 65254007Sfujita register u_short sum = 0; 65354007Sfujita 65454007Sfujita start = (u_short *) omp; 65554007Sfujita end = (u_short *) &start[(OMRON_LBLSIZE/sizeof(u_short) - 1)]; 65654007Sfujita while (start < end) 65754007Sfujita sum ^= *start++; 65854007Sfujita 65954007Sfujita printf("omcksum: saved ... 0x%s\n", hexstr(*end, 4)); 66054007Sfujita printf("omcksum: calced ... 0x%s\n", hexstr(sum, 4)); 66154007Sfujita 66254007Sfujita return (sum); 66354007Sfujita } 66454007Sfujita 66554007Sfujita /* 66654007Sfujita * Write disk label back to device after modification. 66754007Sfujita */ 66854007Sfujita sdwritelabel(dev, strat, lp) 66954007Sfujita dev_t dev; 67054007Sfujita int (*strat)(); 67154007Sfujita register struct disklabel *lp; 67254007Sfujita { 67354007Sfujita struct buf *bp; 67454007Sfujita struct disklabel *dlp; 67554007Sfujita int labelpart; 67654007Sfujita int error = 0; 67754007Sfujita 67854007Sfujita labelpart = sdpart(dev); 67954007Sfujita if (lp->d_partitions[labelpart].p_offset != 0) { 68054007Sfujita if (lp->d_partitions[0].p_offset != 0) 68154007Sfujita return (EXDEV); /* not quite right */ 68254007Sfujita labelpart = 0; 68354007Sfujita } 68454007Sfujita 68554007Sfujita bp = geteblk((int)lp->d_secsize); 68654007Sfujita bp->b_dev = makedev(major(dev), sdminor(sdunit(dev), labelpart)); 68754007Sfujita bp->b_blkno = LABELSECTOR; 68854007Sfujita bp->b_bcount = lp->d_secsize; 68954007Sfujita bp->b_flags = B_READ; 69054007Sfujita (*strat)(bp); 69154007Sfujita if (error = biowait(bp)) 69254007Sfujita goto done; 69354007Sfujita 69454007Sfujita for (dlp = (struct disklabel *)bp->b_un.b_addr; 69554007Sfujita dlp <= (struct disklabel *) 69654007Sfujita (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp)); 69754007Sfujita dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 69854007Sfujita if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && 69954007Sfujita dkcksum(dlp) == 0) { 70054007Sfujita omcksum(bp->b_un.b_addr); 70154007Sfujita /* 70254007Sfujita *dlp = *lp; 70354007Sfujita bp->b_flags = B_WRITE; 70454007Sfujita (*strat)(bp); 70554007Sfujita error = biowait(bp); 70654007Sfujita goto done; 70754007Sfujita */ 70854007Sfujita } 70954007Sfujita } 71054007Sfujita error = ESRCH; 71154007Sfujita done: 71254007Sfujita brelse(bp); 71354007Sfujita return (error); 71454007Sfujita } 71554007Sfujita #endif 71654007Sfujita 71754007Sfujita #endif 718