154007Sfujita /* 254007Sfujita * Copyright (c) 1992 OMRON Corporation. 3*63192Sbostic * Copyright (c) 1992, 1993 4*63192Sbostic * The Regents of the University of California. 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*63192Sbostic * @(#)sd.c 8.1 (Berkeley) 06/10/93 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 2556519Sbostic #include <sys/param.h> 2656519Sbostic #include <sys/systm.h> 2756519Sbostic #include <sys/buf.h> 2856519Sbostic #include <sys/dkstat.h> 2956519Sbostic #include <sys/proc.h> 3056519Sbostic #include <sys/disklabel.h> 3154007Sfujita 3256519Sbostic #include <luna68k/dev/device.h> 3356519Sbostic #include <luna68k/dev/scsireg.h> 3456519Sbostic #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 /* 25158693Sakito * Close 25258693Sakito */ 25358693Sakito 25458693Sakito int 25558693Sakito sdclose(dev, flag, mode, p) 25658693Sakito dev_t dev; 25758693Sakito int flag, mode; 25858693Sakito struct proc *p; 25958693Sakito { 26058693Sakito } 26158693Sakito 26258693Sakito /* 26354007Sfujita * Strategy 26454007Sfujita */ 26554007Sfujita 26654007Sfujita int 26754007Sfujita sdstrategy(bp) 26854007Sfujita register struct buf *bp; 26954007Sfujita { 27054007Sfujita register int unit = sdunit(bp->b_dev); 27154007Sfujita register int part = sdpart(bp->b_dev); 27254007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 27354007Sfujita register struct disklabel *lp = &sdlabel[unit]; 27454007Sfujita register struct partition *pp = &(lp->d_partitions[part]); 27554007Sfujita register struct buf *dp = &sdtab[unit]; 27654007Sfujita register daddr_t bn; 27754007Sfujita register int sz, s; 27854007Sfujita 27954007Sfujita bn = bp->b_blkno; 28054007Sfujita sz = howmany(bp->b_bcount, DEV_BSIZE); 28154007Sfujita 28254007Sfujita /* check that tracsfer is within a drive's partition */ 28354007Sfujita 28454007Sfujita if (bn < 0 || (bn + sz) > pp->p_size) { 28554007Sfujita sz = pp->p_size - bn; 28654007Sfujita if (sz == 0) { 28754007Sfujita bp->b_resid = bp->b_bcount; 28854007Sfujita goto done; 28954007Sfujita } 29054007Sfujita if (sz < 0) { 29154007Sfujita bp->b_error = EINVAL; 29254007Sfujita bp->b_flags |= B_ERROR; 29354007Sfujita goto done; 29454007Sfujita } 29554007Sfujita bp->b_bcount = dbtob(sz); 29654007Sfujita } 29754007Sfujita 29854007Sfujita /* calculate LBA for transfer */ 29954007Sfujita 30054007Sfujita bp->b_lba = bn + pp->p_offset; 30154007Sfujita 30254007Sfujita /* raise priority to block sdintr */ 30354007Sfujita 30454007Sfujita s = splbio(); 30554007Sfujita 30654007Sfujita /* call disksort to sort request into drive queue */ 30754007Sfujita 30854007Sfujita disksort(dp, bp); 30954007Sfujita 31054007Sfujita if (dp->b_active == 0) { /* */ 31154007Sfujita dp->b_active = 1; 31254007Sfujita sdustart(unit); 31354007Sfujita } 31454007Sfujita 31554007Sfujita /* lower priority */ 31654007Sfujita 31754007Sfujita splx(s); 31854007Sfujita 31954007Sfujita return; 32054007Sfujita 32154007Sfujita done: 32254007Sfujita biodone(bp); 32354007Sfujita } 32454007Sfujita 32554007Sfujita int 32654007Sfujita sdustart(unit) 32754007Sfujita register int unit; 32854007Sfujita { 32954007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 33054007Sfujita register struct hp_device *hp = sc->sc_hd; 33154007Sfujita register struct scsi_queue *dq = &sc->sc_dq; 33254007Sfujita register struct buf *bp = sdtab[unit].b_actf; 33354007Sfujita register struct scsi_fmt_cdb *cmd; 33454007Sfujita 33554007Sfujita cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd; 33654007Sfujita *(int *)(&cmd->cdb[2]) = bp->b_lba; 33754007Sfujita *(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE); 33854007Sfujita 33954007Sfujita dq->dq_cdb = cmd; 34054007Sfujita dq->dq_bp = bp; 34154007Sfujita dq->dq_flags = DQ_DISCONNECT; /* SCSI Disconnect */ 34254007Sfujita 34354007Sfujita if (screq(dq)) 34454007Sfujita sdstart(unit); 34554007Sfujita } 34654007Sfujita 34754007Sfujita int 34854007Sfujita sdstart(unit) 34954007Sfujita register int unit; 35054007Sfujita { 35154007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 35254007Sfujita register struct hp_device *hp = sc->sc_hd; 35354007Sfujita 35454007Sfujita if (hp->hp_dk >= 0) { 35554007Sfujita dk_busy |= 1 << hp->hp_dk; 35654007Sfujita } 35754007Sfujita 35854007Sfujita scstart(hp->hp_ctlr); 35954007Sfujita } 36054007Sfujita 36154007Sfujita 36254007Sfujita /* 36354007Sfujita * Return: 36454007Sfujita * 0 if not really an error 36554007Sfujita * <0 if we should do a retry 36654007Sfujita * >0 if a fatal error 36754007Sfujita */ 36854007Sfujita static int 36954007Sfujita sderror(unit, sc, hp, stat) 37054007Sfujita int unit, stat; 37154007Sfujita register struct sd_softc *sc; 37254007Sfujita register struct hp_device *hp; 37354007Sfujita { 37454007Sfujita int cond = 1; 37554007Sfujita 37654007Sfujita sdsense[unit].status = stat; 37754007Sfujita if (stat & STS_CHECKCOND) { 37854007Sfujita struct scsi_xsense *sp; 37954007Sfujita 38054007Sfujita scsi_request_sense(hp->hp_ctlr, hp->hp_slave, 38154007Sfujita sc->sc_punit, sdsense[unit].sense, 38254007Sfujita sizeof(sdsense[unit].sense)); 38354007Sfujita sp = (struct scsi_xsense *)sdsense[unit].sense; 38454007Sfujita printf("sd%d: scsi sense class %d, code %d", unit, 38554007Sfujita sp->class, sp->code); 38654007Sfujita if (sp->class == 7) { 38754007Sfujita printf(", key %d", sp->key); 38854007Sfujita if (sp->valid) 38954007Sfujita printf(", blk %d", *(int *)&sp->info1); 39054007Sfujita switch (sp->key) { 39154007Sfujita /* no sense, try again */ 39254007Sfujita case 0: 39354007Sfujita cond = -1; 39454007Sfujita break; 39554007Sfujita /* recovered error, not a problem */ 39654007Sfujita case 1: 39754007Sfujita cond = 0; 39854007Sfujita break; 39954007Sfujita } 40054007Sfujita } 40154007Sfujita printf("\n"); 40254007Sfujita } 40354007Sfujita return(cond); 40454007Sfujita } 40554007Sfujita 40654007Sfujita /* 40754007Sfujita * Interrupt 40854007Sfujita */ 40954007Sfujita 41054007Sfujita int 41154007Sfujita sdintr(unit, stat) 41254007Sfujita register int unit; 41354007Sfujita int stat; 41454007Sfujita { 41554007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 41654007Sfujita register struct hp_device *hp = sc->sc_hd; 41754007Sfujita register struct scsi_queue *dq = &sc->sc_dq; 41854007Sfujita register struct buf *bp = dq->dq_bp; 41954007Sfujita int cond; 42054007Sfujita 42154007Sfujita if (stat == SC_IO_TIMEOUT) { 42254007Sfujita printf("sdintr: sd%d timeout error\n", unit, stat); 42354007Sfujita } 42454007Sfujita 42554007Sfujita if (hp->hp_dk >= 0) { 42654007Sfujita dk_busy &=~ (1 << hp->hp_dk); 42754007Sfujita if (stat == 0) { 42854007Sfujita ++dk_seek[hp->hp_dk]; 42954007Sfujita ++dk_xfer[hp->hp_dk]; 43054007Sfujita dk_wds[hp->hp_dk] += bp->b_bcount >> 6; 43154007Sfujita } 43254007Sfujita } 43354007Sfujita 43454007Sfujita if (bp->b_flags & B_READ) { 43555176Saki sd_iostat[unit].imin = min(dq->dq_imin, sd_iostat[unit].imin); 43654007Sfujita if (dq->dq_imax > sd_iostat[unit].imax) { 43754007Sfujita sd_iostat[unit].imax = dq->dq_imax; 43854007Sfujita #ifdef SD_IOSTAT 43954007Sfujita printf("sdintr: sd%d INPUT MAX = %d, MIN = %d\n", 44054007Sfujita unit, sd_iostat[unit].imax, sd_iostat[unit].imin); 44154007Sfujita #endif 44254007Sfujita } 44354007Sfujita } else { 44455176Saki sd_iostat[unit].omin = min(dq->dq_omin, sd_iostat[unit].omin); 44554007Sfujita if (dq->dq_omax > sd_iostat[unit].omax) { 44654007Sfujita sd_iostat[unit].omax = dq->dq_omax; 44754007Sfujita #ifdef SD_IOSTAT 44854007Sfujita printf("sdintr: sd%d OUTPUT MAX = %d, MIN = %d\n", 44954007Sfujita unit, sd_iostat[unit].omax, sd_iostat[unit].omin); 45054007Sfujita #endif 45154007Sfujita } 45254007Sfujita } 45354007Sfujita 45454007Sfujita if (stat != 0) { 45554007Sfujita if (stat > 0) { 45654007Sfujita #ifdef DEBUGPRINT 45754007Sfujita dbgprintall(); 45854007Sfujita printf("\n"); 45954007Sfujita #endif 46054007Sfujita cond = sderror(unit, sc, hp, stat); 46154007Sfujita if (cond) { 46254007Sfujita if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) { 46354007Sfujita sdstart(unit); 46454007Sfujita return; 46554007Sfujita } 46654007Sfujita } 46754007Sfujita } else { 46854007Sfujita if (sdtab[unit].b_errcnt++ < SDRETRY) { 46954007Sfujita printf("sdintr: sd%d restart IO request\n", unit); 47054007Sfujita sdstart(unit); 47154007Sfujita return; 47254007Sfujita } 47354007Sfujita } 47454007Sfujita bp->b_flags |= B_ERROR; 47554007Sfujita bp->b_error = EIO; 47654007Sfujita } 47754007Sfujita 47854007Sfujita sdtab[unit].b_errcnt = 0; 47954007Sfujita sdtab[unit].b_actf = bp->b_actf; 48054007Sfujita 48154007Sfujita bp->b_resid = 0; 48254007Sfujita 48354007Sfujita biodone(bp); 48454007Sfujita 48554007Sfujita scfree(dq); 48654007Sfujita 48754007Sfujita if (sdtab[unit].b_actf) { 48854007Sfujita sdustart(unit); 48954007Sfujita } else { 49054007Sfujita sdtab[unit].b_active = 0; 49154007Sfujita } 49254007Sfujita } 49354007Sfujita 49454007Sfujita 49554007Sfujita /* 49654007Sfujita * RAW Device Routines 49754007Sfujita */ 49854007Sfujita 49954007Sfujita int 50054007Sfujita sdread(dev, uio, flags) 50154007Sfujita dev_t dev; 50254007Sfujita struct uio *uio; 50354007Sfujita int flags; 50454007Sfujita { 50554007Sfujita register int unit = sdunit(dev); 50654007Sfujita 50754007Sfujita return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio)); 50854007Sfujita } 50954007Sfujita 51054007Sfujita int 51154007Sfujita sdwrite(dev, uio, flags) 51254007Sfujita dev_t dev; 51354007Sfujita struct uio *uio; 51454007Sfujita int flags; 51554007Sfujita { 51654007Sfujita register int unit = sdunit(dev); 51754007Sfujita 51854007Sfujita return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio)); 51954007Sfujita } 52054007Sfujita 52154007Sfujita int 52254007Sfujita sdioctl(dev, cmd, data, flag, p) 52354007Sfujita dev_t dev; 52454007Sfujita int cmd; 52554007Sfujita caddr_t data; 52654007Sfujita int flag; 52754007Sfujita struct proc *p; 52854007Sfujita { 52954007Sfujita int unit = sdunit(dev); 53054007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 53154007Sfujita register struct disklabel *lp = &sdlabel[unit]; 53254007Sfujita int error = 0; 53354007Sfujita 53454007Sfujita switch (cmd) { 53554007Sfujita 53654007Sfujita case DIOCGDINFO: 53754007Sfujita *(struct disklabel *)data = *lp; 53854007Sfujita break; 53954007Sfujita 54054007Sfujita case DIOCGPART: 54154007Sfujita ((struct partinfo *)data)->disklab = lp; 54254007Sfujita ((struct partinfo *)data)->part = 54354007Sfujita &lp->d_partitions[sdpart(dev)]; 54454007Sfujita break; 54554007Sfujita 54657378Sakito case DIOCWLABEL: 54757378Sakito case DIOCSDINFO: 54857378Sakito case DIOCWDINFO: 54957378Sakito break; 55057378Sakito 55154007Sfujita default: 55254007Sfujita error = ENOTTY; 55354007Sfujita break; 55454007Sfujita } 55554007Sfujita return (error); 55654007Sfujita } 55754007Sfujita 55854007Sfujita 55954007Sfujita /* 56054007Sfujita * Size 56154007Sfujita */ 56254007Sfujita 56354007Sfujita int 56454007Sfujita sdsize(dev) 56554007Sfujita dev_t dev; 56654007Sfujita { 56754007Sfujita register int unit = sdunit(dev); 56854007Sfujita register struct sd_softc *sc = &sd_softc[unit]; 56954007Sfujita 57054007Sfujita if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0) 57154007Sfujita return(-1); 57254007Sfujita 57354007Sfujita return(sdlabel[unit].d_partitions[sdpart(dev)].p_size); 57454007Sfujita } 57554007Sfujita 57654007Sfujita 57754007Sfujita /* 57854007Sfujita * Dump 57954007Sfujita */ 58054007Sfujita 58154007Sfujita int 58254007Sfujita sddump(dev) 58354007Sfujita dev_t dev; 58454007Sfujita { 58554007Sfujita } 58654007Sfujita 58754007Sfujita /* 58854007Sfujita * Disk Subs 58954007Sfujita */ 59054007Sfujita 59154007Sfujita /* 59254007Sfujita * Attempt to read a disk label from a device 59354007Sfujita * using the indicated stategy routine. 59454007Sfujita * The label must be partly set up before this: 59554007Sfujita * secpercyl and anything required in the strategy routine 59654007Sfujita * (e.g., sector size) must be filled in before calling us. 59754007Sfujita * Returns null on success and an error string on failure. 59854007Sfujita */ 59954007Sfujita char * 60054007Sfujita sdreadlabel(dev, strat, lp) 60154007Sfujita dev_t dev; 60254007Sfujita int (*strat)(); 60354007Sfujita register struct disklabel *lp; 60454007Sfujita { 60554007Sfujita register struct buf *bp; 60654007Sfujita struct disklabel *dlp; 60754007Sfujita char *msg = NULL; 60854007Sfujita 60954007Sfujita if (lp->d_secperunit == 0) 61054007Sfujita lp->d_secperunit = 0x1fffffff; 61154007Sfujita lp->d_npartitions = 1; 61254007Sfujita if (lp->d_partitions[0].p_size == 0) 61354007Sfujita lp->d_partitions[0].p_size = 0x1fffffff; 61454007Sfujita lp->d_partitions[0].p_offset = 0; 61554007Sfujita 61654007Sfujita bp = geteblk((int)lp->d_secsize); 61754007Sfujita bp->b_dev = dev; 61854007Sfujita bp->b_blkno = LABELSECTOR; 61954007Sfujita bp->b_bcount = lp->d_secsize; 62054007Sfujita bp->b_flags = B_BUSY | B_READ; 62154007Sfujita (*strat)(bp); 62254007Sfujita if (biowait(bp)) { 62354007Sfujita msg = "I/O error"; 62454007Sfujita } else { 62554007Sfujita for (dlp = (struct disklabel *)bp->b_un.b_addr; 62654007Sfujita dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp)); 62754007Sfujita dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 62854007Sfujita if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { 62954007Sfujita if (msg == NULL) 63054007Sfujita msg = "no disk label"; 63154007Sfujita } else if (dlp->d_npartitions > MAXPARTITIONS || 63254007Sfujita dkcksum(dlp) != 0) 63354007Sfujita msg = "disk label corrupted"; 63454007Sfujita else { 63554007Sfujita *lp = *dlp; 63654007Sfujita msg = NULL; 63754007Sfujita break; 63854007Sfujita } 63954007Sfujita } 64054007Sfujita } 64154007Sfujita bp->b_flags = B_INVAL | B_AGE; 64254007Sfujita brelse(bp); 64354007Sfujita return (msg); 64454007Sfujita } 64554007Sfujita 64654007Sfujita #ifdef notyet 64754007Sfujita 64854007Sfujita /* 64954007Sfujita * Checksum routine for OMRON native disklabel 65054007Sfujita */ 65154007Sfujita 65254007Sfujita #define OMRON_LBLSIZE 512 65354007Sfujita 65454007Sfujita u_short 65554007Sfujita omcksum(omp) 65654007Sfujita register char *omp; 65754007Sfujita { 65854007Sfujita register u_short *start, *end; 65954007Sfujita register u_short sum = 0; 66054007Sfujita 66154007Sfujita start = (u_short *) omp; 66254007Sfujita end = (u_short *) &start[(OMRON_LBLSIZE/sizeof(u_short) - 1)]; 66354007Sfujita while (start < end) 66454007Sfujita sum ^= *start++; 66554007Sfujita 66654007Sfujita printf("omcksum: saved ... 0x%s\n", hexstr(*end, 4)); 66754007Sfujita printf("omcksum: calced ... 0x%s\n", hexstr(sum, 4)); 66854007Sfujita 66954007Sfujita return (sum); 67054007Sfujita } 67154007Sfujita 67254007Sfujita /* 67354007Sfujita * Write disk label back to device after modification. 67454007Sfujita */ 67554007Sfujita sdwritelabel(dev, strat, lp) 67654007Sfujita dev_t dev; 67754007Sfujita int (*strat)(); 67854007Sfujita register struct disklabel *lp; 67954007Sfujita { 68054007Sfujita struct buf *bp; 68154007Sfujita struct disklabel *dlp; 68254007Sfujita int labelpart; 68354007Sfujita int error = 0; 68454007Sfujita 68554007Sfujita labelpart = sdpart(dev); 68654007Sfujita if (lp->d_partitions[labelpart].p_offset != 0) { 68754007Sfujita if (lp->d_partitions[0].p_offset != 0) 68854007Sfujita return (EXDEV); /* not quite right */ 68954007Sfujita labelpart = 0; 69054007Sfujita } 69154007Sfujita 69254007Sfujita bp = geteblk((int)lp->d_secsize); 69354007Sfujita bp->b_dev = makedev(major(dev), sdminor(sdunit(dev), labelpart)); 69454007Sfujita bp->b_blkno = LABELSECTOR; 69554007Sfujita bp->b_bcount = lp->d_secsize; 69654007Sfujita bp->b_flags = B_READ; 69754007Sfujita (*strat)(bp); 69854007Sfujita if (error = biowait(bp)) 69954007Sfujita goto done; 70054007Sfujita 70154007Sfujita for (dlp = (struct disklabel *)bp->b_un.b_addr; 70254007Sfujita dlp <= (struct disklabel *) 70354007Sfujita (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp)); 70454007Sfujita dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 70554007Sfujita if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && 70654007Sfujita dkcksum(dlp) == 0) { 70754007Sfujita omcksum(bp->b_un.b_addr); 70854007Sfujita /* 70954007Sfujita *dlp = *lp; 71054007Sfujita bp->b_flags = B_WRITE; 71154007Sfujita (*strat)(bp); 71254007Sfujita error = biowait(bp); 71354007Sfujita goto done; 71454007Sfujita */ 71554007Sfujita } 71654007Sfujita } 71754007Sfujita error = ESRCH; 71854007Sfujita done: 71954007Sfujita brelse(bp); 72054007Sfujita return (error); 72154007Sfujita } 72254007Sfujita #endif 72354007Sfujita 72454007Sfujita #endif 725