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