xref: /csrg-svn/sys/luna68k/stand/sd.c (revision 63199)
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