xref: /csrg-svn/sys/luna68k/dev/sc.c (revision 54004)
1*54004Sfujita /*
2*54004Sfujita  * Copyright (c) 1992 OMRON Corporation.
3*54004Sfujita  * Copyright (c) 1992 The Regents of the University of California.
4*54004Sfujita  * All rights reserved.
5*54004Sfujita  *
6*54004Sfujita  * This code is derived from software contributed to Berkeley by
7*54004Sfujita  * OMRON Corporation.
8*54004Sfujita  *
9*54004Sfujita  * %sccs.include.redist.c%
10*54004Sfujita  *
11*54004Sfujita  *	@(#)sc.c	7.1 (Berkeley) 06/15/92
12*54004Sfujita  */
13*54004Sfujita 
14*54004Sfujita /*
15*54004Sfujita  * sc.c -- FUJITSU MB89352 SCSI Protocole Controller (SPC) Device Driver
16*54004Sfujita  *
17*54004Sfujita  * remaked by A.Fujita,		Mar-22-1992
18*54004Sfujita  * remaked again by A.Fujita,	Apr-16-1992
19*54004Sfujita  */
20*54004Sfujita 
21*54004Sfujita #define DEBUG_FUNC
22*54004Sfujita 
23*54004Sfujita #include "sc.h"
24*54004Sfujita #if NSC > 0
25*54004Sfujita 
26*54004Sfujita #include "sys/param.h"
27*54004Sfujita #include "sys/systm.h"
28*54004Sfujita #include "sys/buf.h"
29*54004Sfujita #include "device.h"
30*54004Sfujita 
31*54004Sfujita #include "scsireg.h"
32*54004Sfujita #include "scsivar.h"
33*54004Sfujita 
34*54004Sfujita /*
35*54004Sfujita  * SC Driver Options
36*54004Sfujita  */
37*54004Sfujita 
38*54004Sfujita #define	QUADBYTES	/* 4 bytes access to SPC DREG Reg. */
39*54004Sfujita #define	NODISCONNECT	/* not used SCSI DISCONNECT Ops. */
40*54004Sfujita #undef	XFER_ENABLE	/* using interrupt for DREG access */
41*54004Sfujita 
42*54004Sfujita 
43*54004Sfujita #define SCSI_IPL	2
44*54004Sfujita #define SCSI_ID		7
45*54004Sfujita 
46*54004Sfujita extern char *hexstr();
47*54004Sfujita 
48*54004Sfujita int	scinit(), scstart(), scintr();
49*54004Sfujita void	screset();
50*54004Sfujita struct	driver scdriver = {
51*54004Sfujita 	scinit, "sc", scstart, (int (*)()) 0, scintr, (int (*)()) 0
52*54004Sfujita };
53*54004Sfujita 
54*54004Sfujita struct	scsi_softc scsi_softc[NSC];
55*54004Sfujita 
56*54004Sfujita 
57*54004Sfujita #define	SC_TIMEOUT	0x01400000	/* (20971520) */
58*54004Sfujita 
59*54004Sfujita 
60*54004Sfujita /*
61*54004Sfujita  * for DEBUG
62*54004Sfujita  */
63*54004Sfujita 
64*54004Sfujita char *
65*54004Sfujita scsi_status(stat)
66*54004Sfujita 	u_char stat;
67*54004Sfujita {
68*54004Sfujita 	if ((stat & 0x1e) == 0)
69*54004Sfujita 		return("Good");
70*54004Sfujita 	else if ((stat & 0x1e) == STS_CHECKCOND)
71*54004Sfujita 		return("Check Condition");
72*54004Sfujita 	else if ((stat & 0x1e) == STS_CONDMET)
73*54004Sfujita 		return("Condition Met");
74*54004Sfujita 	else if ((stat & 0x1e) == STS_BUSY)
75*54004Sfujita 		return("Busy");
76*54004Sfujita 	else if ((stat & 0x1e) == STS_INTERMED)
77*54004Sfujita 		return("Intermediate status sent");
78*54004Sfujita 	else if ((stat & 0x1e) == STS_EXT)
79*54004Sfujita 		return("Extended status valid");
80*54004Sfujita 	else
81*54004Sfujita 		return("Unknown Status");
82*54004Sfujita }
83*54004Sfujita 
84*54004Sfujita #ifdef DEBUG_FUNC
85*54004Sfujita 
86*54004Sfujita char *
87*54004Sfujita scsi_command(cmd)
88*54004Sfujita 	u_char cmd;
89*54004Sfujita {
90*54004Sfujita 	if (cmd == CMD_TEST_UNIT_READY)
91*54004Sfujita 		return("TEST_UNIT_READY");
92*54004Sfujita 	else if (cmd == CMD_REQUEST_SENSE)
93*54004Sfujita 		return("REQUEST_SENSE");
94*54004Sfujita 	else if (cmd == CMD_INQUIRY)
95*54004Sfujita 		return("INQUIRY");
96*54004Sfujita 	else if (cmd == CMD_READ)
97*54004Sfujita 		return("READ");
98*54004Sfujita 	else if (cmd == CMD_WRITE)
99*54004Sfujita 		return("WRITE");
100*54004Sfujita 	else if (cmd == CMD_READ_EXT)
101*54004Sfujita 		return("READ EXT");
102*54004Sfujita 	else if (cmd == CMD_WRITE_EXT)
103*54004Sfujita 		return("WRITE_EXT");
104*54004Sfujita 	else if (cmd == CMD_READ_CAPACITY)
105*54004Sfujita 		return("READ_CAPACITY");
106*54004Sfujita 	else
107*54004Sfujita 		return(hexstr(cmd, 2));
108*54004Sfujita }
109*54004Sfujita 
110*54004Sfujita char *
111*54004Sfujita scsi_mesg(mesg)
112*54004Sfujita 	u_char mesg;
113*54004Sfujita {
114*54004Sfujita 	if (mesg == MSG_CMD_COMPLETE)
115*54004Sfujita 		return("Command Complete");
116*54004Sfujita 	else if (mesg == MSG_EXT_MESSAGE)
117*54004Sfujita 		return("Extended Message");
118*54004Sfujita 	else if (mesg == MSG_SAVE_DATA_PTR)
119*54004Sfujita 		return("Save Data Pointer");
120*54004Sfujita 	else if (mesg == MSG_RESTORE_PTR)
121*54004Sfujita 		return("Restore Pointer");
122*54004Sfujita 	else if (mesg == MSG_DISCONNECT)
123*54004Sfujita 		return("Disconnect");
124*54004Sfujita 	else if (mesg == MSG_INIT_DETECT_ERROR)
125*54004Sfujita 		return("Initiator Detected Error");
126*54004Sfujita 	else if (mesg == MSG_ABORT)
127*54004Sfujita 		return("Abort");
128*54004Sfujita 	else if (mesg == MSG_REJECT)
129*54004Sfujita 		return("Message Reject");
130*54004Sfujita 	else if (mesg == MSG_NOOP)
131*54004Sfujita 		return("No Operation");
132*54004Sfujita 	else if (mesg == MSG_PARITY_ERROR)
133*54004Sfujita 		return("Message Parity Error");
134*54004Sfujita 	else if (mesg == MSG_BUS_DEVICE_RESET)
135*54004Sfujita 		return("Bus Device Reset");
136*54004Sfujita 	else if (mesg == MSG_IDENTIFY)
137*54004Sfujita 		return("Identify");
138*54004Sfujita 	else if (mesg == MSG_IDENTIFY_DR)
139*54004Sfujita 		return("Identify (Disconnect)");
140*54004Sfujita 	else
141*54004Sfujita 		return("Unknown Message");
142*54004Sfujita }
143*54004Sfujita 
144*54004Sfujita char *
145*54004Sfujita phase_name(phase)
146*54004Sfujita 	u_char phase;
147*54004Sfujita {
148*54004Sfujita 	if (phase == DATA_OUT_PHASE)
149*54004Sfujita 		return("Data Out");
150*54004Sfujita 	else if (phase == DATA_IN_PHASE)
151*54004Sfujita 		return("Data In");
152*54004Sfujita 	else if (phase == CMD_PHASE)
153*54004Sfujita 		return("Command");
154*54004Sfujita 	else if (phase == STATUS_PHASE)
155*54004Sfujita 		return("Status");
156*54004Sfujita 	else if (phase == BUS_FREE_PHASE)
157*54004Sfujita 		return("Bus Free");
158*54004Sfujita 	else if (phase == ARB_SEL_PHASE)
159*54004Sfujita 		return("Arbitration/Select");
160*54004Sfujita 	else if (phase == MESG_OUT_PHASE)
161*54004Sfujita 		return("Message Out");
162*54004Sfujita 	else if (phase == MESG_IN_PHASE)
163*54004Sfujita 		return("Message In");
164*54004Sfujita 	else
165*54004Sfujita 		return("Unknown");
166*54004Sfujita }
167*54004Sfujita #endif
168*54004Sfujita 
169*54004Sfujita /*
170*54004Sfujita  * Initialize SPC & Data Structure
171*54004Sfujita  */
172*54004Sfujita 
173*54004Sfujita int
174*54004Sfujita scinit(hc)
175*54004Sfujita 	register struct hp_ctlr *hc;
176*54004Sfujita {
177*54004Sfujita 	register struct scsi_softc *hs = &scsi_softc[hc->hp_unit];
178*54004Sfujita 	register int i;
179*54004Sfujita 
180*54004Sfujita 	hc->hp_ipl    = SCSI_IPL;
181*54004Sfujita 	hs->sc_hc     = hc;
182*54004Sfujita 	hs->sc_sq.dq_forw = hs->sc_sq.dq_back = &hs->sc_sq;
183*54004Sfujita 	hs->sc_wq.dq_forw = hs->sc_wq.dq_back = &hs->sc_wq;
184*54004Sfujita 
185*54004Sfujita 	hs->sc_flags  = 0;
186*54004Sfujita 	hs->sc_phase  = BUS_FREE_PHASE;
187*54004Sfujita 
188*54004Sfujita 	hs->sc_stat   = 0;
189*54004Sfujita 	hs->sc_msg[0] = 0;
190*54004Sfujita 
191*54004Sfujita 	scsi_init_buf();
192*54004Sfujita 
193*54004Sfujita 	screset(hc->hp_unit);
194*54004Sfujita 
195*54004Sfujita 	return(1);
196*54004Sfujita }
197*54004Sfujita 
198*54004Sfujita void
199*54004Sfujita screset(unit)
200*54004Sfujita 	register int unit;
201*54004Sfujita {
202*54004Sfujita 	register struct scsi_softc *hs = &scsi_softc[unit];
203*54004Sfujita 	volatile register struct scsidevice *hd =
204*54004Sfujita 				(struct scsidevice *)hs->sc_hc->hp_addr;
205*54004Sfujita 
206*54004Sfujita 	printf("sc%d: ", unit);
207*54004Sfujita 
208*54004Sfujita 	/*
209*54004Sfujita 	 * Disable interrupts then reset the FUJI chip.
210*54004Sfujita 	 */
211*54004Sfujita 
212*54004Sfujita 	hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
213*54004Sfujita 	hd->scsi_scmd = 0;
214*54004Sfujita 	hd->scsi_pctl = 0;
215*54004Sfujita 	hd->scsi_temp = 0;
216*54004Sfujita 	hd->scsi_tch  = 0;
217*54004Sfujita 	hd->scsi_tcm  = 0;
218*54004Sfujita 	hd->scsi_tcl  = 0;
219*54004Sfujita 	hd->scsi_ints = 0;
220*54004Sfujita 
221*54004Sfujita 	/* We can use Asynchronous Transfer only */
222*54004Sfujita 	printf("async");
223*54004Sfujita 
224*54004Sfujita 	/*
225*54004Sfujita 	 * Configure MB89352 with its SCSI address, all
226*54004Sfujita 	 * interrupts enabled & appropriate parity.
227*54004Sfujita 	 */
228*54004Sfujita 	hd->scsi_bdid = SCSI_ID;
229*54004Sfujita 	hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB|
230*54004Sfujita 			SCTL_PARITY_ENAB | SCTL_RESEL_ENAB |
231*54004Sfujita 			SCTL_INTR_ENAB;
232*54004Sfujita 	printf(", parity");
233*54004Sfujita 
234*54004Sfujita 	DELAY(400);
235*54004Sfujita 	hd->scsi_sctl &= ~SCTL_DISABLE;
236*54004Sfujita 
237*54004Sfujita 	printf(", scsi id %d\n", SCSI_ID);
238*54004Sfujita }
239*54004Sfujita 
240*54004Sfujita 
241*54004Sfujita /*
242*54004Sfujita  * SPC Arbitration/Selection routine
243*54004Sfujita  */
244*54004Sfujita 
245*54004Sfujita int
246*54004Sfujita issue_select(hd, target, flags)
247*54004Sfujita 	volatile register struct scsidevice *hd;
248*54004Sfujita 	u_char target;
249*54004Sfujita 	int flags;
250*54004Sfujita {
251*54004Sfujita #ifndef NODISCONNECT
252*54004Sfujita 	if (flags & DQ_DISCONNECT) {
253*54004Sfujita 		hd->scsi_scmd = SCMD_SET_ATN;
254*54004Sfujita 	}
255*54004Sfujita #endif
256*54004Sfujita 
257*54004Sfujita 	hd->scsi_pctl = 0;
258*54004Sfujita 	hd->scsi_temp = (1 << SCSI_ID) | (1 << target);
259*54004Sfujita 
260*54004Sfujita 	/* select timeout is hardcoded to 2ms */
261*54004Sfujita 	hd->scsi_tch = 0;
262*54004Sfujita 	hd->scsi_tcm = 32;
263*54004Sfujita 	hd->scsi_tcl = 4;
264*54004Sfujita 
265*54004Sfujita 	hd->scsi_scmd = SCMD_SELECT;
266*54004Sfujita 
267*54004Sfujita 	return (1);
268*54004Sfujita }
269*54004Sfujita 
270*54004Sfujita 
271*54004Sfujita /*
272*54004Sfujita  * SPC Manual Transfer routines
273*54004Sfujita  */
274*54004Sfujita 
275*54004Sfujita /* not yet */
276*54004Sfujita 
277*54004Sfujita 
278*54004Sfujita /*
279*54004Sfujita  * SPC Program Transfer routines
280*54004Sfujita  */
281*54004Sfujita 
282*54004Sfujita int
283*54004Sfujita ixfer_start(hd, len, phase)
284*54004Sfujita 	volatile register struct scsidevice *hd;
285*54004Sfujita 	register int len;
286*54004Sfujita 	register u_char phase;
287*54004Sfujita {
288*54004Sfujita 	register int wait = 0;
289*54004Sfujita 
290*54004Sfujita 	hd->scsi_sdgc = 0;
291*54004Sfujita 
292*54004Sfujita 	hd->scsi_tch  = ((len & 0xff0000) >> 16);
293*54004Sfujita 	hd->scsi_tcm  = ((len & 0x00ff00) >>  8);
294*54004Sfujita 	hd->scsi_tcl  =  (len & 0x0000ff);
295*54004Sfujita 	hd->scsi_pctl = phase;
296*54004Sfujita 	hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
297*54004Sfujita 
298*54004Sfujita 	while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
299*54004Sfujita 		if (wait > SC_TIMEOUT) {
300*54004Sfujita 			panic("ixfer_start: too long wait");
301*54004Sfujita 		}
302*54004Sfujita 		wait++;
303*54004Sfujita 		DELAY(1);
304*54004Sfujita 	}
305*54004Sfujita }
306*54004Sfujita 
307*54004Sfujita int
308*54004Sfujita ixfer_out(hd, len, buf)
309*54004Sfujita 	volatile register struct scsidevice *hd;
310*54004Sfujita 	register int len;
311*54004Sfujita 	register u_char *buf;
312*54004Sfujita {
313*54004Sfujita 	u_char *t = buf;
314*54004Sfujita 	register int wait = 0;
315*54004Sfujita #ifdef QUADBYTES
316*54004Sfujita 	register int qwait = 0;
317*54004Sfujita 	register int l_len = len >> 3;
318*54004Sfujita 	register u_long * l_buf = (u_long *) buf;
319*54004Sfujita 
320*54004Sfujita 	for(; l_len > 0; l_len--) {
321*54004Sfujita 		while ((hd->scsi_ssts & SSTS_DREG_EMPTY) == 0) {
322*54004Sfujita 			if (qwait > SC_TIMEOUT) {
323*54004Sfujita 				printf("ixfer_out: quad time out\n");
324*54004Sfujita 				printf("ixfer_out: %d bytes sended\n",
325*54004Sfujita 				       (((u_char *) l_buf) - t));
326*54004Sfujita 				printf("ixfer_out: TC = %d\n",
327*54004Sfujita 				       ( hd->scsi_tch << 16 ) |
328*54004Sfujita 				       ( hd->scsi_tcm <<  8 ) |
329*54004Sfujita 				       ( hd->scsi_tcl ));
330*54004Sfujita 				return(-1);
331*54004Sfujita 			}
332*54004Sfujita 			qwait++;
333*54004Sfujita 			DELAY(1);
334*54004Sfujita 		}
335*54004Sfujita 		*((u_long *) &hd->scsi_dreg) = *l_buf++;
336*54004Sfujita 		*((u_long *) &hd->scsi_dreg) = *l_buf++;
337*54004Sfujita 	}
338*54004Sfujita 
339*54004Sfujita 	len &= 0x07;
340*54004Sfujita 	buf = (u_char *) l_buf;
341*54004Sfujita #endif
342*54004Sfujita 	for(; len > 0; len--) {
343*54004Sfujita 		while (hd->scsi_ssts & SSTS_DREG_FULL) {
344*54004Sfujita 			if (wait > SC_TIMEOUT) {
345*54004Sfujita 				printf("ixfer_out: time out\n");
346*54004Sfujita 				printf("ixfer_out: %d bytes sended\n",
347*54004Sfujita 				       (buf - t));
348*54004Sfujita 				return(-1);
349*54004Sfujita 			}
350*54004Sfujita 			wait++;
351*54004Sfujita 			DELAY(1);
352*54004Sfujita 		}
353*54004Sfujita 		hd->scsi_dreg = *buf++;
354*54004Sfujita 	}
355*54004Sfujita 
356*54004Sfujita #ifdef QUADBYTES
357*54004Sfujita 	return(qwait);
358*54004Sfujita #else
359*54004Sfujita 	return(wait);
360*54004Sfujita #endif
361*54004Sfujita }
362*54004Sfujita 
363*54004Sfujita int
364*54004Sfujita ixfer_in(hd, len, buf)
365*54004Sfujita 	volatile register struct scsidevice *hd;
366*54004Sfujita 	register int len;
367*54004Sfujita 	register u_char *buf;
368*54004Sfujita {
369*54004Sfujita 	u_char *t = buf;
370*54004Sfujita 	register int wait = 0;
371*54004Sfujita #ifdef QUADBYTES
372*54004Sfujita 	register int qwait = 0;
373*54004Sfujita 	register int l_len = len >> 3;
374*54004Sfujita 	register u_long * l_buf = (u_long *) buf;
375*54004Sfujita 
376*54004Sfujita 	for(; l_len > 0; l_len--) {
377*54004Sfujita 		while ((hd->scsi_ssts & SSTS_DREG_FULL) == 0) {
378*54004Sfujita 			if (qwait > SC_TIMEOUT) {
379*54004Sfujita 				printf("ixfer_in: quad time out\n");
380*54004Sfujita 				printf("ixfer_in: %d bytes recieved\n",
381*54004Sfujita 				       (((u_char *) l_buf) - t));
382*54004Sfujita 				return(-1);
383*54004Sfujita 			}
384*54004Sfujita 			qwait++;
385*54004Sfujita 			DELAY(1);
386*54004Sfujita 		}
387*54004Sfujita 		*l_buf++ = *((u_long *) &hd->scsi_dreg);
388*54004Sfujita 		*l_buf++ = *((u_long *) &hd->scsi_dreg);
389*54004Sfujita 	}
390*54004Sfujita 
391*54004Sfujita 	len &= 0x07;
392*54004Sfujita 	buf = (u_char *) l_buf;
393*54004Sfujita #endif
394*54004Sfujita 	for (; len > 0; len--) {
395*54004Sfujita 		while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
396*54004Sfujita 			if (wait > SC_TIMEOUT) {
397*54004Sfujita 				printf("ixfer_in: time out\n");
398*54004Sfujita 				printf("ixfer_in: %d bytes recieved\n",
399*54004Sfujita 				       (buf - t));
400*54004Sfujita 				return(-1);
401*54004Sfujita 			}
402*54004Sfujita 			wait++;
403*54004Sfujita 			DELAY(1);
404*54004Sfujita 		}
405*54004Sfujita 		*buf++ = hd->scsi_dreg;
406*54004Sfujita 	}
407*54004Sfujita 
408*54004Sfujita 
409*54004Sfujita #ifdef QUADBYTES
410*54004Sfujita 	return(qwait);
411*54004Sfujita #else
412*54004Sfujita 	return(wait);
413*54004Sfujita #endif
414*54004Sfujita }
415*54004Sfujita 
416*54004Sfujita 
417*54004Sfujita #ifdef XFER_ENABLE
418*54004Sfujita /*
419*54004Sfujita  * SPC Interrupt base Transfer Routines
420*54004Sfujita  */
421*54004Sfujita 
422*54004Sfujita int
423*54004Sfujita txfer_start(hd, len, phase)
424*54004Sfujita 	volatile register struct scsidevice *hd;
425*54004Sfujita 	register int len;
426*54004Sfujita 	register u_char phase;
427*54004Sfujita {
428*54004Sfujita 	register int wait = 0;
429*54004Sfujita 
430*54004Sfujita 	hd->scsi_sdgc = SDGC_XFER_ENAB;		/* for interrupt */
431*54004Sfujita 
432*54004Sfujita 	hd->scsi_tch  = ((len & 0xff0000) >> 16);
433*54004Sfujita 	hd->scsi_tcm  = ((len & 0x00ff00) >>  8);
434*54004Sfujita 	hd->scsi_tcl  =  (len & 0x0000ff);
435*54004Sfujita 	hd->scsi_pctl = phase;
436*54004Sfujita 	hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
437*54004Sfujita 
438*54004Sfujita 	while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
439*54004Sfujita 		if (wait > SC_TIMEOUT) {
440*54004Sfujita 			panic("ixfer_start: too long wait");
441*54004Sfujita 		}
442*54004Sfujita 		wait++;
443*54004Sfujita 		DELAY(1);
444*54004Sfujita 	}
445*54004Sfujita }
446*54004Sfujita 
447*54004Sfujita int
448*54004Sfujita txfer_in(ctlr)
449*54004Sfujita 	register int ctlr;
450*54004Sfujita {
451*54004Sfujita 	register struct scsi_softc *hs = &scsi_softc[ctlr];
452*54004Sfujita 	volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr;
453*54004Sfujita 	register struct scsi_queue *dq = hs->sc_sq.dq_forw;
454*54004Sfujita #ifdef QUADBYTES
455*54004Sfujita 	register u_long *lp;
456*54004Sfujita 
457*54004Sfujita 	if (hd->scsi_ssts & SSTS_DREG_FULL) {
458*54004Sfujita 		lp = (u_long *) dq->dq_xferp;
459*54004Sfujita 
460*54004Sfujita 		*lp++ = *((u_long *) &hd->scsi_dreg);
461*54004Sfujita 		*lp++ = *((u_long *) &hd->scsi_dreg);
462*54004Sfujita 
463*54004Sfujita 		dq->dq_xferp = (u_char *) lp;
464*54004Sfujita 		dq->dq_xfercnt -= 8;
465*54004Sfujita 
466*54004Sfujita 		goto xfer_done;
467*54004Sfujita 	}
468*54004Sfujita #endif
469*54004Sfujita 
470*54004Sfujita 	*dq->dq_xferp++ = hd->scsi_dreg;
471*54004Sfujita 	dq->dq_xfercnt--;
472*54004Sfujita 
473*54004Sfujita  xfer_done:
474*54004Sfujita #ifdef DEBUGPRINT
475*54004Sfujita 	if (dq->dq_xfercnt == 0) {
476*54004Sfujita 		dbgprintf("txfer_in: ");
477*54004Sfujita 		dbgprintf("dq->dq_bp->b_un.b_addr = 0x%s, ", hexstr(dq->dq_bp->b_un.b_addr, 8));
478*54004Sfujita 		dbgprintf("dq->dq_xferp = 0x%s :", hexstr(dq->dq_xferp, 8));
479*54004Sfujita 		dbgprintf("done\n");
480*54004Sfujita 	}
481*54004Sfujita #endif
482*54004Sfujita }
483*54004Sfujita #endif
484*54004Sfujita 
485*54004Sfujita /*
486*54004Sfujita  * SCSI Job Handler
487*54004Sfujita  */
488*54004Sfujita 
489*54004Sfujita int
490*54004Sfujita scstart(ctlr)
491*54004Sfujita 	int ctlr;
492*54004Sfujita {
493*54004Sfujita 	register struct scsi_softc *hs = &scsi_softc[ctlr];
494*54004Sfujita 	volatile register struct scsidevice *hd =
495*54004Sfujita 		(struct scsidevice *) hs->sc_hc->hp_addr;
496*54004Sfujita 	register struct scsi_queue *dq = hs->sc_sq.dq_forw;
497*54004Sfujita 
498*54004Sfujita 	dq->dq_imax =  0;
499*54004Sfujita 	dq->dq_imin = -1;
500*54004Sfujita 	dq->dq_omax =  0;
501*54004Sfujita 	dq->dq_omin = -1;
502*54004Sfujita 
503*54004Sfujita 	hs->sc_flags  = 0;
504*54004Sfujita 	hs->sc_phase  = ARB_SEL_PHASE;
505*54004Sfujita 
506*54004Sfujita 	hs->sc_stat   = 0;
507*54004Sfujita 	hs->sc_msg[0] = 0;
508*54004Sfujita 
509*54004Sfujita #ifdef DEBUGPRINT
510*54004Sfujita 	dbgprintf("\n");
511*54004Sfujita 	dbgprintf("scstart: ID = %d\n", dq->dq_slave);
512*54004Sfujita 	dbgprintf("scstart: cdb[0] = %s\n", scsi_command(dq->dq_cdb->cdb[0]));
513*54004Sfujita 	dbgprintf("scstart: cdb[1] = 0x%s\n", hexstr(dq->dq_cdb->cdb[1], 2));
514*54004Sfujita 	dbgprintf("scstart: cdb[2] = 0x%s\n", hexstr(dq->dq_cdb->cdb[2], 2));
515*54004Sfujita 	dbgprintf("scstart: cdb[3] = 0x%s\n", hexstr(dq->dq_cdb->cdb[3], 2));
516*54004Sfujita 	dbgprintf("scstart: cdb[4] = 0x%s\n", hexstr(dq->dq_cdb->cdb[4], 2));
517*54004Sfujita 	dbgprintf("scstart: cdb[5] = 0x%s\n", hexstr(dq->dq_cdb->cdb[5], 2));
518*54004Sfujita 	if (dq->dq_cdb->cdb[0] & 0xE0) {
519*54004Sfujita 		dbgprintf("scstart: cdb[6] = 0x%s\n", hexstr(dq->dq_cdb->cdb[6], 2));
520*54004Sfujita 		dbgprintf("scstart: cdb[7] = 0x%s\n", hexstr(dq->dq_cdb->cdb[7], 2));
521*54004Sfujita 		dbgprintf("scstart: cdb[8] = 0x%s\n", hexstr(dq->dq_cdb->cdb[8], 2));
522*54004Sfujita 		dbgprintf("scstart: cdb[9] = 0x%s\n", hexstr(dq->dq_cdb->cdb[9], 2));
523*54004Sfujita 	}
524*54004Sfujita 	dbgprintf("scstart: bp->b_bcount = %d\n", dq->dq_bp->b_bcount);
525*54004Sfujita 	dbgprintf("scstart: %s\n", phase_name(hs->sc_phase));
526*54004Sfujita #endif
527*54004Sfujita 
528*54004Sfujita 	issue_select(hd, dq->dq_slave, dq->dq_flags);
529*54004Sfujita 
530*54004Sfujita 	return(1);
531*54004Sfujita }
532*54004Sfujita 
533*54004Sfujita int
534*54004Sfujita _scintr()
535*54004Sfujita {
536*54004Sfujita 	register struct scsi_softc *hs;
537*54004Sfujita 	volatile register struct scsidevice *hd;
538*54004Sfujita 	register int ctlr;
539*54004Sfujita 
540*54004Sfujita 	for (ctlr = 0; ctlr < NSC; ctlr++) {
541*54004Sfujita 		hs = &scsi_softc[ctlr];
542*54004Sfujita 		hd = (struct scsidevice *) hs->sc_hc->hp_addr;
543*54004Sfujita 
544*54004Sfujita #ifdef XFER_ENABLE
545*54004Sfujita 		if (((hd->scsi_psns & PHASE) == DATA_IN_PHASE) &&
546*54004Sfujita 		    (hd->scsi_serr & SERR_XFER_OUT))
547*54004Sfujita 			txfer_in(ctlr);
548*54004Sfujita #endif
549*54004Sfujita 
550*54004Sfujita 		if (hd->scsi_ints != 0)
551*54004Sfujita 			scintr(ctlr);
552*54004Sfujita 	}
553*54004Sfujita 
554*54004Sfujita 	return;
555*54004Sfujita }
556*54004Sfujita 
557*54004Sfujita int
558*54004Sfujita scintr(ctlr)
559*54004Sfujita 	register int ctlr;
560*54004Sfujita {
561*54004Sfujita 	register struct scsi_softc *hs = &scsi_softc[ctlr];
562*54004Sfujita 	volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr;
563*54004Sfujita 	register struct scsi_queue *dq = hs->sc_sq.dq_forw;
564*54004Sfujita 	register u_char ints, temp;
565*54004Sfujita 	register int i, slave;
566*54004Sfujita 	int wait, len;
567*54004Sfujita 	u_char *buf;
568*54004Sfujita 
569*54004Sfujita 	ints = hd->scsi_ints;
570*54004Sfujita 
571*54004Sfujita #ifdef DEBUGPRINT
572*54004Sfujita 	dbgprintf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x",
573*54004Sfujita 	       ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
574*54004Sfujita 	if (hs->sc_phase == CMD_PHASE)
575*54004Sfujita 		dbgprintf("   [%s]", scsi_command(dq->dq_cdb->cdb[0]));
576*54004Sfujita 	if (hs->sc_phase & PHASE_MSG)
577*54004Sfujita 		dbgprintf("   [%s]", scsi_mesg(hs->sc_msg[0]));
578*54004Sfujita 	dbgprintf("\n");
579*54004Sfujita #endif
580*54004Sfujita 
581*54004Sfujita 	if (ints & INTS_DISCON) {
582*54004Sfujita 		if (hs->sc_msg[0] == MSG_CMD_COMPLETE) {
583*54004Sfujita 			hd->scsi_ints = ints;
584*54004Sfujita 
585*54004Sfujita 			if (hs->sc_lock != NULL) {
586*54004Sfujita 				*(hs->sc_lock) = SC_IO_COMPLETE;
587*54004Sfujita 			} else {
588*54004Sfujita 				(dq->dq_driver->d_intr)(dq->dq_unit, hs->sc_stat);
589*54004Sfujita 			}
590*54004Sfujita 
591*54004Sfujita 			return;
592*54004Sfujita #ifndef NODISCONNECT
593*54004Sfujita 		} else if (hs->sc_msg[0] == MSG_DISCONNECT) {
594*54004Sfujita #ifdef DEBUGPRINT
595*54004Sfujita 			dbgprintf("scintr: DISCONNECT : ctlr = %d, slave = %d, cdb = %s\n",
596*54004Sfujita 			       dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0]));
597*54004Sfujita #endif
598*54004Sfujita 
599*54004Sfujita 			hd->scsi_ints = ints;
600*54004Sfujita 
601*54004Sfujita 			scpend(dq);
602*54004Sfujita 
603*54004Sfujita 			dq = hs->sc_sq.dq_forw;
604*54004Sfujita 
605*54004Sfujita 			if (dq != &hs->sc_sq)
606*54004Sfujita 				(dq->dq_driver->d_start)(dq->dq_unit);
607*54004Sfujita 
608*54004Sfujita 			return;
609*54004Sfujita #endif
610*54004Sfujita 		} else
611*54004Sfujita 			goto abort;
612*54004Sfujita 
613*54004Sfujita #ifndef NODISCONNECT
614*54004Sfujita 	} else if (ints & INTS_RESEL) {
615*54004Sfujita 		temp = hd->scsi_temp & ~(1 << SCSI_ID);
616*54004Sfujita 		for (slave = 0; temp != 1; slave++) {
617*54004Sfujita 			temp >>= 1;
618*54004Sfujita 		}
619*54004Sfujita 
620*54004Sfujita 		hd->scsi_ints = ints;
621*54004Sfujita 
622*54004Sfujita 		scrschdl(ctlr, slave);
623*54004Sfujita 
624*54004Sfujita 		dq = hs->sc_sq.dq_forw;
625*54004Sfujita #ifdef DEBUGPRINT
626*54004Sfujita 		dbgprintf("\n");
627*54004Sfujita 		dbgprintf("scintr: RESELECT : ctlr = %d, slave = %d, cdb = %s\n",
628*54004Sfujita 		       dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0]));
629*54004Sfujita #endif
630*54004Sfujita #endif
631*54004Sfujita 	} else if (ints & INTS_CMD_DONE) {
632*54004Sfujita 		if (hs->sc_phase == BUS_FREE_PHASE)
633*54004Sfujita 			goto abort;
634*54004Sfujita 		else if (hs->sc_phase  == MESG_IN_PHASE) {
635*54004Sfujita 			hd->scsi_scmd = SCMD_RST_ACK;
636*54004Sfujita 
637*54004Sfujita 			 if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) ||
638*54004Sfujita 			     (hs->sc_msg[0] == MSG_DISCONNECT)) {
639*54004Sfujita 				 hd->scsi_ints = ints;
640*54004Sfujita 
641*54004Sfujita 				 hs->sc_phase  = BUS_FREE_PHASE;
642*54004Sfujita 
643*54004Sfujita 				 return;
644*54004Sfujita 			 }
645*54004Sfujita 		}
646*54004Sfujita 		if (hs->sc_flags & SC_SEL_TIMEOUT)
647*54004Sfujita 			hs->sc_flags &= ~SC_SEL_TIMEOUT;
648*54004Sfujita 	} else if (ints & INTS_SRV_REQ) {
649*54004Sfujita 		if (hs->sc_phase != MESG_IN_PHASE)
650*54004Sfujita 			goto abort;
651*54004Sfujita 	} else if (ints & INTS_TIMEOUT) {
652*54004Sfujita 		if (hs->sc_phase == ARB_SEL_PHASE) {
653*54004Sfujita 			if (hs->sc_flags & SC_SEL_TIMEOUT) {
654*54004Sfujita 				hd->scsi_ints = ints;
655*54004Sfujita 				hs->sc_flags &= ~SC_SEL_TIMEOUT;
656*54004Sfujita 				/* Such SCSI Device is not conected. */
657*54004Sfujita 
658*54004Sfujita 				if (hs->sc_lock != NULL) {
659*54004Sfujita 					*(hs->sc_lock) = SC_DEV_NOT_FOUND;
660*54004Sfujita 				} else {
661*54004Sfujita 					(dq->dq_driver->d_intr)(dq->dq_unit, SC_DEV_NOT_FOUND);
662*54004Sfujita 				}
663*54004Sfujita 
664*54004Sfujita 				return;
665*54004Sfujita 			} else {
666*54004Sfujita 				/* wait more 250 usec */
667*54004Sfujita 				hs->sc_flags |= SC_SEL_TIMEOUT;
668*54004Sfujita 				hd->scsi_temp = 0;
669*54004Sfujita 				hd->scsi_tch  = 0;
670*54004Sfujita 				hd->scsi_tcm  = 0x06;
671*54004Sfujita 				hd->scsi_tcl  = 0x40;
672*54004Sfujita 				hd->scsi_ints = ints;
673*54004Sfujita 				return;
674*54004Sfujita 			}
675*54004Sfujita 		} else
676*54004Sfujita 			goto abort;
677*54004Sfujita 	} else
678*54004Sfujita 		goto abort;
679*54004Sfujita 
680*54004Sfujita 	hd->scsi_ints = ints;
681*54004Sfujita 
682*54004Sfujita 	/*
683*54004Sfujita 	 * Next SCSI Transfer
684*54004Sfujita 	 */
685*54004Sfujita 
686*54004Sfujita 	wait = SC_TIMEOUT;
687*54004Sfujita 	while ((hd->scsi_psns & PSNS_REQ) == 0) {
688*54004Sfujita 		if (wait < 0) {
689*54004Sfujita /*			hd->scsi_scmd = SCMD_SET_ATN;	*/
690*54004Sfujita 			hd->scsi_scmd = SCMD_RST;
691*54004Sfujita 			DELAY(40);			/* wait 25 micro sec */
692*54004Sfujita 			hd->scsi_scmd = 0;
693*54004Sfujita 
694*54004Sfujita 			wait = SC_TIMEOUT;
695*54004Sfujita 			while (wait-- > 0)
696*54004Sfujita 				DELAY(1);
697*54004Sfujita 
698*54004Sfujita 			if (hs->sc_lock != NULL) {
699*54004Sfujita 				*(hs->sc_lock) = SC_IO_TIMEOUT;
700*54004Sfujita 			} else {
701*54004Sfujita 				(dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT);
702*54004Sfujita 			}
703*54004Sfujita 
704*54004Sfujita 			return;
705*54004Sfujita 		}
706*54004Sfujita 		DELAY(1);
707*54004Sfujita 		wait--;
708*54004Sfujita 	}
709*54004Sfujita 
710*54004Sfujita 	hs->sc_phase = hd->scsi_psns & PHASE;
711*54004Sfujita 
712*54004Sfujita #ifdef DEBUGPRINT
713*54004Sfujita 	dbgprintf("scintr: %s\n", phase_name(hs->sc_phase));
714*54004Sfujita #endif
715*54004Sfujita 
716*54004Sfujita 	if ((hs->sc_phase == DATA_OUT_PHASE) || (hs->sc_phase == DATA_IN_PHASE)) {
717*54004Sfujita 		len = ( hs->sc_lock != NULL ? hs->sc_len : dq->dq_bp->b_bcount );
718*54004Sfujita 		buf = ( hs->sc_lock != NULL ? hs->sc_buf : (u_char *) dq->dq_bp->b_un.b_addr );
719*54004Sfujita 	} else if (hs->sc_phase == CMD_PHASE) {
720*54004Sfujita 		len = ( hs->sc_lock != NULL ? hs->sc_cdblen : dq->dq_cdb->len );
721*54004Sfujita 		buf = ( hs->sc_lock != NULL ? hs->sc_cdb    : dq->dq_cdb->cdb );
722*54004Sfujita 	} else if (hs->sc_phase == STATUS_PHASE) {
723*54004Sfujita 		len = 1;
724*54004Sfujita 		buf = &hs->sc_stat;
725*54004Sfujita 	} else {
726*54004Sfujita 		if (hs->sc_phase == MESG_OUT_PHASE) {
727*54004Sfujita #ifndef NODISCONNECT
728*54004Sfujita 			hs->sc_msg[0] = MSG_IDENTIFY_DR;
729*54004Sfujita #else
730*54004Sfujita 			hs->sc_msg[0] = MSG_IDENTIFY;
731*54004Sfujita #endif
732*54004Sfujita 		}
733*54004Sfujita 		len = 1;
734*54004Sfujita 		buf = hs->sc_msg;
735*54004Sfujita 	}
736*54004Sfujita 
737*54004Sfujita #ifdef XFER_ENABLE
738*54004Sfujita 	if ((hs->sc_lock == NULL) && (hs->sc_phase == DATA_IN_PHASE)) {
739*54004Sfujita 		dq->dq_xferp   = buf;
740*54004Sfujita 		dq->dq_xfercnt = len;
741*54004Sfujita 		txfer_start(hd, len, hs->sc_phase);
742*54004Sfujita 		return;
743*54004Sfujita 	}
744*54004Sfujita #endif
745*54004Sfujita 
746*54004Sfujita 	ixfer_start(hd, len, hs->sc_phase);
747*54004Sfujita 	if (hs->sc_phase & PHASE_IO) {
748*54004Sfujita 		if ((wait = ixfer_in(hd, len, buf)) == -1) {
749*54004Sfujita 			goto time_out;
750*54004Sfujita 		}
751*54004Sfujita 		if (dq->dq_imin == -1)
752*54004Sfujita 			dq->dq_imin = wait;
753*54004Sfujita 		else
754*54004Sfujita 			dq->dq_imin = MIN(wait, dq->dq_imin);
755*54004Sfujita 		dq->dq_imax = MAX(wait, dq->dq_imax);
756*54004Sfujita 	} else {
757*54004Sfujita 		if ((wait = ixfer_out(hd, len, buf)) == -1) {
758*54004Sfujita 			goto time_out;
759*54004Sfujita 		}
760*54004Sfujita 		if (dq->dq_omin == -1)
761*54004Sfujita 			dq->dq_omin = wait;
762*54004Sfujita 		else
763*54004Sfujita 			dq->dq_omin = MIN(wait, dq->dq_omin);
764*54004Sfujita 		dq->dq_omax = MAX(wait, dq->dq_omax);
765*54004Sfujita 	}
766*54004Sfujita 
767*54004Sfujita 	return;
768*54004Sfujita 
769*54004Sfujita  time_out:
770*54004Sfujita 	scabort(hs, hd);
771*54004Sfujita 	printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Current Status\n",
772*54004Sfujita 	       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
773*54004Sfujita 
774*54004Sfujita 	if (hs->sc_lock != NULL) {
775*54004Sfujita 		*(hs->sc_lock) = SC_IO_TIMEOUT;
776*54004Sfujita 	} else {
777*54004Sfujita 		(dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT);
778*54004Sfujita 	}
779*54004Sfujita 
780*54004Sfujita 	return;
781*54004Sfujita 
782*54004Sfujita 	/*
783*54004Sfujita 	 * SCSI Abort
784*54004Sfujita 	 */
785*54004Sfujita  abort:
786*54004Sfujita 
787*54004Sfujita 	/* SCSI IO failed */
788*54004Sfujita 	scabort(hs, hd);
789*54004Sfujita 	hd->scsi_ints = ints;
790*54004Sfujita 
791*54004Sfujita 	if (hs->sc_lock != NULL) {
792*54004Sfujita 		*(hs->sc_lock) = SC_IO_FAILED;
793*54004Sfujita 	} else {
794*54004Sfujita 		(dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_FAILED);
795*54004Sfujita 	}
796*54004Sfujita 
797*54004Sfujita 	return;
798*54004Sfujita }
799*54004Sfujita 
800*54004Sfujita int
801*54004Sfujita scabort(hs, hd)
802*54004Sfujita 	register struct scsi_softc *hs;
803*54004Sfujita 	volatile register struct scsidevice *hd;
804*54004Sfujita {
805*54004Sfujita 	int len;
806*54004Sfujita 	u_char junk;
807*54004Sfujita 
808*54004Sfujita #ifdef DEBUGPRINT
809*54004Sfujita 	dbgprintall();
810*54004Sfujita 	printf("\n");
811*54004Sfujita #endif
812*54004Sfujita 
813*54004Sfujita 	printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Current Status\n",
814*54004Sfujita 	       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
815*54004Sfujita 
816*54004Sfujita 	if (hd->scsi_ints != 0)
817*54004Sfujita 		hd->scsi_ints = hd->scsi_ints;
818*54004Sfujita 	printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Reset INTS reg.\n",
819*54004Sfujita 	       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
820*54004Sfujita 
821*54004Sfujita 	if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
822*54004Sfujita 		/* no longer connected to scsi target */
823*54004Sfujita 		return;
824*54004Sfujita 
825*54004Sfujita 	/* get the number of bytes remaining in current xfer + fudge */
826*54004Sfujita 	len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
827*54004Sfujita 	printf("scabort: Current xfer count = %d\n", len);
828*54004Sfujita 
829*54004Sfujita 	/* for that many bus cycles, try to send an abort msg */
830*54004Sfujita 	for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) {
831*54004Sfujita /*
832*54004Sfujita 		hd->scsi_scmd = SCMD_SET_ATN;
833*54004Sfujita 		printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Set ATN\n",
834*54004Sfujita 		       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
835*54004Sfujita  */
836*54004Sfujita 		while ((hd->scsi_psns & PSNS_REQ) == 0) {
837*54004Sfujita 			printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Wait for REQ\n",
838*54004Sfujita 			       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
839*54004Sfujita 			if (! (hd->scsi_ssts & SSTS_INITIATOR))
840*54004Sfujita 				goto out;
841*54004Sfujita 			DELAY(1);
842*54004Sfujita 		}
843*54004Sfujita /*
844*54004Sfujita 		if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE) {
845*54004Sfujita 			hd->scsi_scmd = SCMD_RST_ATN;
846*54004Sfujita 			printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Reset ATN\n",
847*54004Sfujita 			       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
848*54004Sfujita 		}
849*54004Sfujita  */
850*54004Sfujita 		hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE;
851*54004Sfujita 		printf("scabort: Phase = %s\n", phase_name(hs->sc_phase));
852*54004Sfujita 
853*54004Sfujita 		if (hd->scsi_psns & PHASE_IO) {
854*54004Sfujita 			/* one of the input phases - read & discard a byte */
855*54004Sfujita 			hd->scsi_scmd = SCMD_SET_ACK;
856*54004Sfujita 			printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Set ACK\n",
857*54004Sfujita 			       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
858*54004Sfujita 
859*54004Sfujita 			while (hd->scsi_psns & PSNS_REQ) {
860*54004Sfujita 				printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Wait for REQ\n",
861*54004Sfujita 				       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
862*54004Sfujita 				DELAY(1);
863*54004Sfujita 			}
864*54004Sfujita 
865*54004Sfujita 			junk = hd->scsi_temp;
866*54004Sfujita 			printf("scabort: TEMP = 0x%s\n", hexstr(junk, 2));
867*54004Sfujita 		} else {
868*54004Sfujita 			/* one of the output phases - send an abort msg */
869*54004Sfujita 			hd->scsi_temp = MSG_ABORT;
870*54004Sfujita 			hd->scsi_scmd = SCMD_SET_ACK;
871*54004Sfujita 			printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Set ACK\n",
872*54004Sfujita 			       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
873*54004Sfujita 
874*54004Sfujita 			while (hd->scsi_psns & PSNS_REQ) {
875*54004Sfujita 				printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Wait for REQ\n",
876*54004Sfujita 				       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
877*54004Sfujita 				DELAY(1);
878*54004Sfujita 			}
879*54004Sfujita 		}
880*54004Sfujita 
881*54004Sfujita 		hd->scsi_scmd = SCMD_RST_ACK;
882*54004Sfujita 		printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Reset ACK\n",
883*54004Sfujita 		       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
884*54004Sfujita 	}
885*54004Sfujita out:
886*54004Sfujita 	/*
887*54004Sfujita 	 * Either the abort was successful & the bus is disconnected or
888*54004Sfujita 	 * the device didn't listen.  If the latter, announce the problem.
889*54004Sfujita 	 * Either way, reset the card & the SPC.
890*54004Sfujita 	 */
891*54004Sfujita 	if (len < 0 && hs)
892*54004Sfujita 		printf("sc%d: abort failed.  phase=0x%x, ssts=0x%x\n",
893*54004Sfujita 			hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts);
894*54004Sfujita 
895*54004Sfujita 	while (hd->scsi_ints == 0)
896*54004Sfujita 		DELAY(1);
897*54004Sfujita 
898*54004Sfujita 	hd->scsi_ints = hd->scsi_ints;
899*54004Sfujita 
900*54004Sfujita 	printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Current Status\n",
901*54004Sfujita 	       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
902*54004Sfujita 
903*54004Sfujita 	printf("scabort: SCSI abort operation is done\n");
904*54004Sfujita }
905*54004Sfujita 
906*54004Sfujita 
907*54004Sfujita /*
908*54004Sfujita  * SPC device queue handling
909*54004Sfujita  */
910*54004Sfujita 
911*54004Sfujita int
912*54004Sfujita screq(dq)
913*54004Sfujita 	register struct scsi_queue *dq;
914*54004Sfujita {
915*54004Sfujita 	register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr];
916*54004Sfujita 	register struct scsi_queue *hq = &hs->sc_sq;
917*54004Sfujita 
918*54004Sfujita 	insque(dq, hq->dq_back);
919*54004Sfujita 
920*54004Sfujita 	if (dq->dq_back == hq) {
921*54004Sfujita #ifdef QUE_DEBUG
922*54004Sfujita 		printf("screq: slave = %d, command = %s\n",
923*54004Sfujita 		       hq->dq_forw->dq_slave,
924*54004Sfujita 		       scsi_command(hq->dq_forw->dq_cdb->cdb[0]));
925*54004Sfujita #endif
926*54004Sfujita 		return(1);
927*54004Sfujita 	}
928*54004Sfujita 
929*54004Sfujita 	return(0);
930*54004Sfujita }
931*54004Sfujita 
932*54004Sfujita #ifndef NODISCONNECT
933*54004Sfujita int
934*54004Sfujita scpend(dq)
935*54004Sfujita 	register struct scsi_queue *dq;
936*54004Sfujita {
937*54004Sfujita 	register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr];
938*54004Sfujita 	register struct scsi_queue *hq = &hs->sc_sq;
939*54004Sfujita 	register struct scsi_queue *wq = &hs->sc_wq;
940*54004Sfujita 
941*54004Sfujita 	remque(dq);
942*54004Sfujita 
943*54004Sfujita 	insque(dq, wq->dq_back);
944*54004Sfujita }
945*54004Sfujita 
946*54004Sfujita int
947*54004Sfujita scrschdl(ctlr, slave)
948*54004Sfujita 	register int ctlr;
949*54004Sfujita 	register int slave;
950*54004Sfujita {
951*54004Sfujita 	register struct scsi_softc *hs = &scsi_softc[ctlr];
952*54004Sfujita 	register struct scsi_queue *wq = &hs->sc_wq;
953*54004Sfujita 	register struct scsi_queue *hq = &hs->sc_sq;
954*54004Sfujita 	register struct scsi_queue *dq;
955*54004Sfujita 
956*54004Sfujita 	for (dq = wq->dq_forw; dq != wq; dq = dq->dq_forw) {
957*54004Sfujita 		if (dq->dq_slave == slave)
958*54004Sfujita 			goto found;
959*54004Sfujita 	}
960*54004Sfujita 
961*54004Sfujita 	return(0);
962*54004Sfujita 
963*54004Sfujita  found:
964*54004Sfujita 	remque(dq);
965*54004Sfujita 	insque(dq, hq);
966*54004Sfujita 
967*54004Sfujita 	return(1);
968*54004Sfujita }
969*54004Sfujita #endif
970*54004Sfujita 
971*54004Sfujita int
972*54004Sfujita scfree(dq)
973*54004Sfujita 	register struct scsi_queue *dq;
974*54004Sfujita {
975*54004Sfujita 	register struct scsi_softc *hs = &scsi_softc[dq->dq_ctlr];
976*54004Sfujita 	register struct scsi_queue *hq = &hs->sc_sq;
977*54004Sfujita 	int status = hs->sc_stat;
978*54004Sfujita 
979*54004Sfujita 	remque(dq);
980*54004Sfujita 
981*54004Sfujita 	hs->sc_flags  = 0;
982*54004Sfujita 	hs->sc_phase  = BUS_FREE_PHASE;
983*54004Sfujita 
984*54004Sfujita 	hs->sc_stat   = 0;
985*54004Sfujita 	hs->sc_msg[0] = 0;
986*54004Sfujita 
987*54004Sfujita 	if ((dq = hq->dq_forw) != hq) {
988*54004Sfujita #ifdef QUE_DEBUG
989*54004Sfujita 		printf("scfree: slave = %d, command = %s\n",
990*54004Sfujita 		       dq->dq_slave,
991*54004Sfujita 		       scsi_command(dq->dq_cdb->cdb[0]));
992*54004Sfujita #endif
993*54004Sfujita 		(dq->dq_driver->d_start)(dq->dq_unit);
994*54004Sfujita 	}
995*54004Sfujita 
996*54004Sfujita 	return(status);
997*54004Sfujita }
998*54004Sfujita 
999*54004Sfujita /*
1000*54004Sfujita  * SCSI common interface
1001*54004Sfujita  */
1002*54004Sfujita 
1003*54004Sfujita int scsi_lock[NSC];
1004*54004Sfujita 
1005*54004Sfujita int
1006*54004Sfujita scsi_result(unit, stat)
1007*54004Sfujita 	int unit, stat;
1008*54004Sfujita {
1009*54004Sfujita #ifdef SCSI_DEBUG
1010*54004Sfujita 	printf("scsi_result: stat = %s\n", scsi_status(stat));
1011*54004Sfujita #endif
1012*54004Sfujita 	if (stat < 0)
1013*54004Sfujita 		scsi_lock[unit] = stat;
1014*54004Sfujita 	else
1015*54004Sfujita 		scsi_lock[unit] = SC_IO_COMPLETE;
1016*54004Sfujita }
1017*54004Sfujita 
1018*54004Sfujita struct	driver scsi_driver = {
1019*54004Sfujita 	(int (*)()) 0, "scsi", (int (*)()) 0, (int (*)()) 0, scsi_result, (int (*)()) 0
1020*54004Sfujita };
1021*54004Sfujita 
1022*54004Sfujita #define SCSI_BUF 8
1023*54004Sfujita 
1024*54004Sfujita struct buf scsi_buf[SCSI_BUF];
1025*54004Sfujita 
1026*54004Sfujita int
1027*54004Sfujita scsi_init_buf()
1028*54004Sfujita {
1029*54004Sfujita 	register struct buf *rbp = &scsi_buf[0];
1030*54004Sfujita 	register int i;
1031*54004Sfujita 
1032*54004Sfujita 	rbp->av_forw = rbp->av_back = rbp;
1033*54004Sfujita 
1034*54004Sfujita 	for(i = 0; i < SCSI_BUF; i++)
1035*54004Sfujita 		scsi_free_buf(&scsi_buf[i]);
1036*54004Sfujita }
1037*54004Sfujita 
1038*54004Sfujita int
1039*54004Sfujita scsi_free_buf(bp)
1040*54004Sfujita 	register struct buf *bp;
1041*54004Sfujita {
1042*54004Sfujita 	register struct buf *rbp = &scsi_buf[0];
1043*54004Sfujita 
1044*54004Sfujita 	bp->av_forw = rbp;
1045*54004Sfujita 	bp->av_back = rbp->av_back;
1046*54004Sfujita 
1047*54004Sfujita 	rbp->av_back->av_forw = bp;
1048*54004Sfujita 	rbp->av_back = bp;
1049*54004Sfujita }
1050*54004Sfujita 
1051*54004Sfujita struct buf *
1052*54004Sfujita scsi_get_buf()
1053*54004Sfujita {
1054*54004Sfujita 	register struct buf *rbp = &scsi_buf[0];
1055*54004Sfujita 	register struct buf *bp = rbp->av_forw;
1056*54004Sfujita 
1057*54004Sfujita 	if (bp == rbp)
1058*54004Sfujita 		return((struct buf *) 0);
1059*54004Sfujita 
1060*54004Sfujita 	bp->av_forw->av_back = rbp;
1061*54004Sfujita 	rbp->av_forw = bp->av_forw;
1062*54004Sfujita 
1063*54004Sfujita 	return(bp);
1064*54004Sfujita }
1065*54004Sfujita 
1066*54004Sfujita struct scsi_queue scsi_entry[NSC];
1067*54004Sfujita 
1068*54004Sfujita int
1069*54004Sfujita scsi_immed_command(ctlr, slave, lun, cdb, buf, len)
1070*54004Sfujita 	int ctlr, slave, lun;
1071*54004Sfujita 	struct scsi_fmt_cdb *cdb;
1072*54004Sfujita 	u_char *buf;
1073*54004Sfujita 	unsigned len;
1074*54004Sfujita {
1075*54004Sfujita 	register struct scsi_softc *hs = &scsi_softc[ctlr];
1076*54004Sfujita 	volatile register struct scsidevice *hd =
1077*54004Sfujita 		(struct scsidevice *) hs->sc_hc->hp_addr;
1078*54004Sfujita 	register struct scsi_queue *dq = &scsi_entry[ctlr];
1079*54004Sfujita 	register struct buf *bp;
1080*54004Sfujita 	int s, status, wait = 30;
1081*54004Sfujita 
1082*54004Sfujita #ifdef SCSI_DEBUG
1083*54004Sfujita 	printf("scsi_immed_command( %d, %d, %d, cdb(%d,%s), buf, %d): Start\n",
1084*54004Sfujita 	       ctlr, slave, lun, cdb->len, scsi_command(cdb->cdb[0]), len);
1085*54004Sfujita #endif
1086*54004Sfujita 
1087*54004Sfujita 	if ((bp = scsi_get_buf()) == 0) {
1088*54004Sfujita 		return(SC_BUSY);
1089*54004Sfujita 	}
1090*54004Sfujita 
1091*54004Sfujita 	s = splbio();
1092*54004Sfujita 
1093*54004Sfujita 	bp->b_flags = B_BUSY;
1094*54004Sfujita 	bp->b_bcount = len;
1095*54004Sfujita 	bp->b_un.b_addr = (caddr_t) buf;
1096*54004Sfujita 
1097*54004Sfujita 	dq->dq_unit   = ctlr;
1098*54004Sfujita 	dq->dq_ctlr   = ctlr;
1099*54004Sfujita 	dq->dq_slave  = slave;
1100*54004Sfujita 	dq->dq_driver = &scsi_driver;
1101*54004Sfujita 	dq->dq_cdb    = cdb;
1102*54004Sfujita 	dq->dq_bp     = bp;
1103*54004Sfujita 
1104*54004Sfujita 	scsi_lock[ctlr] = SC_IN_PROGRESS;
1105*54004Sfujita 	if (screq(dq))
1106*54004Sfujita 		scstart(ctlr);
1107*54004Sfujita 
1108*54004Sfujita 	splx(s);
1109*54004Sfujita 
1110*54004Sfujita 	while (scsi_lock[ctlr] == SC_IN_PROGRESS) {
1111*54004Sfujita 		if (wait < 0) {
1112*54004Sfujita 			scabort(hs, hd);
1113*54004Sfujita 
1114*54004Sfujita 			s = splbio();
1115*54004Sfujita 			status = scfree(dq);
1116*54004Sfujita 			splx(s);
1117*54004Sfujita 
1118*54004Sfujita 			bp->b_flags = 0;
1119*54004Sfujita 
1120*54004Sfujita 			return(SC_IO_FAILED);
1121*54004Sfujita 		}
1122*54004Sfujita 
1123*54004Sfujita 		DELAY(100000);
1124*54004Sfujita 		wait--;
1125*54004Sfujita 	}
1126*54004Sfujita 
1127*54004Sfujita 	s = splbio();
1128*54004Sfujita 	status = scfree(dq);
1129*54004Sfujita 	splx(s);
1130*54004Sfujita 
1131*54004Sfujita 	if (scsi_lock[ctlr] < 0)
1132*54004Sfujita 		status = scsi_lock[ctlr];
1133*54004Sfujita 
1134*54004Sfujita 	scsi_free_buf(bp);
1135*54004Sfujita 
1136*54004Sfujita #ifdef SCSI_DEBUG
1137*54004Sfujita 		printf("scsi_immed_command: Status -- 0x%x\n", status);
1138*54004Sfujita #endif
1139*54004Sfujita 	return(status);
1140*54004Sfujita }
1141*54004Sfujita 
1142*54004Sfujita int
1143*54004Sfujita scsi_test_unit_rdy(ctlr, slave, lun)
1144*54004Sfujita 	int ctlr, slave, lun;
1145*54004Sfujita {
1146*54004Sfujita 	static struct scsi_fmt_cdb cdb = { 6, CMD_TEST_UNIT_READY };
1147*54004Sfujita 	int stat;
1148*54004Sfujita 
1149*54004Sfujita 	while ((stat = scsi_immed_command(ctlr, slave, lun,
1150*54004Sfujita 					  &cdb, (u_char *) 0, 0)) == SC_BUSY) {
1151*54004Sfujita 		DELAY(10000);
1152*54004Sfujita 	}
1153*54004Sfujita 
1154*54004Sfujita 	return(stat);
1155*54004Sfujita }
1156*54004Sfujita 
1157*54004Sfujita int
1158*54004Sfujita scsi_request_sense(ctlr, slave, lun, buf, len)
1159*54004Sfujita 	int ctlr, slave, lun;
1160*54004Sfujita 	u_char *buf;
1161*54004Sfujita 	unsigned len;
1162*54004Sfujita {
1163*54004Sfujita 	register struct scsi_softc *hs = &scsi_softc[ctlr];
1164*54004Sfujita 	volatile register struct scsidevice *hd =
1165*54004Sfujita 		(struct scsidevice *) hs->sc_hc->hp_addr;
1166*54004Sfujita 	static struct scsi_fmt_cdb req_cmd = { 6, CMD_REQUEST_SENSE };
1167*54004Sfujita 	int s, status, lock;
1168*54004Sfujita 
1169*54004Sfujita #ifdef REQ_DEBUG
1170*54004Sfujita 	printf("scsi_request_sense( %d, %d, %d, buf, %d) -- Start\n",
1171*54004Sfujita 	       ctlr, slave, lun, len);
1172*54004Sfujita #endif
1173*54004Sfujita 
1174*54004Sfujita         req_cmd.cdb[1] = lun;
1175*54004Sfujita         req_cmd.cdb[4] = len;
1176*54004Sfujita 
1177*54004Sfujita 	if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
1178*54004Sfujita 		return(0);
1179*54004Sfujita 
1180*54004Sfujita 	s = splbio();
1181*54004Sfujita 
1182*54004Sfujita 	hs->sc_flags  = 0;
1183*54004Sfujita 	hs->sc_phase  = ARB_SEL_PHASE;
1184*54004Sfujita 
1185*54004Sfujita 	hs->sc_cdb    = req_cmd.cdb;
1186*54004Sfujita 	hs->sc_cdblen = req_cmd.len;
1187*54004Sfujita 	hs->sc_buf    = buf;
1188*54004Sfujita 	hs->sc_len    = len;
1189*54004Sfujita 
1190*54004Sfujita 	hs->sc_stat   = 0;
1191*54004Sfujita 	hs->sc_msg[0] = 0;
1192*54004Sfujita 
1193*54004Sfujita 	lock = SC_IN_PROGRESS;
1194*54004Sfujita 	hs->sc_lock   = &lock;
1195*54004Sfujita 
1196*54004Sfujita 	issue_select(hd, slave, 0);
1197*54004Sfujita 
1198*54004Sfujita 	spl0();
1199*54004Sfujita 
1200*54004Sfujita 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
1201*54004Sfujita 		DELAY(10);
1202*54004Sfujita 
1203*54004Sfujita 	splbio();
1204*54004Sfujita 
1205*54004Sfujita 	hs->sc_flags  = 0;
1206*54004Sfujita 	hs->sc_phase  = BUS_FREE_PHASE;
1207*54004Sfujita 
1208*54004Sfujita 	hs->sc_cdb    = NULL;
1209*54004Sfujita 	hs->sc_cdblen = 0;
1210*54004Sfujita 	hs->sc_buf    = NULL;
1211*54004Sfujita 	hs->sc_len    = 0;
1212*54004Sfujita 	hs->sc_lock   = NULL;
1213*54004Sfujita 
1214*54004Sfujita 	status = hs->sc_stat;
1215*54004Sfujita 
1216*54004Sfujita 	hs->sc_stat   = 0;
1217*54004Sfujita 	hs->sc_msg[0] = 0;
1218*54004Sfujita 
1219*54004Sfujita 	splx(s);
1220*54004Sfujita 
1221*54004Sfujita 	if (lock == SC_IO_COMPLETE) {
1222*54004Sfujita #ifdef REQ_DEBUG
1223*54004Sfujita 		printf("scsi_request_sense: Status -- 0x%x\n", status);
1224*54004Sfujita #endif
1225*54004Sfujita 		return(status);
1226*54004Sfujita 	} else {
1227*54004Sfujita 		return(lock);
1228*54004Sfujita 	}
1229*54004Sfujita }
1230*54004Sfujita #endif
1231