xref: /original-bsd/sys/luna68k/stand/st.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  *	@(#)st.c	8.1 (Berkeley) 06/10/93
12  */
13 
14 /*
15  * st.c -- SCSI Disk Device Driver for LUNA-68K
16  * remaked by A.Fujita, MAR-22-1992
17  */
18 
19 /*
20  * SCSI CCS (Command Command Set) disk driver.
21  */
22 #define NST	1
23 
24 #include <sys/param.h>
25 #include <sys/mtio.h>
26 #include <luna68k/dev/scsireg.h>
27 #include <luna68k/stand/device.h>
28 
29 extern int scsi_test_unit_rdy();
30 extern int scsi_request_sense();
31 extern int scsi_immed_command();
32 
33 extern int scgo();
34 extern void scfree();
35 
36 int	stinit(), ststrategy(), ststart(), stintr();
37 
38 struct	driver stdriver = {
39 	stinit, "st", ststart, (int (*)()) 0, stintr, (int (*)()) 0
40 };
41 
42 struct	st_softc {
43 	struct	hp_device *sc_hd;
44 	struct	devqueue sc_dq;
45 	int	sc_flags;
46 	short	sc_type;	/* drive type */
47 	short	sc_punit;	/* physical unit (scsi lun) */
48 } st_softc[NST];
49 
50 /* softc flags */
51 #define STF_ALIVE	0x0001
52 #define STF_OPEN	0x0002
53 #define STF_WMODE	0x0004
54 #define STF_WRTTN	0x0008
55 #define STF_CMD		0x0010
56 #define STF_LEOT	0x0020
57 #define STF_MOVED	0x0040
58 
59 struct	scsi_fmt_sense stsense[NST];
60 
61 #define	stunit(x)	(minor(x) & 3)
62 #define	stpunit(x)	((x) & 7)
63 
64 #define STDEV_NOREWIND	0x04
65 #define STDEV_HIDENSITY	0x08
66 #define STDEV_EXSFMK	0x10
67 #define STDEV_FIXEDBLK	0x20
68 
69 #define	b_lba		b_resid
70 
71 #define	STRETRY		2	/* IO retry count */
72 
73 
74 /*
75  * Initialize
76  */
77 
78 int
79 stinit(hd)
80 	register struct hp_device *hd;
81 {
82 	register struct st_softc *sc = &st_softc[hd->hp_unit];
83 
84 	sc->sc_hd = hd;
85 	sc->sc_punit = stpunit(hd->hp_flags);
86 	sc->sc_type = stident(sc, hd);
87 	if (sc->sc_type < 0)
88 		return(0);
89 	sc->sc_dq.dq_ctlr = hd->hp_ctlr;
90 	sc->sc_dq.dq_unit = hd->hp_unit;
91 	sc->sc_dq.dq_slave = hd->hp_slave;
92 	sc->sc_dq.dq_driver = &stdriver;
93 	sc->sc_flags = STF_ALIVE;
94 	return(1);
95 }
96 
97 static struct scsi_inquiry inqbuf;
98 static struct scsi_fmt_cdb inq = {
99 	6,
100 	CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
101 };
102 
103 int
104 stident(sc, hd)
105 	struct st_softc *sc;
106 	struct hp_device *hd;
107 {
108 	char idstr[32];
109 	int unit;
110 	register int ctlr, slave;
111 	register int i, stat;
112 	register int tries = 10;
113 
114 	ctlr = hd->hp_ctlr;
115 	slave = hd->hp_slave;
116 	unit = sc->sc_punit;
117 
118 	/*
119 	 * See if unit exists and is a disk then read block size & nblocks.
120 	 */
121 	while ((stat = scsi_immed_command(ctlr, slave, unit,
122 				  &inq, (u_char *)&inqbuf, sizeof(inqbuf))) != 0) {
123 		if (stat < 0 || --tries < 0)
124 			return (-1);
125 		DELAY(1000);
126 	}
127 
128 	if (stat)
129 		return (-1);
130 
131 	switch (inqbuf.type) {
132 	case 1:		/* tape */
133 		break;
134 	default:	/* not a disk */
135 		return (-1);
136 	}
137 
138 	bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
139 	for (i = 27; i > 23; --i)
140 		if (idstr[i] != ' ')
141 			break;
142 	idstr[i+1] = 0;
143 	for (i = 23; i > 7; --i)
144 		if (idstr[i] != ' ')
145 			break;
146 	idstr[i+1] = 0;
147 	for (i = 7; i >= 0; --i)
148 		if (idstr[i] != ' ')
149 			break;
150 	idstr[i+1] = 0;
151 	printf("st%d: %s %s rev %s\n", hd->hp_unit, idstr, &idstr[8],
152 	       &idstr[24]);
153 
154 	return(inqbuf.type);
155 }
156 
157 
158 /*
159  * Open
160  */
161 
162 int
163 stopen(dev)
164 	dev_t dev;
165 {
166 	register int unit = stunit(dev);
167 	register struct st_softc *sc = &st_softc[unit];
168 
169 	if (unit >= NST || (sc->sc_flags & STF_ALIVE) == 0)
170 		return(-1);
171 	if (sc->sc_flags & STF_OPEN)
172 		return(-1);
173 
174 	sc->sc_flags |= STF_OPEN;
175 	sc->sc_flags |= STF_WMODE;
176 	sc->sc_flags &= ~STF_MOVED;
177 
178 	return(0);
179 }
180 
181 /*ARGSUSED*/
182 stclose(dev)
183 	dev_t dev;
184 {
185 	register int unit = stunit(dev);
186 	register struct st_softc *sc = &st_softc[unit];
187 
188 	printf("st: sc->sc_flags = 0x%s\n", hexstr(sc->sc_flags, 8));
189 
190 	if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {
191 		st_write_EOF(dev);
192 	}
193 
194 	if ((minor(dev) & STDEV_NOREWIND) == 0) {
195 		st_rewind(dev);
196 	}
197 
198 	sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN);
199 
200 	return(0);
201 }
202 
203 /*
204  * Strategy
205  */
206 
207 int
208 ststrategy()
209 {
210 }
211 
212 int
213 ststart(unit)
214 	register int unit;
215 {
216 }
217 
218 /*
219  * Interrupt
220  */
221 
222 /*
223  * Return:
224  *	0	if not really an error
225  *	<0	if we should do a retry
226  *	>0	if a fatal error
227  */
228 static int
229 sterror(unit, sc, hp, stat)
230 	int unit, stat;
231 	register struct st_softc *sc;
232 	register struct hp_device *hp;
233 {
234 	int cond = 1;
235 
236 	stsense[unit].status = stat;
237 	if (stat & STS_CHECKCOND) {
238 		struct scsi_xsense *sp;
239 
240 		scsi_request_sense(hp->hp_ctlr, hp->hp_slave,
241 				   sc->sc_punit, stsense[unit].sense,
242 				   sizeof(stsense[unit].sense));
243 		sp = (struct scsi_xsense *)stsense[unit].sense;
244 		printf("st%d: scsi sense class %d, code %d", unit,
245 			sp->class, sp->code);
246 		if (sp->class == 7) {
247 			printf(", key %d", sp->key);
248 			if (sp->valid)
249 				printf(", blk %d", *(int *)&sp->info1);
250 			switch (sp->key) {
251 			/* no sense, try again */
252 			case 0:
253 				cond = -1;
254 				break;
255 			/* recovered error, not a problem */
256 			case 1:
257 				cond = 0;
258 				break;
259 			}
260 		}
261 		printf("\n");
262 	}
263 	return(cond);
264 }
265 
266 int
267 stintr(unit, stat)
268 	register int unit;
269 	int stat;
270 {
271 }
272 
273 
274 /*
275  * RAW Device Routines
276  */
277 
278 char *
279 sense_key(key)
280 	int key;
281 {
282 	if (key == 0)
283 		return("No Sense");
284 	else if (key == 2)
285 		return("Not Ready");
286 	else if (key == 3)
287 		return("Medium Error");
288 	else if (key == 4)
289 		return("Hardware Error");
290 	else if (key == 5)
291 		return("Illegal Request");
292 	else if (key == 6)
293 		return("Unit Attention");
294 	else if (key == 7)
295 		return("Data Protect");
296 	else if (key == 8)
297 		return("No Data");
298 	else if (key == 11)
299 		return("Aborted Command");
300 	else if (key == 13)
301 		return("Volume Overflow");
302 	else
303 		return("Unknown Error");
304 }
305 
306 static struct scsi_fmt_cdb st_cmd  = { 6, 0, 0, 0, 0, 0, 0 };
307 
308 u_char sensebuf[8];
309 
310 int
311 stread(dev, buf, size)
312 	dev_t dev;
313 	char *buf;
314 	int   size;
315 {
316 	register int unit = stunit(dev);
317 	register struct st_softc *sc = &st_softc[unit];
318 	register struct scsi_fmt_cdb *cdb = &st_cmd;
319 	register int nblk = size >> DEV_BSHIFT;
320 	struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
321 	int ctlr, slave, stat;
322 
323 	ctlr  = sc->sc_hd->hp_ctlr;
324 	slave = sc->sc_hd->hp_slave;
325 
326 	cdb->cdb[0] = CMD_READ;
327 	cdb->cdb[1] = 1;		/* unknown setup */
328 
329 	cdb->cdb[2] = (nblk & 0xff0000) >> 16;
330 	cdb->cdb[3] = (nblk & 0x00ff00) >>  8;
331 	cdb->cdb[4] = (nblk & 0x0000ff);
332 
333 	cdb->cdb[5] = 0;		/* unknown setup */
334 
335 	stat = scsi_immed_command(ctlr, slave, 0, cdb, buf, size);
336 
337 	if (stat == 0)
338 		return(size);
339 	else {
340 		scsi_request_sense(ctlr, slave, 0, sp, 8);
341 
342 		if (stat == STS_CHECKCOND) {
343 			printf("stread: Sense Key = [%s]", sense_key(sp->key));
344 			if (sp->filemark)
345 				printf(" [EOF]");
346 			if (sp->eom)
347 				printf(" [EOM]");
348 			printf("\n");
349 		}
350 
351 		return(-1);
352 	}
353 }
354 
355 int
356 stwrite(dev, buf, size)
357 	dev_t dev;
358 	char *buf;
359 	int   size;
360 {
361 	register int unit = stunit(dev);
362 	register struct st_softc *sc = &st_softc[unit];
363 	register struct scsi_fmt_cdb *cdb = &st_cmd;
364 	struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
365 	register int nblk;
366 	int ctlr, slave, stat;
367 
368 	nblk = size >> DEV_BSHIFT;
369 	if (size % DEV_BSIZE)
370 		nblk++;
371 	size = nblk << DEV_BSHIFT;
372 
373 	ctlr  = sc->sc_hd->hp_ctlr;
374 	slave = sc->sc_hd->hp_slave;
375 
376 	sc->sc_flags |= STF_WRTTN;
377 
378 	cdb->cdb[0] = CMD_WRITE;
379 	cdb->cdb[1] = 1;		/* unknown setup */
380 
381 	cdb->cdb[2] = (nblk & 0xff0000) >> 16;
382 	cdb->cdb[3] = (nblk & 0x00ff00) >>  8;
383 	cdb->cdb[4] = (nblk & 0x0000ff);
384 
385 	cdb->cdb[5] = 0;		/* unknown setup */
386 
387 	stat = scsi_immed_command(ctlr, slave, 0, cdb, buf, size);
388 
389 	if (stat == 0)
390 		return(size);
391 	else {
392 		scsi_request_sense(ctlr, slave, 0, sp, 8);
393 
394 		if (stat == STS_CHECKCOND) {
395 			printf("stwrite: Sense Key = [%s]", sense_key(sp->key));
396 			if (sp->eom)
397 				printf(" [EOM]");
398 			printf("\n");
399 		}
400 
401 		return(-1);
402 	}
403 }
404 
405 int
406 stioctl(dev, cmd, data, flag, p)
407 	dev_t dev;
408 	int cmd;
409 	caddr_t data;
410 	int flag;
411 	struct proc *p;
412 {
413 }
414 
415 st_rewind(dev)
416 	dev_t dev;
417 {
418 	register int unit = stunit(dev);
419 	register struct st_softc *sc = &st_softc[unit];
420 	register struct scsi_fmt_cdb *cdb = &st_cmd;
421 	struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
422 	int ctlr, slave, stat;
423 	int retry = 5;
424 
425 	ctlr  = sc->sc_hd->hp_ctlr;
426 	slave = sc->sc_hd->hp_slave;
427 
428 	cdb->cdb[0] = CMD_REWIND;
429 	cdb->cdb[1] = 1;	/* command finished soon */
430 
431 	cdb->cdb[2] = 0;
432 	cdb->cdb[3] = 0;
433 	cdb->cdb[4] = 0;
434 
435 	cdb->cdb[5] = 0;		/* unknown setup */
436 
437  rewind:
438 	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
439 
440 	if (stat == 0) {
441 		return(1);
442 	} else {
443 		scsi_request_sense(ctlr, slave, 0, sp, 8);
444 
445 		if (stat == STS_CHECKCOND) {
446 			printf("st_rewind: Sense Key = [%s]", sense_key(sp->key));
447 			printf("\n");
448 		}
449 
450 		if (retry > 0) {
451 			DELAY(1000000);
452 			retry--;
453 			goto rewind;
454 		}
455 
456 		return(0);
457 	}
458 }
459 
460 st_write_EOF(dev)
461 	dev_t dev;
462 {
463 	register int unit = stunit(dev);
464 	register struct st_softc *sc = &st_softc[unit];
465 	register struct scsi_fmt_cdb *cdb = &st_cmd;
466 	int ctlr, slave, stat;
467 	int marks = 1;
468 
469 	ctlr  = sc->sc_hd->hp_ctlr;
470 	slave = sc->sc_hd->hp_slave;
471 
472 	cdb->cdb[0] = CMD_WRITE_FILEMARK;
473 	cdb->cdb[1] = 1;	/* command finished soon */
474 
475 	cdb->cdb[2] = (marks & 0xff0000) >> 16;
476 	cdb->cdb[3] = (marks & 0x00ff00) >>  8;
477 	cdb->cdb[4] = (marks & 0x0000ff);
478 
479 	cdb->cdb[5] = 0;		/* unknown setup */
480 
481 	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
482 
483 	if (stat == 0)
484 		return(1);
485 
486 	printf("st: write EOF error\n");
487 
488 	return(0);
489 }
490 
491 int
492 st_skip(dev)
493 	dev_t dev;
494 {
495 	register int unit = stunit(dev);
496 	register struct st_softc *sc = &st_softc[unit];
497 	register struct scsi_fmt_cdb *cdb = &st_cmd;
498 	register int nfmk = 1;
499 	struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
500 	int ctlr, slave, stat;
501 
502 	ctlr  = sc->sc_hd->hp_ctlr;
503 	slave = sc->sc_hd->hp_slave;
504 
505 	cdb->cdb[0] = CMD_SPACE;
506 	cdb->cdb[1] = 1;		/* it mean skip until EOF */
507 
508 	cdb->cdb[2] = (nfmk & 0xff0000) >> 16;
509 	cdb->cdb[3] = (nfmk & 0x00ff00) >>  8;
510 	cdb->cdb[4] = (nfmk & 0x0000ff);
511 
512 	cdb->cdb[5] = 0;		/* unknown setup */
513 
514 	stat = scsi_immed_command(ctlr, slave, 0, cdb, 0, 0);
515 
516 	if (stat == 0)
517 		return(0);
518 	else {
519 		scsi_request_sense(ctlr, slave, 0, sp, 8);
520 
521 		if (stat == STS_CHECKCOND) {
522 			printf("st_skip: Sense Key = [%s]", sense_key(sp->key));
523 			if (sp->filemark)
524 				printf(" [EOF]");
525 			if (sp->eom)
526 				printf(" [EOM]");
527 			printf("\n");
528 		}
529 
530 		return(-1);
531 	}
532 }
533 
534 /*
535  * Dump
536  */
537 
538 int
539 stdump(dev)
540 	dev_t dev;
541 {
542 }
543