xref: /csrg-svn/sys/pmax/stand/rz.c (revision 56830)
1*56830Sralph /*
2*56830Sralph  * Copyright (c) 1992 Regents of the University of California.
3*56830Sralph  * All rights reserved.
4*56830Sralph  *
5*56830Sralph  * This code is derived from software contributed to Berkeley by
6*56830Sralph  * Van Jacobson of Lawrence Berkeley Laboratory and Ralph Campbell.
7*56830Sralph  *
8*56830Sralph  * %sccs.include.redist.c%
9*56830Sralph  *
10*56830Sralph  *	@(#)rz.c	7.1 (Berkeley) 11/15/92
11*56830Sralph  */
12*56830Sralph 
13*56830Sralph /*
14*56830Sralph  * SCSI CCS (Command Command Set) disk driver.
15*56830Sralph  * NOTE: The name was changed from "sd" to "rz" for DEC naming compatibility.
16*56830Sralph  * I guess I can't avoid confusion someplace.
17*56830Sralph  */
18*56830Sralph #include <pmax/stand/samachdep.h>
19*56830Sralph #if NRZ > 0
20*56830Sralph 
21*56830Sralph #include <stand/stand.h>
22*56830Sralph #include <sys/param.h>
23*56830Sralph #include <sys/disklabel.h>
24*56830Sralph #include <pmax/dev/device.h>
25*56830Sralph #include <pmax/dev/scsi.h>
26*56830Sralph 
27*56830Sralph void	rzstart(), rzdone();
28*56830Sralph 
29*56830Sralph struct	driver rzdriver = {
30*56830Sralph 	"rz", (int (*)())0, rzstart, rzdone,
31*56830Sralph };
32*56830Sralph 
33*56830Sralph struct	rz_softc {
34*56830Sralph 	struct	scsi_device sc_sd;	/* physical unit info */
35*56830Sralph 	u_short	sc_part;		/* disk partition number */
36*56830Sralph 	u_short	sc_type;		/* drive type from INQUIRY cmd */
37*56830Sralph 	u_int	sc_blks;		/* number of blocks on device */
38*56830Sralph 	int	sc_blksize;		/* device block size in bytes */
39*56830Sralph 	int	sc_bshift;		/* convert device blocks to DEV_BSIZE */
40*56830Sralph 	struct	disklabel sc_label;	/* disk label for this disk */
41*56830Sralph 	struct	ScsiCmd sc_cmd;		/* command for controller */
42*56830Sralph 	ScsiGroup1Cmd sc_rwcmd;		/* group 1 SCSI commands */
43*56830Sralph 	struct	scsi_fmt_sense sc_sense;	/* sense data from last cmd */
44*56830Sralph 	int	sc_error;		/* error code */
45*56830Sralph 	int	sc_resid;		/* amount of data not transfered */
46*56830Sralph };
47*56830Sralph 
48*56830Sralph volatile int	done;
49*56830Sralph 
50*56830Sralph int
51*56830Sralph rzstrategy(devdata, rw, bn, reqcnt, addr, cnt)
52*56830Sralph 	void *devdata;
53*56830Sralph 	int rw;
54*56830Sralph 	daddr_t bn;
55*56830Sralph 	u_int reqcnt;
56*56830Sralph 	char *addr;
57*56830Sralph 	u_int *cnt;	/* out: number of bytes transfered */
58*56830Sralph {
59*56830Sralph 	register struct rz_softc *sc = (struct rz_softc *)devdata;
60*56830Sralph 	register int part = sc->sc_part;
61*56830Sralph 	register struct partition *pp = &sc->sc_label.d_partitions[part];
62*56830Sralph 	register int s;
63*56830Sralph 	long cylin;
64*56830Sralph 
65*56830Sralph 	sc->sc_error = 0;
66*56830Sralph 	s = howmany(reqcnt, DEV_BSIZE);
67*56830Sralph 	if ((unsigned)bn + s > pp->p_size) {
68*56830Sralph 		s = pp->p_size - bn;
69*56830Sralph 		/* if exactly at end of disk, return an EOF */
70*56830Sralph 		if (s == 0) {
71*56830Sralph 			*cnt = 0;
72*56830Sralph 			return (0);
73*56830Sralph 		}
74*56830Sralph 		/* if none of it fits, error */
75*56830Sralph 		if (s < 0) {
76*56830Sralph 			*cnt = 0;
77*56830Sralph 			return (EINVAL);
78*56830Sralph 		}
79*56830Sralph 		/* otherwise, truncate */
80*56830Sralph 		reqcnt = dbtob(s);
81*56830Sralph 	}
82*56830Sralph 	/*
83*56830Sralph 	 * Non-aligned or partial-block transfers not handled.
84*56830Sralph 	 */
85*56830Sralph 	s = sc->sc_blksize - 1;
86*56830Sralph 	if ((dbtob(bn) & s) || (reqcnt & s)) {
87*56830Sralph 		*cnt = 0;
88*56830Sralph 		return (EINVAL);
89*56830Sralph 	}
90*56830Sralph 	cylin = (bn + pp->p_offset) >> sc->sc_bshift;
91*56830Sralph 
92*56830Sralph 	sc->sc_cmd.buf = addr;
93*56830Sralph 	sc->sc_cmd.buflen = reqcnt;
94*56830Sralph 	sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd;
95*56830Sralph 	sc->sc_cmd.cmdlen = sizeof(sc->sc_rwcmd);
96*56830Sralph 
97*56830Sralph 	if (rw & F_READ) {
98*56830Sralph 		sc->sc_cmd.flags = 0;
99*56830Sralph 		sc->sc_rwcmd.command = SCSI_READ_EXT;
100*56830Sralph 	} else {
101*56830Sralph 		sc->sc_cmd.flags = SCSICMD_DATA_TO_DEVICE;
102*56830Sralph 		sc->sc_rwcmd.command = SCSI_WRITE_EXT;
103*56830Sralph 	}
104*56830Sralph 	sc->sc_rwcmd.highAddr = cylin >> 24;
105*56830Sralph 	sc->sc_rwcmd.midHighAddr = cylin >> 16;
106*56830Sralph 	sc->sc_rwcmd.midLowAddr = cylin >> 8;
107*56830Sralph 	sc->sc_rwcmd.lowAddr = cylin;
108*56830Sralph 	s = howmany(reqcnt, sc->sc_blksize);
109*56830Sralph 	sc->sc_rwcmd.highBlockCount = s >> 8;
110*56830Sralph 	sc->sc_rwcmd.lowBlockCount = s;
111*56830Sralph 
112*56830Sralph 	rzstart(sc);
113*56830Sralph 
114*56830Sralph 	*cnt = reqcnt - sc->sc_resid;
115*56830Sralph 	return (sc->sc_error);
116*56830Sralph }
117*56830Sralph 
118*56830Sralph void
119*56830Sralph rzstart(sc)
120*56830Sralph 	register struct rz_softc *sc;
121*56830Sralph {
122*56830Sralph 	ScsiGroup0Cmd reqcmd;
123*56830Sralph 
124*56830Sralph 	/* tell controller to start this command */
125*56830Sralph 	done = 0;
126*56830Sralph 	(*sc->sc_sd.sd_cdriver->d_start)(&sc->sc_cmd);
127*56830Sralph 	while (!done)
128*56830Sralph 		;
129*56830Sralph 
130*56830Sralph 	/* check for errors that need to be processed */
131*56830Sralph 	if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND))
132*56830Sralph 		return;
133*56830Sralph 
134*56830Sralph 	/* start a REQUEST_SENSE command */
135*56830Sralph 	scsiGroup0Cmd(SCSI_REQUEST_SENSE, sc->sc_sd.sd_slave, 0,
136*56830Sralph 		sizeof(sc->sc_sense.sense), &reqcmd);
137*56830Sralph 	sc->sc_cmd.cmdlen = sizeof(ScsiGroup0Cmd);
138*56830Sralph 	sc->sc_cmd.cmd = (u_char *)&reqcmd;
139*56830Sralph 	sc->sc_cmd.buf = (char *)sc->sc_sense.sense;
140*56830Sralph 	sc->sc_cmd.buflen = sizeof(sc->sc_sense.sense);
141*56830Sralph 	sc->sc_cmd.flags = 0;
142*56830Sralph 
143*56830Sralph 	/* tell controller to start this command */
144*56830Sralph 	done = 0;
145*56830Sralph 	(*sc->sc_sd.sd_cdriver->d_start)(&sc->sc_cmd);
146*56830Sralph 	while (!done)
147*56830Sralph 		;
148*56830Sralph 
149*56830Sralph 	if (sc->sc_error || (sc->sc_sense.status & SCSI_STATUS_CHECKCOND)) {
150*56830Sralph 		printf("rz%d: error reading sense data: error %d scsi status 0x%x\n",
151*56830Sralph 			sc->sc_sd.sd_unit, sc->sc_error, sc->sc_sense.status);
152*56830Sralph 		/*
153*56830Sralph 		 * We got an error during the REQUEST_SENSE,
154*56830Sralph 		 * fill in no sense for data.
155*56830Sralph 		 */
156*56830Sralph 		sc->sc_sense.sense[0] = 0x70;
157*56830Sralph 		sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE;
158*56830Sralph 	} else {
159*56830Sralph 		printf("rz%d: ", sc->sc_sd.sd_unit);
160*56830Sralph 		scsiPrintSense((ScsiClass7Sense *)sc->sc_sense.sense,
161*56830Sralph 			sizeof(sc->sc_sense.sense) - sc->sc_resid);
162*56830Sralph 	}
163*56830Sralph 	if (sc->sc_error == 0)
164*56830Sralph 		sc->sc_error = EIO;
165*56830Sralph }
166*56830Sralph 
167*56830Sralph /*
168*56830Sralph  * This is called by the controller driver when the command is done.
169*56830Sralph  */
170*56830Sralph void
171*56830Sralph rzdone(data, error, resid, status)
172*56830Sralph 	void *data;
173*56830Sralph 	int error;		/* error number from errno.h */
174*56830Sralph 	int resid;		/* amount not transfered */
175*56830Sralph 	int status;		/* SCSI status byte */
176*56830Sralph {
177*56830Sralph 	register struct rz_softc *sc = (struct rz_softc *)data;
178*56830Sralph 
179*56830Sralph 	sc->sc_error = error;
180*56830Sralph 	sc->sc_resid = resid;
181*56830Sralph 	sc->sc_sense.status = status;
182*56830Sralph 	done = 1;
183*56830Sralph }
184*56830Sralph 
185*56830Sralph int
186*56830Sralph rzopen(f, ctlr, unit, part)
187*56830Sralph 	struct open_file *f;
188*56830Sralph 	int ctlr, unit, part;
189*56830Sralph {
190*56830Sralph 	register struct rz_softc *sc;
191*56830Sralph 	register struct disklabel *lp;
192*56830Sralph 	register struct scsi_device *sd;
193*56830Sralph 	register int i;
194*56830Sralph 	char *msg;
195*56830Sralph 	ScsiGroup0Cmd inqcmd;
196*56830Sralph 	ScsiInquiryData inqbuf;
197*56830Sralph 	u_char capbuf[8];
198*56830Sralph 	char buf[DEV_BSIZE];
199*56830Sralph 	int cnt;
200*56830Sralph 	struct driver *scsi_driver;
201*56830Sralph 
202*56830Sralph 	if (unit >= NRZ || part >= MAXPARTITIONS)
203*56830Sralph 		return (ENXIO);
204*56830Sralph #ifdef DS3100
205*56830Sralph 	if (ctlr >= NSII)
206*56830Sralph 		return (ENXIO);
207*56830Sralph 	else {
208*56830Sralph 		extern struct driver siidriver;
209*56830Sralph 
210*56830Sralph 		scsi_driver = &siidriver;
211*56830Sralph 	}
212*56830Sralph #endif
213*56830Sralph #ifdef DS5000
214*56830Sralph 	{
215*56830Sralph 	struct pmax_ctlr *cp, *tc_ctlr __P((int, int));
216*56830Sralph 
217*56830Sralph 	cp = tc_ctlr(ctlr, TC_SCSI);
218*56830Sralph 	if (!cp)
219*56830Sralph 		return (ENXIO);
220*56830Sralph 	ctlr = cp->pmax_unit;	/* convert from slot # to controller unit */
221*56830Sralph 	scsi_driver = cp->pmax_driver;
222*56830Sralph 	}
223*56830Sralph #endif
224*56830Sralph 
225*56830Sralph 	sc = alloc(sizeof(struct rz_softc));
226*56830Sralph 	bzero(sc, sizeof(struct rz_softc));
227*56830Sralph 	f->f_devdata = (void *)sc;
228*56830Sralph 
229*56830Sralph 	sc->sc_sd.sd_driver = &rzdriver;
230*56830Sralph 	sc->sc_sd.sd_cdriver = scsi_driver;
231*56830Sralph 	sc->sc_sd.sd_unit = unit;
232*56830Sralph 	sc->sc_sd.sd_ctlr = ctlr;
233*56830Sralph 	sc->sc_sd.sd_drive = unit;
234*56830Sralph 	sc->sc_sd.sd_slave = 0;
235*56830Sralph 	sc->sc_sd.sd_flags = 0;
236*56830Sralph 	sc->sc_sd.sd_alive = 1;
237*56830Sralph 	sc->sc_part = part;
238*56830Sralph 
239*56830Sralph 	/* init fields that don't change */
240*56830Sralph 	sc->sc_cmd.sd = sd = &sc->sc_sd;
241*56830Sralph 	sc->sc_cmd.unit = (int)sc;
242*56830Sralph 
243*56830Sralph 	/*
244*56830Sralph 	 * Try to find out what type of device this is.
245*56830Sralph 	 */
246*56830Sralph 	scsiGroup0Cmd(SCSI_INQUIRY, sd->sd_slave, 0, sizeof(inqbuf), &inqcmd);
247*56830Sralph 	sc->sc_cmd.cmdlen = sizeof(ScsiGroup0Cmd);
248*56830Sralph 	sc->sc_cmd.cmd = (u_char *)&inqcmd;
249*56830Sralph 	sc->sc_cmd.buflen = sizeof(inqbuf);
250*56830Sralph 	sc->sc_cmd.buf = (char *)&inqbuf;
251*56830Sralph 	sc->sc_cmd.flags = 0;
252*56830Sralph 
253*56830Sralph 	/* tell controller to start this command */
254*56830Sralph 	rzstart(sc);
255*56830Sralph 
256*56830Sralph 	if (sc->sc_error || (i = sizeof(inqbuf) - sc->sc_resid) < 5)
257*56830Sralph 		goto bad;
258*56830Sralph 	switch (inqbuf.type) {
259*56830Sralph 	case SCSI_DISK_TYPE:		/* disk */
260*56830Sralph 	case SCSI_WORM_TYPE:		/* WORM */
261*56830Sralph 	case SCSI_ROM_TYPE:		/* CD-ROM */
262*56830Sralph 	case SCSI_OPTICAL_MEM_TYPE:	/* Magneto-optical */
263*56830Sralph 		break;
264*56830Sralph 
265*56830Sralph 	default:			/* not a disk */
266*56830Sralph 		goto bad;
267*56830Sralph 	}
268*56830Sralph 	sc->sc_type = inqbuf.type;
269*56830Sralph 
270*56830Sralph 	/* find out how big a disk this is */
271*56830Sralph 	scsiGroup1Cmd(SCSI_READ_CAPACITY, sd->sd_slave, 0, 0, &sc->sc_rwcmd);
272*56830Sralph 	sc->sc_cmd.cmdlen = sizeof(ScsiGroup1Cmd);
273*56830Sralph 	sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd;
274*56830Sralph 	sc->sc_cmd.buflen = sizeof(capbuf);
275*56830Sralph 	sc->sc_cmd.buf = (char *)capbuf;
276*56830Sralph 	sc->sc_cmd.flags = 0;
277*56830Sralph 
278*56830Sralph 	rzstart(sc);
279*56830Sralph 
280*56830Sralph 	if (sc->sc_error || sc->sc_resid != 0)
281*56830Sralph 		goto bad;
282*56830Sralph 	sc->sc_blks = ((capbuf[0] << 24) | (capbuf[1] << 16) |
283*56830Sralph 		(capbuf[2] << 8) | capbuf[3]) + 1;
284*56830Sralph 	sc->sc_blksize = (capbuf[4] << 24) | (capbuf[5] << 16) |
285*56830Sralph 		(capbuf[6] << 8) | capbuf[7];
286*56830Sralph 
287*56830Sralph #if 0
288*56830Sralph 	printf("rz%d at %s%d drive %d slave %d", sd->sd_unit,
289*56830Sralph 		sd->sd_cdriver->d_name, sd->sd_ctlr, sd->sd_drive,
290*56830Sralph 		sd->sd_slave);
291*56830Sralph 	if (inqbuf.version > 1 || i < 36)
292*56830Sralph 		printf(" type 0x%x, qual 0x%x, ver %d",
293*56830Sralph 			inqbuf.type, inqbuf.qualifier, inqbuf.version);
294*56830Sralph 	else {
295*56830Sralph 		char vid[9], pid[17], revl[5];
296*56830Sralph 
297*56830Sralph 		bcopy((caddr_t)inqbuf.vendorID, (caddr_t)vid, 8);
298*56830Sralph 		bcopy((caddr_t)inqbuf.productID, (caddr_t)pid, 16);
299*56830Sralph 		bcopy((caddr_t)inqbuf.revLevel, (caddr_t)revl, 4);
300*56830Sralph 		for (i = 8; --i > 0; )
301*56830Sralph 			if (vid[i] != ' ')
302*56830Sralph 				break;
303*56830Sralph 		vid[i+1] = 0;
304*56830Sralph 		for (i = 16; --i > 0; )
305*56830Sralph 			if (pid[i] != ' ')
306*56830Sralph 				break;
307*56830Sralph 		pid[i+1] = 0;
308*56830Sralph 		for (i = 4; --i > 0; )
309*56830Sralph 			if (revl[i] != ' ')
310*56830Sralph 				break;
311*56830Sralph 		revl[i+1] = 0;
312*56830Sralph 		printf(" %s %s rev %s", vid, pid, revl);
313*56830Sralph 	}
314*56830Sralph 	printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
315*56830Sralph #endif
316*56830Sralph 
317*56830Sralph 	if (sc->sc_blksize != DEV_BSIZE) {
318*56830Sralph 		if (sc->sc_blksize < DEV_BSIZE) {
319*56830Sralph 			printf("rz%d: need %d byte blocks - drive ignored\n",
320*56830Sralph 				unit, DEV_BSIZE);
321*56830Sralph 			goto bad;
322*56830Sralph 		}
323*56830Sralph 		for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
324*56830Sralph 			++sc->sc_bshift;
325*56830Sralph 		sc->sc_blks <<= sc->sc_bshift;
326*56830Sralph 	}
327*56830Sralph 
328*56830Sralph 	/* try to read disk label and partition table information */
329*56830Sralph 	lp = &sc->sc_label;
330*56830Sralph 	lp->d_secsize = DEV_BSIZE;
331*56830Sralph 	lp->d_secpercyl = 1 << sc->sc_bshift;
332*56830Sralph 	lp->d_npartitions = MAXPARTITIONS;
333*56830Sralph 	lp->d_partitions[part].p_offset = 0;
334*56830Sralph 	lp->d_partitions[part].p_size = sc->sc_blks;
335*56830Sralph 	i = rzstrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE, buf, &cnt);
336*56830Sralph 	if (i || cnt != DEV_BSIZE) {
337*56830Sralph 		printf("rz%d: error reading disk label\n", unit);
338*56830Sralph 		goto bad;
339*56830Sralph 	} else {
340*56830Sralph 		msg = getdisklabel(buf, lp);
341*56830Sralph 		if (msg) {
342*56830Sralph 			printf("rz%d: %s\n", unit, msg);
343*56830Sralph 			goto bad;
344*56830Sralph 		}
345*56830Sralph 	}
346*56830Sralph 
347*56830Sralph 	if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) {
348*56830Sralph 	bad:
349*56830Sralph 		free(sc, sizeof(struct rz_softc));
350*56830Sralph 		return (ENXIO);
351*56830Sralph 	}
352*56830Sralph 	return (0);
353*56830Sralph }
354*56830Sralph 
355*56830Sralph rzclose(f)
356*56830Sralph 	struct open_file *f;
357*56830Sralph {
358*56830Sralph 	free(f->f_devdata, sizeof(struct rz_softc));
359*56830Sralph 	f->f_devdata = (void *)0;
360*56830Sralph 	return (0);
361*56830Sralph }
362*56830Sralph #endif
363