xref: /original-bsd/sys/news3400/iodev/scsi.c (revision 3705696b)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
7  *
8  * %sccs.include.redist.c%
9  *
10  * from: $Hdr: scsi.c,v 4.300 91/06/27 20:42:51 root Rel41 $ SONY
11  *
12  *	@(#)scsi.c	8.1 (Berkeley) 06/11/93
13  */
14 
15 /*
16  *	scsi.c	ver 1.1
17  */
18 
19 #include <machine/param.h>
20 
21 #include <sys/param.h>
22 #include <sys/buf.h>
23 #include <sys/proc.h>
24 #include <sys/user.h>
25 
26 # include <machine/cpu.h>
27 
28 #include <news3400/hbdev/hbvar.h>
29 #include <news3400/hbdev/scsic.h>
30 #include <news3400/hbdev/screg_1185.h>
31 
32 #include <news3400/iodev/scsireg.h>
33 #include <news3400/iodev/ioptohb.h>
34 
35 #define DEBUG_LOSSBSY_HUNG
36 
37 #ifdef DEBUG_LOSSBSY_HUNG
38 # define PROBE_MAXRETRY	100
39 #endif
40 
41 #ifndef NO_SCSI_DISCONNECT
42 int Scsi_Disconnect = IDT_DISCON;
43 #else
44 int Scsi_Disconnect = 0;
45 #endif
46 
47 # define MAXCTLR	8
48 struct sc_data sc_data[MAXCTLR];
49 struct scintsw scintsw[MAXCTLR];
50 
51 #ifdef RSENSE_MSG_DISP
52 int	rsense_msg_disp = 1;	/* RSENSE-message display flag */
53 #else
54 int	rsense_msg_disp = 0;	/* RSENSE-message display flag */
55 #endif
56 
57 int	mo_disp_format = 0;	/* MO format mode display flag */
58 
59 struct msg_list {
60 	int	ml_code;		/* message code */
61 	int	ml_msglvl;		/* message level */
62 	char	*ml_msgstr;		/* message string */
63 };
64 
65 #ifdef NO_SHRINK_RSENSE_MSG
66 #	define MSG(m) m
67 #else
68 #	define MSG(m) NULL
69 #endif
70 
71 struct msg_list skeylist[] = {
72 	{ 0x00,	1, MSG("No Sense") },
73 	{ 0x01,	0, MSG("Recoverable Error") },
74 	{ 0x02,	0, MSG("Not Ready") },
75 	{ 0x03,	0, MSG("Medium Error") },
76 	{ 0x04,	0, MSG("Hardware Error") },
77 	{ 0x05, 0, MSG("Illegal Request") },
78 	{ 0x06, 1, MSG("Unit Attention") },
79 	{ 0x07,	1, MSG("Data protect") },
80 	{ 0x08, 0, MSG("Blank Check") },
81 	{ 0x09,	0, MSG("Vendor Unique") },
82 	{ 0x0a,	0, MSG("Copy/Compare Aborted") },
83 	{ 0x0b, 0, MSG("Aborted Command") },
84 	{ 0x0c, 0, MSG("Equal") },
85 	{ 0x0d, 0, MSG("Volume Overflow") },
86 	{ 0x0e,	0, MSG("Miscompare") },
87 	{ -1,	0, (caddr_t)0 }
88 };
89 
90 struct msg_list ecodelist[] = {
91 	{ 0x00, 9, MSG("No Additional Sense Information") },
92 /*HD*/	{ 0x01, 1, MSG("No Index/Address Mark Found signal") },
93 	{ 0x02, 0, MSG("No Seek Complete") },
94 	{ 0x03, 0, MSG("Write Fault") },
95 	{ 0x04, 9, MSG("Drive Not Ready") },
96 	{ 0x05, 0, MSG("Drive Not Selected") },
97 /*HD*/	{ 0x06, 0, MSG("No Track Zero") },
98 	{ 0x07, 0, MSG("Multiple Drives Selected") },
99 	{ 0x08, 0, MSG("Logical Unit Communication Failure") },
100 	{ 0x09, 2, MSG("Track Following Error") },
101 /*MO*/	{ 0x0a, 1, MSG("No Disk") },
102 /*MO*/	{ 0x0b, 1, MSG("Load/Unload Failure") },
103 /*MO*/	{ 0x0c, 1, MSG("Spindle Failure") },
104 /*MO*/	{ 0x0d, 1, MSG("Focus Failure") },
105 /*MO*/	{ 0x0e, 1, MSG("Tracking Failure") },
106 /*MO*/	{ 0x0f, 0, MSG("Drive Initialization Failure") },
107 	{ 0x10, 1, MSG("ID CRC or ECC error") },
108 	{ 0x11, 0, MSG("Unrecoverd Read error") },
109 /*HD*/	{ 0x12, 0, MSG("No Address Mark (byte sync byte) found in ID field") },
110 /*HD*/	{ 0x13, 0, MSG("No Address Mark (byte sync byte) found in Data field") },
111 /*HD*/	{ 0x14, 0, MSG("No record found") },
112 	{ 0x15, 1, MSG("Seek Positioning Error") },
113 
114 /*HD*/	{ 0x17, 0, MSG("Recovered Read data with Read retries") },
115 	{ 0x18, 0, MSG("Recovered Read data with ECC procedure") },
116 /*HD*/	{ 0x19, 0, MSG("Defect List error") },
117 /*HD*/	{ 0x1a, 0, MSG("Parameter overrun") },
118 /*HD*/	{ 0x1b, 0, MSG("Synchronous transfer error") },
119 /*HD*/	{ 0x1c, 0, MSG("Primary Defect List not found") },
120 /*HD*/	{ 0x1d, 0, MSG("Compare error") },
121 
122 	{ 0x20, 0, MSG("Invalid Command Operation Code") },
123 	{ 0x21, 0, MSG("Illegal Logical Block Address") },
124 /*HD*/	{ 0x22, 0, MSG("Illegal function for device type") },
125 /*MO*/	{ 0x23, 0, MSG("Illegal function for Medium Type") },
126 	{ 0x24, 0, MSG("Illegal Field in CDB") },
127 	{ 0x25, 0, MSG("Invalid LUN") },
128 	{ 0x26, 0, MSG("Invalid field in Parameter List") },
129 	{ 0x27, 0, MSG("Write Protected") },
130 	{ 0x28, 1, MSG("Medium Changed") },
131 	{ 0x29, 1, MSG("Power On or Reset or Bus Device Reset Occured") },
132 	{ 0x2a, 1, MSG("Mode Select Parameters Changed") },
133 /*HD*/	{ 0x2b, 0, MSG("Host cannot Disconnect") },
134 
135 	{ 0x31, 0, MSG("Medium Format Corrupted") },
136 	{ 0x32, 0, MSG("No Defect Spare Location Available") },
137 
138 /*MO*/	{ 0x38, 1, MSG("Recovered with Automatic Reallocation") },
139 /*MO*/	{ 0x39, 0, MSG("Automatic Reallocation Failure") },
140 /*MO*/	{ 0x3a, 1, MSG("Defect List Update Failure") },
141 
142 /*MO*/	{ 0x3d, 0, MSG("Defect List Not Available") },
143 
144 /*HD*/	{ 0x40, 0, MSG("RAM failure") },
145 /*HD*/	{ 0x41, 0, MSG("Data Path diagnostic failure") },
146 	{ 0x42, 0, MSG("Power On Diagnostic Failure") },
147 	{ 0x43, 0, MSG("Message Reject Error") },
148 	{ 0x44, 9, MSG("Internal Controller Error") },
149 /*HD*/	{ 0x45, 0, MSG("Selection/Reselection failure") },
150 
151 	{ 0x47, 0, MSG("SCSI Interface Parity Error") },
152 	{ 0x48, 0, MSG("Initiator Detected Error") },
153 	{ 0x49, 0, MSG("Inappropriate/Illegal Message") },
154 
155 	{ 0x64, 1, MSG("Illegal mode for this track") },
156 
157 	{ -1,   0, (caddr_t)0 }
158 };
159 #undef MSG
160 
161 /*
162  * Init a scsi bus.
163  */
164 scop_init(scn)
165 	int	scn;
166 {
167 	static struct scsi sc;
168 	int chan;
169 
170 	for (chan = 0; chan < MAXCTLR; chan++) {
171 		bzero((caddr_t)&sc, sizeof(struct scsi));
172 		sc.sc_cdb.un_reserved[0] = SCOP_RESET;
173 		sc.sc_cdb.un_reserved[1] = SCOP_RESET;
174 
175 		if (!sc_busy(chan)) {
176 			sc_go(chan, (struct scsi *)&sc, SCSI_INTDIS);
177 
178 			chan = (chan / 8 + 1) * 8;
179 		}
180 	}
181 }
182 
183 /**************************************
184 	The multiple scsi bus is NOT suported by following routines.
185 	How about use inter like dev_t ( uper is scsi#, lower is inter )
186 	or hb_ctlr.
187 	probe() ga futatuarukara unit# ----- udauda.
188 **************************************/
189 
190 /*
191  * scprobe. probe routine for mass storage controller.
192  */
193 scprobe(im, ctlrintr, sc)
194 	struct iop/**/_ctlr *im;
195 	int (*ctlrintr)();
196 	register struct scsi *sc;
197 {
198 	register struct scintsw *sci;
199 	int s;
200 #ifdef DEBUG_LOSSBSY_HUNG
201 	int retry = 0;
202 #endif DEBUG_LOSSBSY_HUNG
203 
204 	sci = &scintsw[im->im_intr];
205 	if (sci->sci_inthandler)
206 		return (0);
207 
208 #ifdef DEBUG_LOSSBSY_HUNG
209 scprobe_loop:
210 	/* s = splsc(); */
211 	scop_inquiry(im->im_intr, sc, 0, SCSI_INTDIS, 4, (caddr_t)0);
212 	/* splx(s); */
213 
214 	if (sc->sc_istatus != INST_EP) {
215 		if ((sc->sc_tstatus == TGST_BUSY) && (retry++ < PROBE_MAXRETRY)) {
216 			goto scprobe_loop;
217 		}
218 		return (0);
219 	}
220 
221 #else /* DEBUG_LOSSBSY_HUNG */
222 
223 	/* s = splsc(); */
224 	scop_inquiry(im->im_intr, sc, 0, SCSI_INTDIS, 4, (caddr_t)0);
225 	/* splx(s); */
226 
227 	if (sc->sc_istatus != INST_EP)
228 		return (0);
229 
230 #endif /* DEBUG_LOSSBSY_HUNG */
231 
232 	sci->sci_inthandler = ctlrintr;
233 	sci->sci_ctlr = im->im_ctlr;
234 	return (1);
235 }
236 
237 /*
238  * ssprobe. probe routine for non-mass storage peripherals.
239  */
240 ssprobe(ii, ctlrintr, sc)
241 	struct iop/**/_device *ii;
242 	int (*ctlrintr)();
243 	register struct scsi *sc;
244 {
245 	register struct scintsw *sci;
246 	int s;
247 
248 	sci = &scintsw[ii->ii_intr];
249 	if (sci->sci_inthandler)
250 		return (0);
251 
252 	/* s = splsc(); */
253 	scop_inquiry(ii->ii_intr, sc, 0, SCSI_INTDIS, 4, (caddr_t)0);
254 	/* splx(s); */
255 
256 	if (sc->sc_istatus != INST_EP)
257 		return (0);
258 
259 	sci->sci_inthandler = ctlrintr;
260 	sci->sci_ctlr = ii->ii_unit;
261 	return (1);
262 }
263 
264 /*
265  * SCOP_TST request
266  */
267 scop_tst(intr, sc, slave, ie)
268 	register int intr;
269 	register struct scsi *sc;
270 	register int slave;
271 	register int ie;
272 {
273 	scinit(sc, slave, DEV_BSIZE);
274 
275 	/* sc_cdb */
276 	sc->sc_opcode = SCOP_TST;
277 
278 	sc_go(intr, (struct scsi *)sc, ie);
279 }
280 
281 /*
282  * SCOP_REZERO request
283  */
284 scop_rezero(intr, sc, slave, ie)
285 	register int intr;
286 	register struct scsi *sc;
287 	register int slave;
288 	register int ie;
289 {
290 	scinit(sc, slave, DEV_BSIZE);
291 
292 	/* sc_cdb */
293 	sc->sc_opcode = SCOP_REZERO;
294 
295 	sc_go(intr, (struct scsi *)sc, ie);
296 }
297 
298 /*
299  * SCOP_REWIND request
300  */
301 scop_rewind(intr, sc, slave, ie, imme)
302 	register int intr;
303 	register struct scsi *sc;
304 	register int slave;
305 	register int ie, imme;
306 {
307 	scinit(sc, slave, DEV_BSIZE);
308 
309 	/* sc_cdb */
310 	sc->sc_opcode = SCOP_REZERO;
311 	sc->sc_tucode = imme;
312 
313 	sc_go(intr, (struct scsi *)sc, ie);
314 }
315 
316 /*
317  * SCOP_RSENSE request
318  */
319 scop_rsense(intr, sc, slave, ie, count, param)
320 	register int intr;
321 	register struct scsi *sc;
322 	register int slave;
323 	register int ie;
324 	register int count;
325 	register caddr_t param;
326 {
327 	scinit(sc, slave, DEV_BSIZE);
328 
329 	sc->sc_cpoint = (u_char *)param;
330 	sc->sc_ctrnscnt = count;
331 
332 	/* sc_cdb */
333 	sc->sc_opcode = SCOP_RSENSE;
334 	sc->sc_count = count;
335 
336 	sc_go(intr, (struct scsi *)sc, ie);
337 }
338 
339 /*
340  * SCOP_RASBLK request
341  */
342 scop_rasblk(intr, sc, slave, ie, lad)
343 	register int intr;
344 	register struct scsi *sc;
345 	register int slave;
346 	register int ie;
347 	register int lad;
348 {
349 	struct sc_rab *sca = (struct sc_rab *)sc->sc_param;
350 
351 	scinit(sc, slave, DEV_BSIZE);
352 
353 	sca->sca_dllen = 4;
354 	sca->sca_dlad[0] = lad;
355 	sc->sc_cpoint = (u_char *)sca;
356 
357 	sc->sc_ctrnscnt = 8;
358 
359 	/* sc_cdb */
360 	sc->sc_opcode = SCOP_RASBLK;
361 
362 	sc_go(intr, (struct scsi *)sc, ie);
363 }
364 
365 /*
366  * SCOP_MERASE request
367  */
368 scop_merase(intr, sc, slave, ie, count)
369 	register int intr;
370 	register struct scsi *sc;
371 	register int slave;
372 	register int ie;
373 	register int count;
374 {
375 	scinit(sc, slave, DEV_BSIZE);
376 
377 	/* sc_cdb */
378 	sc->sc_opcode = SCOP_MERASE;
379 	sc->sc_mtcount3 = count;
380 
381 	sc_go(intr, (struct scsi *)sc, ie);
382 }
383 
384 /*
385  * SCOP_WFMARK request
386  */
387 scop_wfmark(intr, sc, slave, ie, count)
388 	register int intr;
389 	register struct scsi *sc;
390 	register int slave;
391 	register int ie;
392 	register int count;
393 {
394 	scinit(sc, slave, DEV_BSIZE);
395 
396 	/* sc_cdb */
397 	sc->sc_opcode = SCOP_WFMARK;
398 	count &= 0xffffff;
399 	sc->sc_tucount3 = count & 0xff;
400 	count >>= 8;
401 	sc->sc_tucount2 = count & 0xff;
402 	count >>= 8;
403 	sc->sc_tucount1 = count & 0xff;
404 
405 	sc_go(intr, (struct scsi *)sc, ie);
406 }
407 
408 /*
409  * SCOP_SPACE request
410  */
411 scop_space(intr, sc, slave, ie, count, code)
412 	register int intr;
413 	register struct scsi *sc;
414 	register int slave;
415 	register int ie;
416 	register int count;
417 	register int code;
418 {
419 	scinit(sc, slave, DEV_BSIZE);
420 
421 	/* sc_cdb */
422 	sc->sc_opcode = SCOP_SPACE;
423 	sc->sc_tucode = code;
424 	count &= 0xffffff;
425 	sc->sc_tucount3 = count & 0xff;
426 	count >>= 8;
427 	sc->sc_tucount2 = count & 0xff;
428 	count >>= 8;
429 	sc->sc_tucount1 = count & 0xff;
430 
431 	sc_go(intr, (struct scsi *)sc, ie);
432 }
433 
434 /*
435  * SCOP_INQUIRY request
436  */
437 scop_inquiry(intr, sc, slave, ie, count, param)
438 	register int intr;
439 	register struct scsi *sc;
440 	register int slave;
441 	register int ie;
442 	register int count;
443 	register caddr_t param;
444 {
445 	scinit(sc, slave, DEV_BSIZE);
446 
447 	sc->sc_cpoint = (u_char *)param;
448 	sc->sc_ctrnscnt = count;
449 
450 	/* sc_cdb */
451 	sc->sc_opcode = SCOP_INQUIRY;
452 	sc->sc_count = count;
453 
454 	sc_go(intr, (struct scsi *)sc, ie);
455 }
456 
457 /*
458  * SCOP_STST request
459  */
460 scop_stst(intr, sc, slave, ie, sw)
461 	register int intr;
462 	register struct scsi *sc;
463 	register int slave;
464 	register int ie;
465 	register int sw;
466 {
467 	scinit(sc, slave, DEV_BSIZE);
468 
469 	/* sc_cdb */
470 	sc->sc_opcode = SCOP_STST;
471 	sc->sc_switch = sw;
472 
473 	sc_go(intr, (struct scsi *)sc, ie);
474 }
475 
476 /*
477  * SCOP_RCAP request
478  */
479 scop_rcap(intr, sc, slave, ie, count, param)
480 	register int intr;
481 	register struct scsi *sc;
482 	register int slave;
483 	register int ie;
484 	register int count;
485 	register caddr_t param;
486 {
487 	scinit(sc, slave, DEV_BSIZE);
488 
489 	sc->sc_cpoint = (u_char *)param;
490 	sc->sc_ctrnscnt = count;
491 
492 	/* sc_cdb */
493 	sc->sc_opcode = SCOP_RCAP;
494 	sc->sc_pmi = OFF;
495 
496 	sc_go(intr, (struct scsi *)sc, ie);
497 }
498 
499 /*
500  * SCOP_BSSRCH request
501  */
502 scop_bssrch(intr, sc, slave, ie, count, param)
503 	register int intr;
504 	register struct scsi *sc;
505 	register int slave;
506 	register int ie;
507 	register int count;
508 	register caddr_t param;
509 {
510 	scinit(sc, slave, DEV_BSIZE);
511 
512 	sc->sc_cpoint = (u_char *)param;
513 	sc->sc_ctrnscnt = count;
514 
515 	/* sc_cdb */
516 	sc->sc_opcode = SCOP_BSSRCH;
517 	sc->sc_ladhi = *(short *)param;
518 	sc->sc_ladlo = *(short *)(param + 2);
519 
520 	sc_go(intr, (struct scsi *)sc, ie);
521 }
522 
523 /*
524  * SCOP_WSSRCH request
525  */
526 scop_wssrch(intr, sc, slave, ie, count, param)
527 	register int intr;
528 	register struct scsi *sc;
529 	register int slave;
530 	register int ie;
531 	register int count;
532 	register caddr_t param;
533 {
534 	scinit(sc, slave, DEV_BSIZE);
535 
536 	sc->sc_cpoint = (u_char *)param;
537 	sc->sc_ctrnscnt = count;
538 
539 	/* sc_cdb */
540 	sc->sc_opcode = SCOP_WSSRCH;
541 	sc->sc_ladhi = *(short *)param;
542 	sc->sc_ladlo = *(short *)(param + 2);
543 
544 	sc_go(intr, (struct scsi *)sc, ie);
545 }
546 
547 /*
548  *
549  * SCOP_EESENSE request
550  * Enable/Disable Eject Request Sense
551  * Write Once only supported.
552  *
553  */
554 scop_eesense(intr, sc, slave, ie, sw)
555 	register int intr;
556 	register struct scsi *sc;
557 	register int slave;
558 	register int ie;
559 	register int sw;
560 {
561 	scinit(sc, slave, DEV_BSIZE);
562 
563 	/* sc_cdb */
564 	sc->sc_opcode = SCOP_EESENSE;
565 	sc->sc_switch = sw;
566 
567 	sc_go(intr, (struct scsi *)sc, ie);
568 }
569 
570 /*
571  * SCOP_EJECT
572  */
573 scop_eject(intr, sc, slave, ie)
574 	register int intr;
575 	register struct scsi *sc;
576 	register int slave;
577 	register int ie;
578 {
579 	scinit(sc, slave, DEV_BSIZE);
580 
581 	/* sc_cdb */
582 	sc->sc_opcode = SCOP_EJECT;
583 
584 	sc_go(intr, (struct scsi *)sc, ie);
585 }
586 
587 /*
588  * SCOP_RBLIM request
589  */
590 scop_rblim(intr, sc, slave, ie, count, param)
591 	register int intr;
592 	register struct scsi *sc;
593 	register int slave;
594 	register int ie;
595 	register int count;
596 	register caddr_t param;
597 {
598 	scinit(sc, slave, DEV_BSIZE);
599 
600 	sc->sc_cpoint = (u_char *)param;
601 	sc->sc_ctrnscnt = count & 0xff;
602 
603 	/* sc_cdb */
604 	sc->sc_opcode = SCOP_RBLIM;
605 
606 	sc_go(intr, (struct scsi *)sc, ie);
607 }
608 
609 /*
610  * SCOP_MSENSE request
611  */
612 scop_msense(intr, sc, slave, ie, count, param)
613 	register int intr;
614 	register struct scsi *sc;
615 	register int slave;
616 	register int ie;
617 	register int count;
618 	register caddr_t param;
619 {
620 	scinit(sc, slave, DEV_BSIZE);
621 
622 	sc->sc_cpoint = (u_char *)param;
623 	sc->sc_ctrnscnt = count & 0xff;
624 
625 	/* sc_cdb */
626 	sc->sc_opcode = SCOP_MSENSE;
627 	sc->sc_lad = count >> 8;
628 	sc->sc_count = count & 0xff;
629 
630 	sc_go(intr, (struct scsi *)sc, ie);
631 }
632 
633 /*
634  * SCOP_MSELECT request
635  */
636 scop_mselect(intr, sc, slave, ie, count, param)
637 	register int intr;
638 	register struct scsi *sc;
639 	register int slave;
640 	register int ie;
641 	register int count;
642 	register caddr_t param;
643 {
644 	u_char psave[20];
645 
646 	bcopy((caddr_t)sc->sc_param, (caddr_t)psave, 20);
647 	scinit(sc, slave, DEV_BSIZE);
648 	bcopy((caddr_t)psave, (caddr_t)sc->sc_param, 20);
649 
650 	sc->sc_cpoint = (u_char *)param;
651 	sc->sc_ctrnscnt = count & 0xff;
652 
653 	/* sc_cdb */
654 	sc->sc_opcode = SCOP_MSELECT;
655 	sc->sc_lad = count >> 8;
656 	sc->sc_count = count & 0xff;
657 
658 	sc_go(intr, (struct scsi *)sc, ie);
659 }
660 
661 #ifdef SRD_MSELECT
662 /*
663  * SCOP_MSELECT request
664  */
665 scop_msense_OTHER_HD(intr, sc, slave, ie, count, param)
666 	register int intr;
667 	register struct scsi *sc;
668 	register int slave;
669 	register int ie;
670 	register int count;
671 	register caddr_t param;
672 {
673 	scinit(sc, slave, DEV_BSIZE);
674 
675 	sc->sc_cpoint = (u_char *)param;
676 	sc->sc_ctrnscnt = count;
677 
678 	/* sc_cdb */
679 	sc->sc_opcode = SCOP_MSENSE;
680 	sc->sc_count = count;
681 	sc->sc_lad = 0x3f00;
682 
683 	sc_go(intr, (struct scsi *)sc, ie);
684 }
685 
686 /*
687  * SCOP_MSELECT request
688  */
689 scop_mselect_OTHER_HD(intr, sc, slave, ie, count, param)
690 	register int intr;
691 	register struct scsi *sc;
692 	register int slave;
693 	register int ie;
694 	register int count;
695 	register caddr_t param;
696 {
697 	u_char psave[20];
698 
699 	bcopy((caddr_t)sc->sc_param, (caddr_t)psave, 20);
700 	scinit(sc, slave, DEV_BSIZE);
701 	bcopy((caddr_t)psave, (caddr_t)sc->sc_param, 20);
702 
703 	sc->sc_cpoint = (u_char *)param;
704 	sc->sc_ctrnscnt = count;
705 
706 	/* sc_cdb */
707 	sc->sc_opcode = SCOP_MSELECT;
708 	sc->sc_count = count;
709 	sc->sc_lad = 0;
710 
711 	sc_go(intr, (struct scsi *)sc, ie);
712 }
713 #endif SRD_MSELECT
714 
715 scop_erase(intr, sc, slave, ie)
716 	register int intr;
717 	register struct scsi *sc;
718 	register int slave;
719 	register int ie;
720 {
721 	scinit(sc, slave, DEV_BSIZE);
722 
723 	/* sc_cdb */
724 	sc->sc_opcode = SCOP_ERASE;
725 	sc->sc_tucode = 1;
726 
727 	sc_go(intr, (struct scsi *)sc, ie);
728 }
729 
730 /*
731  * One sector programmed I/O
732  */
733 scop_rdwr(intr, sc, slave, ie, flag, addr, lba, sectsize)
734 	int	intr;
735 	register struct scsi	*sc;
736 	int	slave;
737 	int	ie;
738 	int	flag;
739 	caddr_t	addr;
740 	int	lba;
741 	int	sectsize;
742 {
743 	scinit(sc, slave, sectsize);
744 
745 	sc->sc_cpoint = (u_char *)addr;
746 	sc->sc_ctrnscnt = sectsize;
747 
748 	/* sc_cdb */
749 	sc->sc_opcode = (flag & B_READ) ? SCOP_READ : SCOP_WRITE;
750 	sc->sc_lad = lba;
751 	sc->sc_count = 1;
752 
753 	sc_go(intr, sc, ie);
754 }
755 
756 /*
757  * Medium allow/prevent removable
758  */
759 scop_medrmv(intr, sc, slave, ie, sw)
760 	register int intr;
761 	register struct scsi *sc;
762 	register int slave;
763 	register int ie;
764 	register int sw;
765 {
766 	scinit(sc, slave, DEV_BSIZE);
767 
768 	/* sc_cdb */
769 	sc->sc_opcode = SCOP_MEDRMV;
770 	sc->sc_count = sw;
771 
772 	sc_go(intr, (struct scsi *)sc, ie);
773 }
774 
775 /*
776  * initialize struct scsi
777  */
778 scinit(sc, slave, sectsize)
779 	register struct scsi *sc;
780 	int	slave;
781 	int	sectsize;
782 {
783 	bzero((caddr_t)sc, sizeof(struct scsi));
784 
785 	sc->sc_identify = MSG_IDENT|Scsi_Disconnect|(slave & IDT_DRMASK);
786 	sc->sc_bytesec = sectsize;
787 	sc->sc_lun = slave;
788 }
789 
790 
791 /*
792  * ABORT MESSAGE
793  */
794 scms_abort(intr, sc, slave, ie)
795 	register int intr;
796 	register struct scsi *sc;
797 	register int slave;
798 	register int ie;
799 {
800 	bzero((caddr_t)sc, sizeof(struct scsi));
801 
802 	sc->sc_identify = MSG_ABORT;
803 
804 	/* sc_cdb */
805 	sc->sc_opcode = SCOP_TST;
806 	sc->sc_lun = slave;
807 
808 	sc_go(intr, (struct scsi *)sc, ie);
809 }
810 
811 sc_go(intr, sc, ie)
812 	int intr;
813 	struct scsi *sc;
814 	int ie;
815 {
816 	register struct sc_data *scdp;
817 
818 	scdp = &sc_data[intr];
819 
820 	if (sc->sc_cpoint)
821 		scdp->scd_vaddr = (char *)sc->sc_cpoint;
822 	else
823 		scdp->scd_vaddr = (char *)sc->sc_param;
824 	scdp->scd_procp = curproc;
825 	scdp->scd_scaddr = (char *)sc;
826 	scdp->scd_count = sc->sc_ctrnscnt;
827 	sc->sc_cpoint = (u_char *)ipc_phys(scdp->scd_vaddr);
828 
829 	_sc_go(intr, sc, ie);
830 
831 	if((ie & SCSI_INTEN) == 0) {
832 #ifdef mips
833 	/* if (DATAIN_PHASE_FINISHED) */
834 	MachFlushDCache(scdp->scd_scaddr, sizeof (struct scsi));
835 	if (MACH_IS_USPACE(scdp->scd_vaddr))
836 		panic("sc_go: user address is not supported");
837 	else if (MACH_IS_CACHED(scdp->scd_vaddr))
838 		MachFlushDCache(scdp->scd_vaddr, scdp->scd_count);
839 	else if (MACH_IS_MAPPED(scdp->scd_vaddr))
840 #ifdef notyet /* KU:XXX */
841 		clean_k2dcache(scdp->scd_vaddr, scdp->scd_count);
842 #else
843 		MachFlushCache(); /* Flush all caches */
844 #endif
845 #endif /* mips */
846 	}
847 }
848 
849 #ifdef CPU_SINGLE
850 _sc_go(intr, sc, ie)
851 	int intr;
852 	struct scsi *sc;
853 	int ie;
854 {
855 	register int i, s;
856 
857 	if((ie & SCSI_INTEN) == 0) {
858 		scsend(intr, ie|SCSI_NOTWAIT, sc);
859 		while (sc_busy(intr)) {
860 			splx(splscon());	/* splsc -1 */
861 #ifdef mc68030
862 			dcia();
863 #endif
864 		}
865 	} else {
866 		scsend(intr, ie, (caddr_t)sc);
867 	}
868 }
869 #endif /* CPU_SINGLE */
870 
871 screset(chan)
872 	int chan;
873 {
874 	int i, s;
875 
876 	s = splsc();
877 	printf("SCSI: screset() called ");
878 	scop_init(chan / 8);
879 	splx(s);
880 
881 	for (s = 0; s < 10; s++) {
882 		DELAY(100000 * 10);
883 	}
884 	printf("\n");
885 	iop/**/reset();
886 }
887 
888 scsisetup(bp, map, nmap)
889 	struct buf *bp;
890 	struct sc_map *map;
891 	int nmap;
892 {
893 	return (iop/**/setup(bp, map, nmap));
894 }
895 
896 
897 /*
898  * transrate skey / ecode into message display ON/OFF value
899  *	1 : display message
900  *	0 : silence
901  */
902 isdispmsg(code, list, count)
903 	register int code;
904 	register struct msg_list *list;
905 	int count;
906 {
907 	register int msglvl = 0;
908 
909 	while (list->ml_code >= 0) {
910 		if (code == list->ml_code) {
911 			msglvl = list->ml_msglvl;
912 			break;
913 		}
914 		list++;
915 	}
916 	return (count >= msglvl);
917 }
918 
919 #ifdef NO_SHRINK_RSENSE_MSG
920 /*
921  * transrate skey / ecode into message
922  */
923 char *
924 getmsg(code, list, defmsg)
925 	int code;
926 	struct msg_list *list;
927 	char *defmsg;
928 {
929 	while (list->ml_code >= 0) {
930 		if (code == list->ml_code)
931 			return (list->ml_msgstr);
932 		list++;
933 	}
934 	return (defmsg);
935 }
936 #endif /* NO_SHRINK_RSENSE_MSG */
937 
938 check_chan_busy(intr, sc, slave)
939 	register int intr;
940 	register struct scsi *sc;
941 	register int slave;
942 {
943 	register struct sc_extnd *sce = (struct sc_extnd *)sc->sc_param;
944 	int	i = 0;
945 
946 	if (sc->sc_istatus == INST_EP) {
947 		switch (sc->sc_tstatus) {
948 
949 		case TGST_CC:
950 			scop_rsense(intr, sc, slave, SCSI_INTDIS, 18, 0);
951 			if (rsense_msg_disp ||
952 			    isdispmsg(sce->sce_skey, skeylist, 0)) {
953 #ifdef NO_SHRINK_RSENSE_MSG
954 				if (sce->sce_advalid) {
955 					printf("SCSI%d(block %d): %s (sense key = 0x%x)\n",
956 					intr,
957 					(sce->sce_infob1 << 24) +
958 					(sce->sce_infob2 << 16) +
959 					(sce->sce_infob3 <<  8) +
960 					(sce->sce_infob4),
961 					getmsg(sce->sce_skey, skeylist, "(reserved)"),
962 					sce->sce_skey);
963 				} else {
964 					printf("SCSI%d(unknown block): %s (sense key = 0x%x)\n",
965 					intr,
966 					getmsg(sce->sce_skey, skeylist, "(reserved)"),
967 					sce->sce_skey);
968 				}
969 #else /* NO_SHRINK_RSENSE_MSG */
970 				if (sce->sce_advalid) {
971 					printf("SCSI%d(sn %d): skey=0x%x)\n",
972 					intr,
973 					(sce->sce_infob1 << 24) +
974 					(sce->sce_infob2 << 16) +
975 					(sce->sce_infob3 <<  8) +
976 					(sce->sce_infob4),
977 					sce->sce_skey);
978 				} else {
979 					printf("SCSI%d: skey=0x%x)\n",
980 					intr, sce->sce_skey);
981 				}
982 #endif /* NO_SHRINK_RSENSE_MSG */
983 				printf("sense data = ");
984 				for (i = 0; i < 18; i++)
985 					printf("%x ", sc->sc_param[i]);
986 				printf("\n");
987 			}
988 			break;
989 
990 		case TGST_GOOD:
991 			break;
992 
993 		default:
994 			printf("SCSI%d: bad target status 0x%x\n", intr, sc->sc_tstatus);
995 			break;
996 		}
997 	} else {
998 		printf("SCSI%d: bad initiator status 0x%x\n", intr, sc->sc_istatus);
999 	}
1000 
1001 	while (i++ < 100000) {
1002 		scop_tst(intr, sc, slave, SCSI_INTDIS);
1003 		if (sc->sc_tstatus != TGST_BUSY)
1004 			break;
1005 	}
1006 	if (i > 100000)
1007 		printf("SCSI%d: still busy after rasblk.\n", intr);
1008 }
1009 
1010 /***/
1011 struct scsi_berr_bug_table {
1012 	int model;
1013 	int serial_l;
1014 	int serial_h;
1015 	int value;	/* 1:BUG, 0:NOBUG */
1016 };
1017 /***/
1018