157099Sakito /*
257099Sakito * Copyright (c) 1992 OMRON Corporation.
3*63199Sbostic * Copyright (c) 1992, 1993
4*63199Sbostic * The Regents of the University of California. All rights reserved.
557099Sakito *
657099Sakito * This code is derived from software contributed to Berkeley by
757099Sakito * OMRON Corporation.
857099Sakito *
957099Sakito * %sccs.include.redist.c%
1057099Sakito *
11*63199Sbostic * @(#)sd.c 8.1 (Berkeley) 06/10/93
1257099Sakito */
1357099Sakito
1457099Sakito /*
1557099Sakito * sd.c -- SCSI DISK device driver
1657099Sakito * by A.Fujita, FEB-26-1992
1757099Sakito */
1857099Sakito
1957099Sakito
2057099Sakito /*
2157099Sakito * SCSI CCS (Command Command Set) disk driver.
2257099Sakito */
2357099Sakito #define NSD 2
2457099Sakito
2557099Sakito #include <sys/param.h>
2657099Sakito #include <sys/disklabel.h>
2757099Sakito #include <luna68k/dev/scsireg.h>
2857099Sakito #include <luna68k/stand/saio.h>
2957099Sakito #include <luna68k/stand/device.h>
3057099Sakito
3157099Sakito
3257099Sakito int sdinit(), sdstrategy(), sdstart(), sdustart(), sdgo(), sdintr();
3357099Sakito
3457099Sakito struct driver sddriver = {
3557099Sakito sdinit, "sd", sdstart, sdgo, sdintr,
3657099Sakito };
3757099Sakito
3857099Sakito struct disklabel sdlabel[NSD];
3957099Sakito
4057099Sakito struct sd_softc {
4157099Sakito struct hp_device *sc_hd;
4257099Sakito struct devqueue sc_dq;
4357099Sakito int sc_format_pid; /* process using "format" mode */
4457099Sakito short sc_flags;
4557099Sakito short sc_type; /* drive type */
4657099Sakito short sc_punit; /* physical unit (scsi lun) */
4757099Sakito u_short sc_bshift; /* convert device blocks to DEV_BSIZE blks */
4857099Sakito u_int sc_blks; /* number of blocks on device */
4957099Sakito int sc_blksize; /* device block size in bytes */
5057099Sakito u_int sc_wpms; /* average xfer rate in 16 bit wds/sec. */
5157099Sakito } sd_softc[NSD];
5257099Sakito
5357099Sakito /* sc_flags values */
5457099Sakito #define SDF_ALIVE 0x1
5557099Sakito
5657099Sakito #define sdunit(x) ((minor(x) >> 3) & 0x7)
5757099Sakito #define sdpart(x) (minor(x) & 0x7)
5857099Sakito #define sdpunit(x) ((x) & 7)
5957099Sakito
6057099Sakito static struct scsi_inquiry inqbuf;
6157099Sakito static struct scsi_fmt_cdb inq = {
6257099Sakito 6,
6357099Sakito CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
6457099Sakito };
6557099Sakito
6657099Sakito static u_long capbuf[2];
6757099Sakito struct scsi_fmt_cdb cap = {
6857099Sakito 10,
6957099Sakito CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0
7057099Sakito };
7157099Sakito
7257099Sakito int
sdident(sc,hd)7357099Sakito sdident(sc, hd)
7457099Sakito struct sd_softc *sc;
7557099Sakito struct hp_device *hd;
7657099Sakito {
7757099Sakito char idstr[32];
7857099Sakito int unit;
7957099Sakito register int ctlr, slave;
8057099Sakito register int i;
8157099Sakito register int tries = 10;
8257099Sakito
8357099Sakito ctlr = hd->hp_ctlr;
8457099Sakito slave = hd->hp_slave;
8557099Sakito unit = sc->sc_punit;
8657099Sakito
8757099Sakito /*
8857099Sakito * See if unit exists and is a disk then read block size & nblocks.
8957099Sakito */
9057099Sakito while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) {
9157099Sakito if (i < 0 || --tries < 0)
9257099Sakito return (-1);
9357099Sakito if (i == STS_CHECKCOND) {
9457099Sakito u_char sensebuf[8];
9557099Sakito struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
9657099Sakito
9757099Sakito scsi_request_sense(ctlr, slave, unit, sensebuf, 8);
9857099Sakito if (sp->class == 7 && sp->key == 6)
9957099Sakito /* drive doing an RTZ -- give it a while */
10057099Sakito DELAY(1000000);
10157099Sakito }
10257099Sakito DELAY(1000);
10357099Sakito }
10457099Sakito if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf,
10557099Sakito sizeof(inqbuf)) ||
10657099Sakito scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf,
10757099Sakito sizeof(capbuf)))
10857099Sakito /* doesn't exist or not a CCS device */
10957099Sakito return (-1);
11057099Sakito
11157099Sakito switch (inqbuf.type) {
11257099Sakito case 0: /* disk */
11357099Sakito case 4: /* WORM */
11457099Sakito case 5: /* CD-ROM */
11557099Sakito case 7: /* Magneto-optical */
11657099Sakito break;
11757099Sakito default: /* not a disk */
11857099Sakito return (-1);
11957099Sakito }
12057099Sakito sc->sc_blks = capbuf[0];
12157099Sakito sc->sc_blksize = capbuf[1];
12257099Sakito
12357099Sakito bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
12457099Sakito for (i = 27; i > 23; --i)
12557099Sakito if (idstr[i] != ' ')
12657099Sakito break;
12757099Sakito idstr[i+1] = 0;
12857099Sakito for (i = 23; i > 7; --i)
12957099Sakito if (idstr[i] != ' ')
13057099Sakito break;
13157099Sakito idstr[i+1] = 0;
13257099Sakito for (i = 7; i >= 0; --i)
13357099Sakito if (idstr[i] != ' ')
13457099Sakito break;
13557099Sakito idstr[i+1] = 0;
13657099Sakito printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
13757099Sakito &idstr[24]);
13857099Sakito
13957099Sakito printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
14057099Sakito if (sc->sc_blksize != DEV_BSIZE) {
14157099Sakito if (sc->sc_blksize < DEV_BSIZE) {
14257099Sakito printf("sd%d: need %d byte blocks - drive ignored\n",
14357099Sakito unit, DEV_BSIZE);
14457099Sakito return (-1);
14557099Sakito }
14657099Sakito for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
14757099Sakito ++sc->sc_bshift;
14857099Sakito sc->sc_blks <<= sc->sc_bshift;
14957099Sakito }
15057099Sakito sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */
15157099Sakito return(inqbuf.type);
15257099Sakito }
15357099Sakito
15457099Sakito int
sdinit(hd)15557099Sakito sdinit(hd)
15657099Sakito register struct hp_device *hd;
15757099Sakito {
15857099Sakito register struct sd_softc *sc = &sd_softc[hd->hp_unit];
15957099Sakito register struct disklabel *lp;
16057099Sakito char *msg, *readdisklabel();
16157099Sakito
16257099Sakito #ifdef DEBUG
16357099Sakito printf("sdinit: hd->hp_unit = %d\n", hd->hp_unit);
16457099Sakito printf("sdinit: hd->hp_ctlr = %d, hd->hp_slave = %d\n",
16557099Sakito hd->hp_ctlr, hd->hp_slave);
16657099Sakito #endif
16757099Sakito sc->sc_hd = hd;
16857099Sakito sc->sc_punit = sdpunit(hd->hp_flags);
16957099Sakito sc->sc_type = sdident(sc, hd);
17057099Sakito if (sc->sc_type < 0)
17157099Sakito return(0);
17257099Sakito
17357099Sakito /*
17457099Sakito * Use the default sizes until we've read the label,
17557099Sakito * or longer if there isn't one there.
17657099Sakito */
17757099Sakito lp = &sdlabel[hd->hp_unit];
17857099Sakito
17957099Sakito if (lp->d_secpercyl == 0) {
18057099Sakito lp->d_secsize = DEV_BSIZE;
18157099Sakito lp->d_nsectors = 32;
18257099Sakito lp->d_ntracks = 20;
18357099Sakito lp->d_secpercyl = 32*20;
18457099Sakito lp->d_npartitions = 1;
18557099Sakito lp->d_partitions[0].p_offset = 0;
18657099Sakito lp->d_partitions[0].p_size = LABELSECTOR + 1;
18757099Sakito }
18857099Sakito
18957099Sakito /*
19057099Sakito * read disklabel
19157099Sakito */
19257099Sakito if (msg = readdisklabel(hd->hp_slave, sdstrategy, lp)) {
19357099Sakito if (msg != NULL)
19457099Sakito printf("sd%d: %s\n", hd->hp_unit, msg);
19557099Sakito }
19657099Sakito
19757099Sakito sc->sc_flags = SDF_ALIVE;
19857099Sakito return(1);
19957099Sakito }
20057099Sakito
20157099Sakito int
sdopen(io)20257099Sakito sdopen(io)
20357099Sakito struct iob *io;
20457099Sakito {
20557099Sakito register int unit = io->i_unit;
20657099Sakito register struct disklabel *lp;
20757099Sakito
20857099Sakito if (unit < 0 || unit >= NSD)
20957099Sakito return(-1);
21057099Sakito
21157099Sakito lp = &sdlabel[unit];
21257099Sakito io->i_boff = lp->d_partitions[io->i_boff].p_offset;
21357099Sakito }
21457099Sakito
21557099Sakito static struct scsi_fmt_cdb cdb_read = {
21657099Sakito 10,
21757099Sakito CMD_READ_EXT, 0, 0, 0, 0, 0, 0, 0, 0, 0
21857099Sakito };
21957099Sakito
22057099Sakito static struct scsi_fmt_cdb cdb_write = {
22157099Sakito 6,
22257099Sakito CMD_WRITE_EXT, 0, 0, 0, 0, 0, 0, 0, 0, 0
22357099Sakito };
22457099Sakito
22557099Sakito int
sdstrategy(io,func)22657099Sakito sdstrategy(io, func)
22757099Sakito register struct iob *io;
22857099Sakito register int func;
22957099Sakito {
23057099Sakito int unit = io->i_unit;
23157099Sakito struct sd_softc *sc = &sd_softc[unit];
23257099Sakito struct scsi_fmt_cdb *cdb;
23357099Sakito daddr_t blk = io->i_bn >> sc->sc_bshift;
23457099Sakito u_int nblk = io->i_cc >> sc->sc_bshift;
23557099Sakito int stat, ctlr, slave, i;
23657099Sakito
23757099Sakito if (unit < 0 || unit >= NSD)
23857099Sakito return(-1);
23957099Sakito
24057099Sakito ctlr = sc->sc_hd->hp_ctlr;
24157099Sakito slave = sc->sc_hd->hp_slave;
24257099Sakito
24357099Sakito if (func == READ)
24457099Sakito cdb = &cdb_read;
24557099Sakito else
24657099Sakito cdb = &cdb_write;
24757099Sakito
24857099Sakito cdb->cdb[2] = (blk & 0xff000000) >> 24;
24957099Sakito cdb->cdb[3] = (blk & 0x00ff0000) >> 16;
25057099Sakito cdb->cdb[4] = (blk & 0x0000ff00) >> 8;
25157099Sakito cdb->cdb[5] = (blk & 0x000000ff);
25257099Sakito
25357099Sakito cdb->cdb[7] = ((nblk >> DEV_BSHIFT) & 0xff00) >> 8;
25457099Sakito cdb->cdb[8] = ((nblk >> DEV_BSHIFT) & 0x00ff);
25557099Sakito
25657099Sakito #ifdef DEBUG
25757099Sakito printf("sdstrategy: io->i_unit = %d\n", io->i_unit);
25857099Sakito printf("sdstrategy: blk = %d (0x%x), nblk = %d (0x%x)\n", blk, blk, nblk, nblk);
25957099Sakito for (i = 0; i < 10; i++)
26057099Sakito printf("sdstrategy: cdb[%d] = 0x%x\n", i, cdb->cdb[i]);
26157099Sakito printf("sdstrategy: ctlr = %d, slave = %d\n", ctlr, slave);
26257099Sakito #endif
26357099Sakito stat = scsi_immed_command(ctlr, slave, sc->sc_punit, cdb, io->i_ma, io->i_cc);
26457099Sakito
26557099Sakito return(io->i_cc);
26657099Sakito }
26757099Sakito
26857099Sakito int
sdustart()26957099Sakito sdustart()
27057099Sakito {
27157099Sakito }
27257099Sakito
27357099Sakito int
sdstart()27457099Sakito sdstart()
27557099Sakito {
27657099Sakito }
27757099Sakito
27857099Sakito int
sdgo()27957099Sakito sdgo()
28057099Sakito {
28157099Sakito }
28257099Sakito
28357099Sakito int
sdintr()28457099Sakito sdintr()
28557099Sakito {
28657099Sakito }
28757099Sakito
28857099Sakito int
sdread(dev,blk,nblk,buff,len)28957099Sakito sdread(dev, blk, nblk, buff, len)
29057099Sakito dev_t dev;
29157099Sakito u_int blk;
29257099Sakito u_int nblk;
29357099Sakito u_char *buff;
29457099Sakito u_int len;
29557099Sakito {
29657099Sakito register int unit = sdunit(dev);
29757099Sakito register int part = sdpart(dev);
29857099Sakito struct sd_softc *sc = &sd_softc[unit];
29957099Sakito struct scsi_fmt_cdb *cdb;
30057099Sakito int stat, ctlr, slave;
30157099Sakito
30257099Sakito ctlr = sc->sc_hd->hp_ctlr;
30357099Sakito slave = sc->sc_hd->hp_slave;
30457099Sakito
30557099Sakito cdb = &cdb_read;
30657099Sakito
30757099Sakito cdb->cdb[2] = (blk & 0xff000000) >> 24;
30857099Sakito cdb->cdb[3] = (blk & 0x00ff0000) >> 16;
30957099Sakito cdb->cdb[4] = (blk & 0x0000ff00) >> 8;
31057099Sakito cdb->cdb[5] = (blk & 0x000000ff);
31157099Sakito
31257099Sakito cdb->cdb[7] = (nblk & 0xff00) >> 8;
31357099Sakito cdb->cdb[8] = (nblk & 0x00ff);
31457099Sakito
31557099Sakito stat = scsi_immed_command(ctlr, slave, sc->sc_punit, cdb, buff, len);
31657099Sakito
31757099Sakito if (stat == 0)
31857099Sakito return(1);
31957099Sakito else
32057099Sakito return(0);
32157099Sakito }
32257099Sakito
32357099Sakito int
sdioctl(dev,data)32457099Sakito sdioctl(dev, data)
32557099Sakito dev_t dev;
32657099Sakito u_long data[];
32757099Sakito {
32857099Sakito register int unit = sdunit(dev);
32957099Sakito register int part = sdpart(dev);
33057099Sakito register struct disklabel *lp;
33157099Sakito
33257099Sakito if (unit < 0 || unit >= NSD)
33357099Sakito return(0);
33457099Sakito
33557099Sakito if (part < 0 || part >= MAXPARTITIONS)
33657099Sakito return(0);
33757099Sakito
33857099Sakito lp = &sdlabel[unit];
33957099Sakito data[0] = lp->d_partitions[part].p_offset;
34057099Sakito data[1] = lp->d_partitions[part].p_size;
34157099Sakito
34257099Sakito return(1);
34357099Sakito }
344