xref: /original-bsd/sys/luna68k/stand/sd.c (revision 3705696b)
1 /*
2  * Copyright (c) 1992 OMRON Corporation.
3  * Copyright (c) 1992, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * OMRON Corporation.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)sd.c	8.1 (Berkeley) 06/10/93
12  */
13 
14 /*
15  * sd.c -- SCSI DISK device driver
16  * by A.Fujita, FEB-26-1992
17  */
18 
19 
20 /*
21  * SCSI CCS (Command Command Set) disk driver.
22  */
23 #define	NSD	2
24 
25 #include <sys/param.h>
26 #include <sys/disklabel.h>
27 #include <luna68k/dev/scsireg.h>
28 #include <luna68k/stand/saio.h>
29 #include <luna68k/stand/device.h>
30 
31 
32 int	sdinit(), sdstrategy(), sdstart(), sdustart(), sdgo(), sdintr();
33 
34 struct	driver sddriver = {
35 	sdinit, "sd", sdstart, sdgo, sdintr,
36 };
37 
38 struct	disklabel sdlabel[NSD];
39 
40 struct	sd_softc {
41 	struct	hp_device *sc_hd;
42 	struct	devqueue sc_dq;
43 	int	sc_format_pid;	/* process using "format" mode */
44 	short	sc_flags;
45 	short	sc_type;	/* drive type */
46 	short	sc_punit;	/* physical unit (scsi lun) */
47 	u_short	sc_bshift;	/* convert device blocks to DEV_BSIZE blks */
48 	u_int	sc_blks;	/* number of blocks on device */
49 	int	sc_blksize;	/* device block size in bytes */
50 	u_int	sc_wpms;	/* average xfer rate in 16 bit wds/sec. */
51 } sd_softc[NSD];
52 
53 /* sc_flags values */
54 #define	SDF_ALIVE	0x1
55 
56 #define	sdunit(x)	((minor(x) >> 3) & 0x7)
57 #define sdpart(x)	(minor(x) & 0x7)
58 #define	sdpunit(x)	((x) & 7)
59 
60 static struct scsi_inquiry inqbuf;
61 static struct scsi_fmt_cdb inq = {
62 	6,
63 	CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
64 };
65 
66 static u_long capbuf[2];
67 struct scsi_fmt_cdb cap = {
68 	10,
69 	CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0
70 };
71 
72 int
73 sdident(sc, hd)
74 	struct sd_softc *sc;
75 	struct hp_device *hd;
76 {
77 	char idstr[32];
78 	int unit;
79 	register int ctlr, slave;
80 	register int i;
81 	register int tries = 10;
82 
83 	ctlr = hd->hp_ctlr;
84 	slave = hd->hp_slave;
85 	unit = sc->sc_punit;
86 
87 	/*
88 	 * See if unit exists and is a disk then read block size & nblocks.
89 	 */
90 	while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) {
91 		if (i < 0 || --tries < 0)
92 			return (-1);
93 		if (i == STS_CHECKCOND) {
94 			u_char sensebuf[8];
95 			struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
96 
97 			scsi_request_sense(ctlr, slave, unit, sensebuf, 8);
98 			if (sp->class == 7 && sp->key == 6)
99 				/* drive doing an RTZ -- give it a while */
100 				DELAY(1000000);
101 		}
102 		DELAY(1000);
103 	}
104 	if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf,
105 			       sizeof(inqbuf)) ||
106 	    scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf,
107 			       sizeof(capbuf)))
108 		/* doesn't exist or not a CCS device */
109 		return (-1);
110 
111 	switch (inqbuf.type) {
112 	case 0:		/* disk */
113 	case 4:		/* WORM */
114 	case 5:		/* CD-ROM */
115 	case 7:		/* Magneto-optical */
116 		break;
117 	default:	/* not a disk */
118 		return (-1);
119 	}
120 	sc->sc_blks    = capbuf[0];
121 	sc->sc_blksize = capbuf[1];
122 
123 	bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
124 	for (i = 27; i > 23; --i)
125 		if (idstr[i] != ' ')
126 			break;
127 	idstr[i+1] = 0;
128 	for (i = 23; i > 7; --i)
129 		if (idstr[i] != ' ')
130 			break;
131 	idstr[i+1] = 0;
132 	for (i = 7; i >= 0; --i)
133 		if (idstr[i] != ' ')
134 			break;
135 	idstr[i+1] = 0;
136 	printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
137 	       &idstr[24]);
138 
139 	printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
140 	if (sc->sc_blksize != DEV_BSIZE) {
141 		if (sc->sc_blksize < DEV_BSIZE) {
142 			printf("sd%d: need %d byte blocks - drive ignored\n",
143 				unit, DEV_BSIZE);
144 			return (-1);
145 		}
146 		for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
147 			++sc->sc_bshift;
148 		sc->sc_blks <<= sc->sc_bshift;
149 	}
150 	sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2);	/* XXX */
151 	return(inqbuf.type);
152 }
153 
154 int
155 sdinit(hd)
156 	register struct hp_device *hd;
157 {
158 	register struct sd_softc *sc = &sd_softc[hd->hp_unit];
159 	register struct disklabel *lp;
160 	char *msg, *readdisklabel();
161 
162 #ifdef DEBUG
163 	printf("sdinit: hd->hp_unit = %d\n", hd->hp_unit);
164 	printf("sdinit: hd->hp_ctlr = %d, hd->hp_slave = %d\n",
165 	       hd->hp_ctlr, hd->hp_slave);
166 #endif
167 	sc->sc_hd = hd;
168 	sc->sc_punit = sdpunit(hd->hp_flags);
169 	sc->sc_type = sdident(sc, hd);
170 	if (sc->sc_type < 0)
171 		return(0);
172 
173 	/*
174 	 * Use the default sizes until we've read the label,
175 	 * or longer if there isn't one there.
176 	 */
177 	lp = &sdlabel[hd->hp_unit];
178 
179 	if (lp->d_secpercyl == 0) {
180 		lp->d_secsize = DEV_BSIZE;
181 		lp->d_nsectors = 32;
182 		lp->d_ntracks = 20;
183 		lp->d_secpercyl = 32*20;
184 		lp->d_npartitions = 1;
185 		lp->d_partitions[0].p_offset = 0;
186 		lp->d_partitions[0].p_size = LABELSECTOR + 1;
187 	}
188 
189 	/*
190 	 * read disklabel
191 	 */
192 	if (msg = readdisklabel(hd->hp_slave, sdstrategy, lp)) {
193 		if (msg != NULL)
194 			printf("sd%d: %s\n", hd->hp_unit, msg);
195 	}
196 
197 	sc->sc_flags = SDF_ALIVE;
198 	return(1);
199 }
200 
201 int
202 sdopen(io)
203 	struct iob *io;
204 {
205 	register int unit = io->i_unit;
206 	register struct disklabel *lp;
207 
208 	if (unit < 0 || unit >= NSD)
209 		return(-1);
210 
211 	lp = &sdlabel[unit];
212 	io->i_boff = lp->d_partitions[io->i_boff].p_offset;
213 }
214 
215 static struct scsi_fmt_cdb cdb_read = {
216 	10,
217 	CMD_READ_EXT,  0, 0, 0, 0, 0, 0, 0, 0, 0
218 };
219 
220 static struct scsi_fmt_cdb cdb_write = {
221 	6,
222 	CMD_WRITE_EXT, 0, 0, 0, 0, 0, 0, 0, 0, 0
223 };
224 
225 int
226 sdstrategy(io, func)
227 	register struct iob *io;
228 	register int func;
229 {
230 	int unit = io->i_unit;
231 	struct sd_softc *sc = &sd_softc[unit];
232 	struct scsi_fmt_cdb *cdb;
233 	daddr_t blk = io->i_bn >> sc->sc_bshift;
234 	u_int nblk  = io->i_cc >> sc->sc_bshift;
235 	int stat, ctlr, slave, i;
236 
237 	if (unit < 0 || unit >= NSD)
238 		return(-1);
239 
240 	ctlr  = sc->sc_hd->hp_ctlr;
241 	slave = sc->sc_hd->hp_slave;
242 
243 	if (func == READ)
244 		cdb = &cdb_read;
245 	else
246 		cdb = &cdb_write;
247 
248 	cdb->cdb[2] = (blk & 0xff000000) >> 24;
249 	cdb->cdb[3] = (blk & 0x00ff0000) >> 16;
250 	cdb->cdb[4] = (blk & 0x0000ff00) >>  8;
251 	cdb->cdb[5] = (blk & 0x000000ff);
252 
253 	cdb->cdb[7] = ((nblk >> DEV_BSHIFT) & 0xff00) >> 8;
254 	cdb->cdb[8] = ((nblk >> DEV_BSHIFT) & 0x00ff);
255 
256 #ifdef DEBUG
257 	printf("sdstrategy: io->i_unit = %d\n", io->i_unit);
258 	printf("sdstrategy: blk = %d (0x%x), nblk = %d (0x%x)\n", blk, blk, nblk, nblk);
259 	for (i = 0; i < 10; i++)
260 		printf("sdstrategy: cdb[%d] = 0x%x\n", i, cdb->cdb[i]);
261 	printf("sdstrategy: ctlr = %d, slave = %d\n", ctlr, slave);
262 #endif
263 	stat = scsi_immed_command(ctlr, slave, sc->sc_punit, cdb,  io->i_ma, io->i_cc);
264 
265 	return(io->i_cc);
266 }
267 
268 int
269 sdustart()
270 {
271 }
272 
273 int
274 sdstart()
275 {
276 }
277 
278 int
279 sdgo()
280 {
281 }
282 
283 int
284 sdintr()
285 {
286 }
287 
288 int
289 sdread(dev, blk, nblk, buff, len)
290 	dev_t dev;
291 	u_int   blk;
292 	u_int   nblk;
293 	u_char *buff;
294 	u_int   len;
295 {
296 	register int unit = sdunit(dev);
297 	register int part = sdpart(dev);
298 	struct sd_softc *sc = &sd_softc[unit];
299 	struct scsi_fmt_cdb *cdb;
300 	int stat, ctlr, slave;
301 
302 	ctlr  = sc->sc_hd->hp_ctlr;
303 	slave = sc->sc_hd->hp_slave;
304 
305 	cdb = &cdb_read;
306 
307 	cdb->cdb[2] = (blk & 0xff000000) >> 24;
308 	cdb->cdb[3] = (blk & 0x00ff0000) >> 16;
309 	cdb->cdb[4] = (blk & 0x0000ff00) >>  8;
310 	cdb->cdb[5] = (blk & 0x000000ff);
311 
312 	cdb->cdb[7] = (nblk & 0xff00) >> 8;
313 	cdb->cdb[8] = (nblk & 0x00ff);
314 
315 	stat = scsi_immed_command(ctlr, slave, sc->sc_punit, cdb,  buff, len);
316 
317 	if (stat == 0)
318 		return(1);
319 	else
320 		return(0);
321 }
322 
323 int
324 sdioctl(dev, data)
325 	dev_t dev;
326 	u_long data[];
327 {
328 	register int unit = sdunit(dev);
329 	register int part = sdpart(dev);
330 	register struct disklabel *lp;
331 
332 	if (unit < 0 || unit >= NSD)
333 		return(0);
334 
335 	if (part < 0 || part >= MAXPARTITIONS)
336 		return(0);
337 
338 	lp = &sdlabel[unit];
339 	data[0] = lp->d_partitions[part].p_offset;
340 	data[1] = lp->d_partitions[part].p_size;
341 
342 	return(1);
343 }
344