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
stinit(hd)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
stident(sc,hd)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
stopen(dev)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*/
stclose(dev)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
ststrategy()208 ststrategy()
209 {
210 }
211
212 int
ststart(unit)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
sterror(unit,sc,hp,stat)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
stintr(unit,stat)267 stintr(unit, stat)
268 register int unit;
269 int stat;
270 {
271 }
272
273
274 /*
275 * RAW Device Routines
276 */
277
278 char *
sense_key(key)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
stread(dev,buf,size)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
stwrite(dev,buf,size)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
stioctl(dev,cmd,data,flag,p)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
st_rewind(dev)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
st_write_EOF(dev)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
st_skip(dev)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
stdump(dev)539 stdump(dev)
540 dev_t dev;
541 {
542 }
543