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