157101Sakito /*
257101Sakito * Copyright (c) 1992 OMRON Corporation.
3*63199Sbostic * Copyright (c) 1992, 1993
4*63199Sbostic * The Regents of the University of California. All rights reserved.
557101Sakito *
657101Sakito * This code is derived from software contributed to Berkeley by
757101Sakito * OMRON Corporation.
857101Sakito *
957101Sakito * %sccs.include.redist.c%
1057101Sakito *
11*63199Sbostic * @(#)st.c 8.1 (Berkeley) 06/10/93
1257101Sakito */
1357101Sakito
1457101Sakito /*
1557101Sakito * st.c -- SCSI Disk Device Driver for LUNA-68K
1657101Sakito * remaked by A.Fujita, MAR-22-1992
1757101Sakito */
1857101Sakito
1957101Sakito /*
2057101Sakito * SCSI CCS (Command Command Set) disk driver.
2157101Sakito */
2257101Sakito #define NST 1
2357101Sakito
2457101Sakito #include <sys/param.h>
2557101Sakito #include <sys/mtio.h>
2657101Sakito #include <luna68k/dev/scsireg.h>
2757101Sakito #include <luna68k/stand/device.h>
2857101Sakito
2957101Sakito extern int scsi_test_unit_rdy();
3057101Sakito extern int scsi_request_sense();
3157101Sakito extern int scsi_immed_command();
3257101Sakito
3357101Sakito extern int scgo();
3457101Sakito extern void scfree();
3557101Sakito
3657101Sakito int stinit(), ststrategy(), ststart(), stintr();
3757101Sakito
3857101Sakito struct driver stdriver = {
3957101Sakito stinit, "st", ststart, (int (*)()) 0, stintr, (int (*)()) 0
4057101Sakito };
4157101Sakito
4257101Sakito struct st_softc {
4357101Sakito struct hp_device *sc_hd;
4457101Sakito struct devqueue sc_dq;
4557101Sakito int sc_flags;
4657101Sakito short sc_type; /* drive type */
4757101Sakito short sc_punit; /* physical unit (scsi lun) */
4857101Sakito } st_softc[NST];
4957101Sakito
5057101Sakito /* softc flags */
5157101Sakito #define STF_ALIVE 0x0001
5257101Sakito #define STF_OPEN 0x0002
5357101Sakito #define STF_WMODE 0x0004
5457101Sakito #define STF_WRTTN 0x0008
5557101Sakito #define STF_CMD 0x0010
5657101Sakito #define STF_LEOT 0x0020
5757101Sakito #define STF_MOVED 0x0040
5857101Sakito
5957101Sakito struct scsi_fmt_sense stsense[NST];
6057101Sakito
6157101Sakito #define stunit(x) (minor(x) & 3)
6257101Sakito #define stpunit(x) ((x) & 7)
6357101Sakito
6457101Sakito #define STDEV_NOREWIND 0x04
6557101Sakito #define STDEV_HIDENSITY 0x08
6657101Sakito #define STDEV_EXSFMK 0x10
6757101Sakito #define STDEV_FIXEDBLK 0x20
6857101Sakito
6957101Sakito #define b_lba b_resid
7057101Sakito
7157101Sakito #define STRETRY 2 /* IO retry count */
7257101Sakito
7357101Sakito
7457101Sakito /*
7557101Sakito * Initialize
7657101Sakito */
7757101Sakito
7857101Sakito int
stinit(hd)7957101Sakito stinit(hd)
8057101Sakito register struct hp_device *hd;
8157101Sakito {
8257101Sakito register struct st_softc *sc = &st_softc[hd->hp_unit];
8357101Sakito
8457101Sakito sc->sc_hd = hd;
8557101Sakito sc->sc_punit = stpunit(hd->hp_flags);
8657101Sakito sc->sc_type = stident(sc, hd);
8757101Sakito if (sc->sc_type < 0)
8857101Sakito return(0);
8957101Sakito sc->sc_dq.dq_ctlr = hd->hp_ctlr;
9057101Sakito sc->sc_dq.dq_unit = hd->hp_unit;
9157101Sakito sc->sc_dq.dq_slave = hd->hp_slave;
9257101Sakito sc->sc_dq.dq_driver = &stdriver;
9357101Sakito sc->sc_flags = STF_ALIVE;
9457101Sakito return(1);
9557101Sakito }
9657101Sakito
9757101Sakito static struct scsi_inquiry inqbuf;
9857101Sakito static struct scsi_fmt_cdb inq = {
9957101Sakito 6,
10057101Sakito CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
10157101Sakito };
10257101Sakito
10357101Sakito int
stident(sc,hd)10457101Sakito stident(sc, hd)
10557101Sakito struct st_softc *sc;
10657101Sakito struct hp_device *hd;
10757101Sakito {
10857101Sakito char idstr[32];
10957101Sakito int unit;
11057101Sakito register int ctlr, slave;
11157101Sakito register int i, stat;
11257101Sakito register int tries = 10;
11357101Sakito
11457101Sakito ctlr = hd->hp_ctlr;
11557101Sakito slave = hd->hp_slave;
11657101Sakito unit = sc->sc_punit;
11757101Sakito
11857101Sakito /*
11957101Sakito * See if unit exists and is a disk then read block size & nblocks.
12057101Sakito */
12157101Sakito while ((stat = scsi_immed_command(ctlr, slave, unit,
12257101Sakito &inq, (u_char *)&inqbuf, sizeof(inqbuf))) != 0) {
12357101Sakito if (stat < 0 || --tries < 0)
12457101Sakito return (-1);
12557101Sakito DELAY(1000);
12657101Sakito }
12757101Sakito
12857101Sakito if (stat)
12957101Sakito return (-1);
13057101Sakito
13157101Sakito switch (inqbuf.type) {
13257101Sakito case 1: /* tape */
13357101Sakito break;
13457101Sakito default: /* not a disk */
13557101Sakito return (-1);
13657101Sakito }
13757101Sakito
13857101Sakito bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
13957101Sakito for (i = 27; i > 23; --i)
14057101Sakito if (idstr[i] != ' ')
14157101Sakito break;
14257101Sakito idstr[i+1] = 0;
14357101Sakito for (i = 23; i > 7; --i)
14457101Sakito if (idstr[i] != ' ')
14557101Sakito break;
14657101Sakito idstr[i+1] = 0;
14757101Sakito for (i = 7; i >= 0; --i)
14857101Sakito if (idstr[i] != ' ')
14957101Sakito break;
15057101Sakito idstr[i+1] = 0;
15157101Sakito printf("st%d: %s %s rev %s\n", hd->hp_unit, idstr, &idstr[8],
15257101Sakito &idstr[24]);
15357101Sakito
15457101Sakito return(inqbuf.type);
15557101Sakito }
15657101Sakito
15757101Sakito
15857101Sakito /*
15957101Sakito * Open
16057101Sakito */
16157101Sakito
16257101Sakito int
stopen(dev)16357101Sakito stopen(dev)
16457101Sakito dev_t dev;
16557101Sakito {
16657101Sakito register int unit = stunit(dev);
16757101Sakito register struct st_softc *sc = &st_softc[unit];
16857101Sakito
16957101Sakito if (unit >= NST || (sc->sc_flags & STF_ALIVE) == 0)
17057101Sakito return(-1);
17157101Sakito if (sc->sc_flags & STF_OPEN)
17257101Sakito return(-1);
17357101Sakito
17457101Sakito sc->sc_flags |= STF_OPEN;
17557101Sakito sc->sc_flags |= STF_WMODE;
17657101Sakito sc->sc_flags &= ~STF_MOVED;
17757101Sakito
17857101Sakito return(0);
17957101Sakito }
18057101Sakito
18157101Sakito /*ARGSUSED*/
stclose(dev)18257101Sakito stclose(dev)
18357101Sakito dev_t dev;
18457101Sakito {
18557101Sakito register int unit = stunit(dev);
18657101Sakito register struct st_softc *sc = &st_softc[unit];
18757101Sakito
18857101Sakito printf("st: sc->sc_flags = 0x%s\n", hexstr(sc->sc_flags, 8));
18957101Sakito
19057101Sakito if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {
19157101Sakito st_write_EOF(dev);
19257101Sakito }
19357101Sakito
19457101Sakito if ((minor(dev) & STDEV_NOREWIND) == 0) {
19557101Sakito st_rewind(dev);
19657101Sakito }
19757101Sakito
19857101Sakito sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN);
19957101Sakito
20057101Sakito return(0);
20157101Sakito }
20257101Sakito
20357101Sakito /*
20457101Sakito * Strategy
20557101Sakito */
20657101Sakito
20757101Sakito int
ststrategy()20857101Sakito ststrategy()
20957101Sakito {
21057101Sakito }
21157101Sakito
21257101Sakito int
ststart(unit)21357101Sakito ststart(unit)
21457101Sakito register int unit;
21557101Sakito {
21657101Sakito }
21757101Sakito
21857101Sakito /*
21957101Sakito * Interrupt
22057101Sakito */
22157101Sakito
22257101Sakito /*
22357101Sakito * Return:
22457101Sakito * 0 if not really an error
22557101Sakito * <0 if we should do a retry
22657101Sakito * >0 if a fatal error
22757101Sakito */
22857101Sakito static int
sterror(unit,sc,hp,stat)22957101Sakito sterror(unit, sc, hp, stat)
23057101Sakito int unit, stat;
23157101Sakito register struct st_softc *sc;
23257101Sakito register struct hp_device *hp;
23357101Sakito {
23457101Sakito int cond = 1;
23557101Sakito
23657101Sakito stsense[unit].status = stat;
23757101Sakito if (stat & STS_CHECKCOND) {
23857101Sakito struct scsi_xsense *sp;
23957101Sakito
24057101Sakito scsi_request_sense(hp->hp_ctlr, hp->hp_slave,
24157101Sakito sc->sc_punit, stsense[unit].sense,
24257101Sakito sizeof(stsense[unit].sense));
24357101Sakito sp = (struct scsi_xsense *)stsense[unit].sense;
24457101Sakito printf("st%d: scsi sense class %d, code %d", unit,
24557101Sakito sp->class, sp->code);
24657101Sakito if (sp->class == 7) {
24757101Sakito printf(", key %d", sp->key);
24857101Sakito if (sp->valid)
24957101Sakito printf(", blk %d", *(int *)&sp->info1);
25057101Sakito switch (sp->key) {
25157101Sakito /* no sense, try again */
25257101Sakito case 0:
25357101Sakito cond = -1;
25457101Sakito break;
25557101Sakito /* recovered error, not a problem */
25657101Sakito case 1:
25757101Sakito cond = 0;
25857101Sakito break;
25957101Sakito }
26057101Sakito }
26157101Sakito printf("\n");
26257101Sakito }
26357101Sakito return(cond);
26457101Sakito }
26557101Sakito
26657101Sakito int
stintr(unit,stat)26757101Sakito stintr(unit, stat)
26857101Sakito register int unit;
26957101Sakito int stat;
27057101Sakito {
27157101Sakito }
27257101Sakito
27357101Sakito
27457101Sakito /*
27557101Sakito * RAW Device Routines
27657101Sakito */
27757101Sakito
27857101Sakito char *
sense_key(key)27957101Sakito sense_key(key)
28057101Sakito int key;
28157101Sakito {
28257101Sakito if (key == 0)
28357101Sakito return("No Sense");
28457101Sakito else if (key == 2)
28557101Sakito return("Not Ready");
28657101Sakito else if (key == 3)
28757101Sakito return("Medium Error");
28857101Sakito else if (key == 4)
28957101Sakito return("Hardware Error");
29057101Sakito else if (key == 5)
29157101Sakito return("Illegal Request");
29257101Sakito else if (key == 6)
29357101Sakito return("Unit Attention");
29457101Sakito else if (key == 7)
29557101Sakito return("Data Protect");
29657101Sakito else if (key == 8)
29757101Sakito return("No Data");
29857101Sakito else if (key == 11)
29957101Sakito return("Aborted Command");
30057101Sakito else if (key == 13)
30157101Sakito return("Volume Overflow");
30257101Sakito else
30357101Sakito return("Unknown Error");
30457101Sakito }
30557101Sakito
30657101Sakito static struct scsi_fmt_cdb st_cmd = { 6, 0, 0, 0, 0, 0, 0 };
30757101Sakito
30857101Sakito u_char sensebuf[8];
30957101Sakito
31057101Sakito int
stread(dev,buf,size)31157101Sakito stread(dev, buf, size)
31257101Sakito dev_t dev;
31357101Sakito char *buf;
31457101Sakito int size;
31557101Sakito {
31657101Sakito register int unit = stunit(dev);
31757101Sakito register struct st_softc *sc = &st_softc[unit];
31857101Sakito register struct scsi_fmt_cdb *cdb = &st_cmd;
31957101Sakito register int nblk = size >> DEV_BSHIFT;
32057101Sakito struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
32157101Sakito int ctlr, slave, stat;
32257101Sakito
32357101Sakito ctlr = sc->sc_hd->hp_ctlr;
32457101Sakito slave = sc->sc_hd->hp_slave;
32557101Sakito
32657101Sakito cdb->cdb[0] = CMD_READ;
32757101Sakito cdb->cdb[1] = 1; /* unknown setup */
32857101Sakito
32957101Sakito cdb->cdb[2] = (nblk & 0xff0000) >> 16;
33057101Sakito cdb->cdb[3] = (nblk & 0x00ff00) >> 8;
33157101Sakito cdb->cdb[4] = (nblk & 0x0000ff);
33257101Sakito
33357101Sakito cdb->cdb[5] = 0; /* unknown setup */
33457101Sakito
33557101Sakito stat = scsi_immed_command(ctlr, slave, 0, cdb, buf, size);
33657101Sakito
33757101Sakito if (stat == 0)
33857101Sakito return(size);
33957101Sakito else {
34057101Sakito scsi_request_sense(ctlr, slave, 0, sp, 8);
34157101Sakito
34257101Sakito if (stat == STS_CHECKCOND) {
34357101Sakito printf("stread: Sense Key = [%s]", sense_key(sp->key));
34457101Sakito if (sp->filemark)
34557101Sakito printf(" [EOF]");
34657101Sakito if (sp->eom)
34757101Sakito printf(" [EOM]");
34857101Sakito printf("\n");
34957101Sakito }
35057101Sakito
35157101Sakito return(-1);
35257101Sakito }
35357101Sakito }
35457101Sakito
35557101Sakito int
stwrite(dev,buf,size)35657101Sakito stwrite(dev, buf, size)
35757101Sakito dev_t dev;
35857101Sakito char *buf;
35957101Sakito int size;
36057101Sakito {
36157101Sakito register int unit = stunit(dev);
36257101Sakito register struct st_softc *sc = &st_softc[unit];
36357101Sakito register struct scsi_fmt_cdb *cdb = &st_cmd;
36457101Sakito struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
36557101Sakito register int nblk;
36657101Sakito int ctlr, slave, stat;
36757101Sakito
36857101Sakito nblk = size >> DEV_BSHIFT;
36957101Sakito if (size % DEV_BSIZE)
37057101Sakito nblk++;
37157101Sakito size = nblk << DEV_BSHIFT;
37257101Sakito
37357101Sakito ctlr = sc->sc_hd->hp_ctlr;
37457101Sakito slave = sc->sc_hd->hp_slave;
37557101Sakito
37657101Sakito sc->sc_flags |= STF_WRTTN;
37757101Sakito
37857101Sakito cdb->cdb[0] = CMD_WRITE;
37957101Sakito cdb->cdb[1] = 1; /* unknown setup */
38057101Sakito
38157101Sakito cdb->cdb[2] = (nblk & 0xff0000) >> 16;
38257101Sakito cdb->cdb[3] = (nblk & 0x00ff00) >> 8;
38357101Sakito cdb->cdb[4] = (nblk & 0x0000ff);
38457101Sakito
38557101Sakito cdb->cdb[5] = 0; /* unknown setup */
38657101Sakito
38757101Sakito stat = scsi_immed_command(ctlr, slave, 0, cdb, buf, size);
38857101Sakito
38957101Sakito if (stat == 0)
39057101Sakito return(size);
39157101Sakito else {
39257101Sakito scsi_request_sense(ctlr, slave, 0, sp, 8);
39357101Sakito
39457101Sakito if (stat == STS_CHECKCOND) {
39557101Sakito printf("stwrite: Sense Key = [%s]", sense_key(sp->key));
39657101Sakito if (sp->eom)
39757101Sakito printf(" [EOM]");
39857101Sakito printf("\n");
39957101Sakito }
40057101Sakito
40157101Sakito return(-1);
40257101Sakito }
40357101Sakito }
40457101Sakito
40557101Sakito int
stioctl(dev,cmd,data,flag,p)40657101Sakito stioctl(dev, cmd, data, flag, p)
40757101Sakito dev_t dev;
40857101Sakito int cmd;
40957101Sakito caddr_t data;
41057101Sakito int flag;
41157101Sakito struct proc *p;
41257101Sakito {
41357101Sakito }
41457101Sakito
st_rewind(dev)41557101Sakito st_rewind(dev)
41657101Sakito dev_t dev;
41757101Sakito {
41857101Sakito register int unit = stunit(dev);
41957101Sakito register struct st_softc *sc = &st_softc[unit];
42057101Sakito register struct scsi_fmt_cdb *cdb = &st_cmd;
42157101Sakito struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
42257101Sakito int ctlr, slave, stat;
42357101Sakito int retry = 5;
42457101Sakito
42557101Sakito ctlr = sc->sc_hd->hp_ctlr;
42657101Sakito slave = sc->sc_hd->hp_slave;
42757101Sakito
42857101Sakito cdb->cdb[0] = CMD_REWIND;
42957101Sakito cdb->cdb[1] = 1; /* command finished soon */
43057101Sakito
43157101Sakito cdb->cdb[2] = 0;
43257101Sakito cdb->cdb[3] = 0;
43357101Sakito cdb->cdb[4] = 0;
43457101Sakito
43557101Sakito cdb->cdb[5] = 0; /* unknown setup */
43657101Sakito
43757101Sakito rewind:
43857101Sakito stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
43957101Sakito
44057101Sakito if (stat == 0) {
44157101Sakito return(1);
44257101Sakito } else {
44357101Sakito scsi_request_sense(ctlr, slave, 0, sp, 8);
44457101Sakito
44557101Sakito if (stat == STS_CHECKCOND) {
44657101Sakito printf("st_rewind: Sense Key = [%s]", sense_key(sp->key));
44757101Sakito printf("\n");
44857101Sakito }
44957101Sakito
45057101Sakito if (retry > 0) {
45157101Sakito DELAY(1000000);
45257101Sakito retry--;
45357101Sakito goto rewind;
45457101Sakito }
45557101Sakito
45657101Sakito return(0);
45757101Sakito }
45857101Sakito }
45957101Sakito
st_write_EOF(dev)46057101Sakito st_write_EOF(dev)
46157101Sakito dev_t dev;
46257101Sakito {
46357101Sakito register int unit = stunit(dev);
46457101Sakito register struct st_softc *sc = &st_softc[unit];
46557101Sakito register struct scsi_fmt_cdb *cdb = &st_cmd;
46657101Sakito int ctlr, slave, stat;
46757101Sakito int marks = 1;
46857101Sakito
46957101Sakito ctlr = sc->sc_hd->hp_ctlr;
47057101Sakito slave = sc->sc_hd->hp_slave;
47157101Sakito
47257101Sakito cdb->cdb[0] = CMD_WRITE_FILEMARK;
47357101Sakito cdb->cdb[1] = 1; /* command finished soon */
47457101Sakito
47557101Sakito cdb->cdb[2] = (marks & 0xff0000) >> 16;
47657101Sakito cdb->cdb[3] = (marks & 0x00ff00) >> 8;
47757101Sakito cdb->cdb[4] = (marks & 0x0000ff);
47857101Sakito
47957101Sakito cdb->cdb[5] = 0; /* unknown setup */
48057101Sakito
48157101Sakito stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
48257101Sakito
48357101Sakito if (stat == 0)
48457101Sakito return(1);
48557101Sakito
48657101Sakito printf("st: write EOF error\n");
48757101Sakito
48857101Sakito return(0);
48957101Sakito }
49057101Sakito
49157101Sakito int
st_skip(dev)49257101Sakito st_skip(dev)
49357101Sakito dev_t dev;
49457101Sakito {
49557101Sakito register int unit = stunit(dev);
49657101Sakito register struct st_softc *sc = &st_softc[unit];
49757101Sakito register struct scsi_fmt_cdb *cdb = &st_cmd;
49857101Sakito register int nfmk = 1;
49957101Sakito struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
50057101Sakito int ctlr, slave, stat;
50157101Sakito
50257101Sakito ctlr = sc->sc_hd->hp_ctlr;
50357101Sakito slave = sc->sc_hd->hp_slave;
50457101Sakito
50557101Sakito cdb->cdb[0] = CMD_SPACE;
50657101Sakito cdb->cdb[1] = 1; /* it mean skip until EOF */
50757101Sakito
50857101Sakito cdb->cdb[2] = (nfmk & 0xff0000) >> 16;
50957101Sakito cdb->cdb[3] = (nfmk & 0x00ff00) >> 8;
51057101Sakito cdb->cdb[4] = (nfmk & 0x0000ff);
51157101Sakito
51257101Sakito cdb->cdb[5] = 0; /* unknown setup */
51357101Sakito
51457101Sakito stat = scsi_immed_command(ctlr, slave, 0, cdb, 0, 0);
51557101Sakito
51657101Sakito if (stat == 0)
51757101Sakito return(0);
51857101Sakito else {
51957101Sakito scsi_request_sense(ctlr, slave, 0, sp, 8);
52057101Sakito
52157101Sakito if (stat == STS_CHECKCOND) {
52257101Sakito printf("st_skip: Sense Key = [%s]", sense_key(sp->key));
52357101Sakito if (sp->filemark)
52457101Sakito printf(" [EOF]");
52557101Sakito if (sp->eom)
52657101Sakito printf(" [EOM]");
52757101Sakito printf("\n");
52857101Sakito }
52957101Sakito
53057101Sakito return(-1);
53157101Sakito }
53257101Sakito }
53357101Sakito
53457101Sakito /*
53557101Sakito * Dump
53657101Sakito */
53757101Sakito
53857101Sakito int
stdump(dev)53957101Sakito stdump(dev)
54057101Sakito dev_t dev;
54157101Sakito {
54257101Sakito }
543