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