xref: /csrg-svn/sys/luna68k/dev/sc.c (revision 65034)
154004Sfujita /*
254004Sfujita  * Copyright (c) 1992 OMRON Corporation.
363192Sbostic  * Copyright (c) 1992, 1993
463192Sbostic  *	The Regents of the University of California.  All rights reserved.
554004Sfujita  *
654004Sfujita  * This code is derived from software contributed to Berkeley by
754004Sfujita  * OMRON Corporation.
854004Sfujita  *
954004Sfujita  * %sccs.include.redist.c%
1054004Sfujita  *
11*65034Sakito  *	@(#)sc.c	8.2 (Berkeley) 12/06/93
1254004Sfujita  */
1354004Sfujita 
1454004Sfujita /*
1554004Sfujita  * sc.c -- FUJITSU MB89352 SCSI Protocole Controller (SPC) Device Driver
1654004Sfujita  *
1754004Sfujita  * remaked by A.Fujita,		Mar-22-1992
1854004Sfujita  * remaked again by A.Fujita,	Apr-16-1992
1954004Sfujita  */
2054004Sfujita 
2154004Sfujita #define DEBUG_FUNC
2254004Sfujita 
2354004Sfujita #include "sc.h"
2454004Sfujita #if NSC > 0
2554004Sfujita 
2656519Sbostic #include <sys/param.h>
2756519Sbostic #include <sys/systm.h>
2856519Sbostic #include <sys/buf.h>
2954004Sfujita 
3056519Sbostic #include <luna68k/dev/device.h>
31*65034Sakito #include <luna68k/dev/screg.h>
32*65034Sakito #include <luna68k/dev/scvar.h>
3354004Sfujita 
3454004Sfujita /*
3554004Sfujita  * SC Driver Options
3654004Sfujita  */
3754004Sfujita 
3854004Sfujita #define	QUADBYTES	/* 4 bytes access to SPC DREG Reg. */
3954004Sfujita #define	NODISCONNECT	/* not used SCSI DISCONNECT Ops. */
4054004Sfujita #undef	XFER_ENABLE	/* using interrupt for DREG access */
4154004Sfujita 
4254004Sfujita 
4354004Sfujita #define SCSI_IPL	2
4454004Sfujita #define SCSI_ID		7
4554004Sfujita 
4654004Sfujita extern char *hexstr();
4754004Sfujita 
4854004Sfujita int	scinit(), scstart(), scintr();
4954004Sfujita void	screset();
5054004Sfujita struct	driver scdriver = {
5154004Sfujita 	scinit, "sc", scstart, (int (*)()) 0, scintr, (int (*)()) 0
5254004Sfujita };
5354004Sfujita 
54*65034Sakito struct	sc_softc sc_softc[NSC];
5554004Sfujita 
5654004Sfujita 
5754004Sfujita #define	SC_TIMEOUT	0x01400000	/* (20971520) */
5854004Sfujita 
5954004Sfujita 
6054004Sfujita /*
6154004Sfujita  * for DEBUG
6254004Sfujita  */
6354004Sfujita 
6454004Sfujita char *
scsi_status(stat)6554004Sfujita scsi_status(stat)
6654004Sfujita 	u_char stat;
6754004Sfujita {
6854004Sfujita 	if ((stat & 0x1e) == 0)
6954004Sfujita 		return("Good");
7054004Sfujita 	else if ((stat & 0x1e) == STS_CHECKCOND)
7154004Sfujita 		return("Check Condition");
7254004Sfujita 	else if ((stat & 0x1e) == STS_CONDMET)
7354004Sfujita 		return("Condition Met");
7454004Sfujita 	else if ((stat & 0x1e) == STS_BUSY)
7554004Sfujita 		return("Busy");
7654004Sfujita 	else if ((stat & 0x1e) == STS_INTERMED)
7754004Sfujita 		return("Intermediate status sent");
7854004Sfujita 	else if ((stat & 0x1e) == STS_EXT)
7954004Sfujita 		return("Extended status valid");
8054004Sfujita 	else
8154004Sfujita 		return("Unknown Status");
8254004Sfujita }
8354004Sfujita 
8454004Sfujita #ifdef DEBUG_FUNC
8554004Sfujita 
8654004Sfujita char *
scsi_command(cmd)8754004Sfujita scsi_command(cmd)
8854004Sfujita 	u_char cmd;
8954004Sfujita {
9054004Sfujita 	if (cmd == CMD_TEST_UNIT_READY)
9154004Sfujita 		return("TEST_UNIT_READY");
9254004Sfujita 	else if (cmd == CMD_REQUEST_SENSE)
9354004Sfujita 		return("REQUEST_SENSE");
9454004Sfujita 	else if (cmd == CMD_INQUIRY)
9554004Sfujita 		return("INQUIRY");
9654004Sfujita 	else if (cmd == CMD_READ)
9754004Sfujita 		return("READ");
9854004Sfujita 	else if (cmd == CMD_WRITE)
9954004Sfujita 		return("WRITE");
10054004Sfujita 	else if (cmd == CMD_READ_EXT)
10154004Sfujita 		return("READ EXT");
10254004Sfujita 	else if (cmd == CMD_WRITE_EXT)
10354004Sfujita 		return("WRITE_EXT");
10454004Sfujita 	else if (cmd == CMD_READ_CAPACITY)
10554004Sfujita 		return("READ_CAPACITY");
10654004Sfujita 	else
10754004Sfujita 		return(hexstr(cmd, 2));
10854004Sfujita }
10954004Sfujita 
11054004Sfujita char *
scsi_mesg(mesg)11154004Sfujita scsi_mesg(mesg)
11254004Sfujita 	u_char mesg;
11354004Sfujita {
11454004Sfujita 	if (mesg == MSG_CMD_COMPLETE)
11554004Sfujita 		return("Command Complete");
11654004Sfujita 	else if (mesg == MSG_EXT_MESSAGE)
11754004Sfujita 		return("Extended Message");
11854004Sfujita 	else if (mesg == MSG_SAVE_DATA_PTR)
11954004Sfujita 		return("Save Data Pointer");
12054004Sfujita 	else if (mesg == MSG_RESTORE_PTR)
12154004Sfujita 		return("Restore Pointer");
12254004Sfujita 	else if (mesg == MSG_DISCONNECT)
12354004Sfujita 		return("Disconnect");
12454004Sfujita 	else if (mesg == MSG_INIT_DETECT_ERROR)
12554004Sfujita 		return("Initiator Detected Error");
12654004Sfujita 	else if (mesg == MSG_ABORT)
12754004Sfujita 		return("Abort");
12854004Sfujita 	else if (mesg == MSG_REJECT)
12954004Sfujita 		return("Message Reject");
13054004Sfujita 	else if (mesg == MSG_NOOP)
13154004Sfujita 		return("No Operation");
13254004Sfujita 	else if (mesg == MSG_PARITY_ERROR)
13354004Sfujita 		return("Message Parity Error");
13454004Sfujita 	else if (mesg == MSG_BUS_DEVICE_RESET)
13554004Sfujita 		return("Bus Device Reset");
13654004Sfujita 	else if (mesg == MSG_IDENTIFY)
13754004Sfujita 		return("Identify");
13854004Sfujita 	else if (mesg == MSG_IDENTIFY_DR)
13954004Sfujita 		return("Identify (Disconnect)");
14054004Sfujita 	else
14154004Sfujita 		return("Unknown Message");
14254004Sfujita }
14354004Sfujita 
14454004Sfujita char *
phase_name(phase)14554004Sfujita phase_name(phase)
14654004Sfujita 	u_char phase;
14754004Sfujita {
14854004Sfujita 	if (phase == DATA_OUT_PHASE)
14954004Sfujita 		return("Data Out");
15054004Sfujita 	else if (phase == DATA_IN_PHASE)
15154004Sfujita 		return("Data In");
15254004Sfujita 	else if (phase == CMD_PHASE)
15354004Sfujita 		return("Command");
15454004Sfujita 	else if (phase == STATUS_PHASE)
15554004Sfujita 		return("Status");
15654004Sfujita 	else if (phase == BUS_FREE_PHASE)
15754004Sfujita 		return("Bus Free");
15854004Sfujita 	else if (phase == ARB_SEL_PHASE)
15954004Sfujita 		return("Arbitration/Select");
16054004Sfujita 	else if (phase == MESG_OUT_PHASE)
16154004Sfujita 		return("Message Out");
16254004Sfujita 	else if (phase == MESG_IN_PHASE)
16354004Sfujita 		return("Message In");
16454004Sfujita 	else
16554004Sfujita 		return("Unknown");
16654004Sfujita }
16754004Sfujita #endif
16854004Sfujita 
16954004Sfujita /*
17054004Sfujita  * Initialize SPC & Data Structure
17154004Sfujita  */
17254004Sfujita 
17354004Sfujita int
scinit(hc)17454004Sfujita scinit(hc)
17554004Sfujita 	register struct hp_ctlr *hc;
17654004Sfujita {
177*65034Sakito 	register struct sc_softc *hs = &sc_softc[hc->hp_unit];
17854004Sfujita 	register int i;
17954004Sfujita 
18054004Sfujita 	hc->hp_ipl    = SCSI_IPL;
18154004Sfujita 	hs->sc_hc     = hc;
18254004Sfujita 	hs->sc_sq.dq_forw = hs->sc_sq.dq_back = &hs->sc_sq;
18354004Sfujita 	hs->sc_wq.dq_forw = hs->sc_wq.dq_back = &hs->sc_wq;
18454004Sfujita 
18554004Sfujita 	hs->sc_flags  = 0;
18654004Sfujita 	hs->sc_phase  = BUS_FREE_PHASE;
18754004Sfujita 
18854004Sfujita 	hs->sc_stat   = 0;
18954004Sfujita 	hs->sc_msg[0] = 0;
19054004Sfujita 
19154004Sfujita 	screset(hc->hp_unit);
19254004Sfujita 
19354004Sfujita 	return(1);
19454004Sfujita }
19554004Sfujita 
19654004Sfujita void
screset(unit)19754004Sfujita screset(unit)
19854004Sfujita 	register int unit;
19954004Sfujita {
200*65034Sakito 	register struct sc_softc *hs = &sc_softc[unit];
20154004Sfujita 	volatile register struct scsidevice *hd =
20254004Sfujita 				(struct scsidevice *)hs->sc_hc->hp_addr;
20354004Sfujita 
20454004Sfujita 	printf("sc%d: ", unit);
20554004Sfujita 
20654004Sfujita 	/*
20754004Sfujita 	 * Disable interrupts then reset the FUJI chip.
20854004Sfujita 	 */
20954004Sfujita 
21054004Sfujita 	hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
21154004Sfujita 	hd->scsi_scmd = 0;
21254004Sfujita 	hd->scsi_pctl = 0;
21354004Sfujita 	hd->scsi_temp = 0;
21454004Sfujita 	hd->scsi_tch  = 0;
21554004Sfujita 	hd->scsi_tcm  = 0;
21654004Sfujita 	hd->scsi_tcl  = 0;
21754004Sfujita 	hd->scsi_ints = 0;
21854004Sfujita 
21954004Sfujita 	/* We can use Asynchronous Transfer only */
22054004Sfujita 	printf("async");
22154004Sfujita 
22254004Sfujita 	/*
22354004Sfujita 	 * Configure MB89352 with its SCSI address, all
22454004Sfujita 	 * interrupts enabled & appropriate parity.
22554004Sfujita 	 */
22654004Sfujita 	hd->scsi_bdid = SCSI_ID;
22754004Sfujita 	hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB|
22854004Sfujita 			SCTL_PARITY_ENAB | SCTL_RESEL_ENAB |
22954004Sfujita 			SCTL_INTR_ENAB;
23054004Sfujita 	printf(", parity");
23154004Sfujita 
23254004Sfujita 	DELAY(400);
23354004Sfujita 	hd->scsi_sctl &= ~SCTL_DISABLE;
23454004Sfujita 
23554004Sfujita 	printf(", scsi id %d\n", SCSI_ID);
23654004Sfujita }
23754004Sfujita 
23854004Sfujita 
23954004Sfujita /*
24054004Sfujita  * SPC Arbitration/Selection routine
24154004Sfujita  */
24254004Sfujita 
24354004Sfujita int
issue_select(hd,target,flags)24454004Sfujita issue_select(hd, target, flags)
24554004Sfujita 	volatile register struct scsidevice *hd;
24654004Sfujita 	u_char target;
24754004Sfujita 	int flags;
24854004Sfujita {
24954004Sfujita #ifndef NODISCONNECT
25054004Sfujita 	if (flags & DQ_DISCONNECT) {
25154004Sfujita 		hd->scsi_scmd = SCMD_SET_ATN;
25254004Sfujita 	}
25354004Sfujita #endif
25454004Sfujita 
25554004Sfujita 	hd->scsi_pctl = 0;
25654004Sfujita 	hd->scsi_temp = (1 << SCSI_ID) | (1 << target);
25754004Sfujita 
25854004Sfujita 	/* select timeout is hardcoded to 2ms */
25954004Sfujita 	hd->scsi_tch = 0;
26054004Sfujita 	hd->scsi_tcm = 32;
26154004Sfujita 	hd->scsi_tcl = 4;
26254004Sfujita 
26354004Sfujita 	hd->scsi_scmd = SCMD_SELECT;
26454004Sfujita 
26554004Sfujita 	return (1);
26654004Sfujita }
26754004Sfujita 
26854004Sfujita 
26954004Sfujita /*
27054004Sfujita  * SPC Manual Transfer routines
27154004Sfujita  */
27254004Sfujita 
27354004Sfujita /* not yet */
27454004Sfujita 
27554004Sfujita 
27654004Sfujita /*
27754004Sfujita  * SPC Program Transfer routines
27854004Sfujita  */
27954004Sfujita 
28054004Sfujita int
ixfer_start(hd,len,phase)28154004Sfujita ixfer_start(hd, len, phase)
28254004Sfujita 	volatile register struct scsidevice *hd;
28354004Sfujita 	register int len;
28454004Sfujita 	register u_char phase;
28554004Sfujita {
28654004Sfujita 	register int wait = 0;
28754004Sfujita 
28854004Sfujita 	hd->scsi_sdgc = 0;
28954004Sfujita 
29054004Sfujita 	hd->scsi_tch  = ((len & 0xff0000) >> 16);
29154004Sfujita 	hd->scsi_tcm  = ((len & 0x00ff00) >>  8);
29254004Sfujita 	hd->scsi_tcl  =  (len & 0x0000ff);
29354004Sfujita 	hd->scsi_pctl = phase;
29454004Sfujita 	hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
29554004Sfujita 
29654004Sfujita 	while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
29754004Sfujita 		if (wait > SC_TIMEOUT) {
29854004Sfujita 			panic("ixfer_start: too long wait");
29954004Sfujita 		}
30054004Sfujita 		wait++;
30154004Sfujita 		DELAY(1);
30254004Sfujita 	}
30354004Sfujita }
30454004Sfujita 
30554004Sfujita int
ixfer_out(hd,len,buf)30654004Sfujita ixfer_out(hd, len, buf)
30754004Sfujita 	volatile register struct scsidevice *hd;
30854004Sfujita 	register int len;
30954004Sfujita 	register u_char *buf;
31054004Sfujita {
31154004Sfujita 	u_char *t = buf;
31254004Sfujita 	register int wait = 0;
31354004Sfujita #ifdef QUADBYTES
31454004Sfujita 	register int qwait = 0;
31554004Sfujita 	register int l_len = len >> 3;
31654004Sfujita 	register u_long * l_buf = (u_long *) buf;
31754004Sfujita 
31854004Sfujita 	for(; l_len > 0; l_len--) {
31954004Sfujita 		while ((hd->scsi_ssts & SSTS_DREG_EMPTY) == 0) {
32054004Sfujita 			if (qwait > SC_TIMEOUT) {
32154004Sfujita 				printf("ixfer_out: quad time out\n");
32254004Sfujita 				printf("ixfer_out: %d bytes sended\n",
32354004Sfujita 				       (((u_char *) l_buf) - t));
32454004Sfujita 				printf("ixfer_out: TC = %d\n",
32554004Sfujita 				       ( hd->scsi_tch << 16 ) |
32654004Sfujita 				       ( hd->scsi_tcm <<  8 ) |
32754004Sfujita 				       ( hd->scsi_tcl ));
32854004Sfujita 				return(-1);
32954004Sfujita 			}
33054004Sfujita 			qwait++;
33154004Sfujita 			DELAY(1);
33254004Sfujita 		}
33354004Sfujita 		*((u_long *) &hd->scsi_dreg) = *l_buf++;
33454004Sfujita 		*((u_long *) &hd->scsi_dreg) = *l_buf++;
33554004Sfujita 	}
33654004Sfujita 
33754004Sfujita 	len &= 0x07;
33854004Sfujita 	buf = (u_char *) l_buf;
33954004Sfujita #endif
34054004Sfujita 	for(; len > 0; len--) {
34154004Sfujita 		while (hd->scsi_ssts & SSTS_DREG_FULL) {
34254004Sfujita 			if (wait > SC_TIMEOUT) {
34354004Sfujita 				printf("ixfer_out: time out\n");
34454004Sfujita 				printf("ixfer_out: %d bytes sended\n",
34554004Sfujita 				       (buf - t));
34654004Sfujita 				return(-1);
34754004Sfujita 			}
34854004Sfujita 			wait++;
34954004Sfujita 			DELAY(1);
35054004Sfujita 		}
35154004Sfujita 		hd->scsi_dreg = *buf++;
35254004Sfujita 	}
35354004Sfujita 
35454004Sfujita #ifdef QUADBYTES
35554004Sfujita 	return(qwait);
35654004Sfujita #else
35754004Sfujita 	return(wait);
35854004Sfujita #endif
35954004Sfujita }
36054004Sfujita 
36154004Sfujita int
ixfer_in(hd,len,buf)36254004Sfujita ixfer_in(hd, len, buf)
36354004Sfujita 	volatile register struct scsidevice *hd;
36454004Sfujita 	register int len;
36554004Sfujita 	register u_char *buf;
36654004Sfujita {
36754004Sfujita 	u_char *t = buf;
36854004Sfujita 	register int wait = 0;
36954004Sfujita #ifdef QUADBYTES
37054004Sfujita 	register int qwait = 0;
37154004Sfujita 	register int l_len = len >> 3;
37254004Sfujita 	register u_long * l_buf = (u_long *) buf;
37354004Sfujita 
37454004Sfujita 	for(; l_len > 0; l_len--) {
37554004Sfujita 		while ((hd->scsi_ssts & SSTS_DREG_FULL) == 0) {
37654004Sfujita 			if (qwait > SC_TIMEOUT) {
37754004Sfujita 				printf("ixfer_in: quad time out\n");
37854004Sfujita 				printf("ixfer_in: %d bytes recieved\n",
37954004Sfujita 				       (((u_char *) l_buf) - t));
38054004Sfujita 				return(-1);
38154004Sfujita 			}
38254004Sfujita 			qwait++;
38354004Sfujita 			DELAY(1);
38454004Sfujita 		}
38554004Sfujita 		*l_buf++ = *((u_long *) &hd->scsi_dreg);
38654004Sfujita 		*l_buf++ = *((u_long *) &hd->scsi_dreg);
38754004Sfujita 	}
38854004Sfujita 
38954004Sfujita 	len &= 0x07;
39054004Sfujita 	buf = (u_char *) l_buf;
39154004Sfujita #endif
39254004Sfujita 	for (; len > 0; len--) {
39354004Sfujita 		while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
39454004Sfujita 			if (wait > SC_TIMEOUT) {
39554004Sfujita 				printf("ixfer_in: time out\n");
39654004Sfujita 				printf("ixfer_in: %d bytes recieved\n",
39754004Sfujita 				       (buf - t));
39854004Sfujita 				return(-1);
39954004Sfujita 			}
40054004Sfujita 			wait++;
40154004Sfujita 			DELAY(1);
40254004Sfujita 		}
40354004Sfujita 		*buf++ = hd->scsi_dreg;
40454004Sfujita 	}
40554004Sfujita 
40654004Sfujita 
40754004Sfujita #ifdef QUADBYTES
40854004Sfujita 	return(qwait);
40954004Sfujita #else
41054004Sfujita 	return(wait);
41154004Sfujita #endif
41254004Sfujita }
41354004Sfujita 
41454004Sfujita 
41554004Sfujita #ifdef XFER_ENABLE
41654004Sfujita /*
41754004Sfujita  * SPC Interrupt base Transfer Routines
41854004Sfujita  */
41954004Sfujita 
42054004Sfujita int
txfer_start(hd,len,phase)42154004Sfujita txfer_start(hd, len, phase)
42254004Sfujita 	volatile register struct scsidevice *hd;
42354004Sfujita 	register int len;
42454004Sfujita 	register u_char phase;
42554004Sfujita {
42654004Sfujita 	register int wait = 0;
42754004Sfujita 
42854004Sfujita 	hd->scsi_sdgc = SDGC_XFER_ENAB;		/* for interrupt */
42954004Sfujita 
43054004Sfujita 	hd->scsi_tch  = ((len & 0xff0000) >> 16);
43154004Sfujita 	hd->scsi_tcm  = ((len & 0x00ff00) >>  8);
43254004Sfujita 	hd->scsi_tcl  =  (len & 0x0000ff);
43354004Sfujita 	hd->scsi_pctl = phase;
43454004Sfujita 	hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
43554004Sfujita 
43654004Sfujita 	while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
43754004Sfujita 		if (wait > SC_TIMEOUT) {
43854004Sfujita 			panic("ixfer_start: too long wait");
43954004Sfujita 		}
44054004Sfujita 		wait++;
44154004Sfujita 		DELAY(1);
44254004Sfujita 	}
44354004Sfujita }
44454004Sfujita 
44554004Sfujita int
txfer_in(ctlr)44654004Sfujita txfer_in(ctlr)
44754004Sfujita 	register int ctlr;
44854004Sfujita {
449*65034Sakito 	register struct sc_softc *hs = &sc_softc[ctlr];
45054004Sfujita 	volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr;
45154004Sfujita 	register struct scsi_queue *dq = hs->sc_sq.dq_forw;
45254004Sfujita #ifdef QUADBYTES
45354004Sfujita 	register u_long *lp;
45454004Sfujita 
45554004Sfujita 	if (hd->scsi_ssts & SSTS_DREG_FULL) {
45654004Sfujita 		lp = (u_long *) dq->dq_xferp;
45754004Sfujita 
45854004Sfujita 		*lp++ = *((u_long *) &hd->scsi_dreg);
45954004Sfujita 		*lp++ = *((u_long *) &hd->scsi_dreg);
46054004Sfujita 
46154004Sfujita 		dq->dq_xferp = (u_char *) lp;
46254004Sfujita 		dq->dq_xfercnt -= 8;
46354004Sfujita 
46454004Sfujita 		goto xfer_done;
46554004Sfujita 	}
46654004Sfujita #endif
46754004Sfujita 
46854004Sfujita 	*dq->dq_xferp++ = hd->scsi_dreg;
46954004Sfujita 	dq->dq_xfercnt--;
47054004Sfujita 
47154004Sfujita  xfer_done:
47254004Sfujita #ifdef DEBUGPRINT
47354004Sfujita 	if (dq->dq_xfercnt == 0) {
47454004Sfujita 		dbgprintf("txfer_in: ");
47554004Sfujita 		dbgprintf("dq->dq_bp->b_un.b_addr = 0x%s, ", hexstr(dq->dq_bp->b_un.b_addr, 8));
47654004Sfujita 		dbgprintf("dq->dq_xferp = 0x%s :", hexstr(dq->dq_xferp, 8));
47754004Sfujita 		dbgprintf("done\n");
47854004Sfujita 	}
47954004Sfujita #endif
48054004Sfujita }
48154004Sfujita #endif
48254004Sfujita 
48354004Sfujita /*
48454004Sfujita  * SCSI Job Handler
48554004Sfujita  */
48654004Sfujita 
48754004Sfujita int
scstart(ctlr)48854004Sfujita scstart(ctlr)
48954004Sfujita 	int ctlr;
49054004Sfujita {
491*65034Sakito 	register struct sc_softc *hs = &sc_softc[ctlr];
49254004Sfujita 	volatile register struct scsidevice *hd =
49354004Sfujita 		(struct scsidevice *) hs->sc_hc->hp_addr;
49454004Sfujita 	register struct scsi_queue *dq = hs->sc_sq.dq_forw;
49554004Sfujita 
49654004Sfujita 	dq->dq_imax =  0;
49754004Sfujita 	dq->dq_imin = -1;
49854004Sfujita 	dq->dq_omax =  0;
49954004Sfujita 	dq->dq_omin = -1;
50054004Sfujita 
50154004Sfujita 	hs->sc_flags  = 0;
50254004Sfujita 	hs->sc_phase  = ARB_SEL_PHASE;
50354004Sfujita 
50454004Sfujita 	hs->sc_stat   = 0;
50554004Sfujita 	hs->sc_msg[0] = 0;
50654004Sfujita 
50754004Sfujita #ifdef DEBUGPRINT
50854004Sfujita 	dbgprintf("\n");
50954004Sfujita 	dbgprintf("scstart: ID = %d\n", dq->dq_slave);
51054004Sfujita 	dbgprintf("scstart: cdb[0] = %s\n", scsi_command(dq->dq_cdb->cdb[0]));
51154004Sfujita 	dbgprintf("scstart: cdb[1] = 0x%s\n", hexstr(dq->dq_cdb->cdb[1], 2));
51254004Sfujita 	dbgprintf("scstart: cdb[2] = 0x%s\n", hexstr(dq->dq_cdb->cdb[2], 2));
51354004Sfujita 	dbgprintf("scstart: cdb[3] = 0x%s\n", hexstr(dq->dq_cdb->cdb[3], 2));
51454004Sfujita 	dbgprintf("scstart: cdb[4] = 0x%s\n", hexstr(dq->dq_cdb->cdb[4], 2));
51554004Sfujita 	dbgprintf("scstart: cdb[5] = 0x%s\n", hexstr(dq->dq_cdb->cdb[5], 2));
51654004Sfujita 	if (dq->dq_cdb->cdb[0] & 0xE0) {
51754004Sfujita 		dbgprintf("scstart: cdb[6] = 0x%s\n", hexstr(dq->dq_cdb->cdb[6], 2));
51854004Sfujita 		dbgprintf("scstart: cdb[7] = 0x%s\n", hexstr(dq->dq_cdb->cdb[7], 2));
51954004Sfujita 		dbgprintf("scstart: cdb[8] = 0x%s\n", hexstr(dq->dq_cdb->cdb[8], 2));
52054004Sfujita 		dbgprintf("scstart: cdb[9] = 0x%s\n", hexstr(dq->dq_cdb->cdb[9], 2));
52154004Sfujita 	}
52254004Sfujita 	dbgprintf("scstart: bp->b_bcount = %d\n", dq->dq_bp->b_bcount);
52354004Sfujita 	dbgprintf("scstart: %s\n", phase_name(hs->sc_phase));
52454004Sfujita #endif
52554004Sfujita 
52654004Sfujita 	issue_select(hd, dq->dq_slave, dq->dq_flags);
52754004Sfujita 
52854004Sfujita 	return(1);
52954004Sfujita }
53054004Sfujita 
53154004Sfujita int
_scintr()53254004Sfujita _scintr()
53354004Sfujita {
534*65034Sakito 	register struct sc_softc *hs;
53554004Sfujita 	volatile register struct scsidevice *hd;
53654004Sfujita 	register int ctlr;
53754004Sfujita 
53854004Sfujita 	for (ctlr = 0; ctlr < NSC; ctlr++) {
539*65034Sakito 		hs = &sc_softc[ctlr];
54054004Sfujita 		hd = (struct scsidevice *) hs->sc_hc->hp_addr;
54154004Sfujita 
54254004Sfujita #ifdef XFER_ENABLE
54354004Sfujita 		if (((hd->scsi_psns & PHASE) == DATA_IN_PHASE) &&
54454004Sfujita 		    (hd->scsi_serr & SERR_XFER_OUT))
54554004Sfujita 			txfer_in(ctlr);
54654004Sfujita #endif
54754004Sfujita 
54854004Sfujita 		if (hd->scsi_ints != 0)
54954004Sfujita 			scintr(ctlr);
55054004Sfujita 	}
55154004Sfujita 
55254004Sfujita 	return;
55354004Sfujita }
55454004Sfujita 
55554004Sfujita int
scintr(ctlr)55654004Sfujita scintr(ctlr)
55754004Sfujita 	register int ctlr;
55854004Sfujita {
559*65034Sakito 	register struct sc_softc *hs = &sc_softc[ctlr];
56054004Sfujita 	volatile register struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr;
56154004Sfujita 	register struct scsi_queue *dq = hs->sc_sq.dq_forw;
56254004Sfujita 	register u_char ints, temp;
56354004Sfujita 	register int i, slave;
56454004Sfujita 	int wait, len;
56554004Sfujita 	u_char *buf;
56654004Sfujita 
56754004Sfujita 	ints = hd->scsi_ints;
56854004Sfujita 
56954004Sfujita #ifdef DEBUGPRINT
57054004Sfujita 	dbgprintf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x",
57154004Sfujita 	       ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
57254004Sfujita 	if (hs->sc_phase == CMD_PHASE)
57354004Sfujita 		dbgprintf("   [%s]", scsi_command(dq->dq_cdb->cdb[0]));
57454004Sfujita 	if (hs->sc_phase & PHASE_MSG)
57554004Sfujita 		dbgprintf("   [%s]", scsi_mesg(hs->sc_msg[0]));
57654004Sfujita 	dbgprintf("\n");
57754004Sfujita #endif
57854004Sfujita 
57954004Sfujita 	if (ints & INTS_DISCON) {
58054004Sfujita 		if (hs->sc_msg[0] == MSG_CMD_COMPLETE) {
58154004Sfujita 			hd->scsi_ints = ints;
58254004Sfujita 
58354004Sfujita 			if (hs->sc_lock != NULL) {
58454004Sfujita 				*(hs->sc_lock) = SC_IO_COMPLETE;
58554004Sfujita 			} else {
58654004Sfujita 				(dq->dq_driver->d_intr)(dq->dq_unit, hs->sc_stat);
58754004Sfujita 			}
58854004Sfujita 
58954004Sfujita 			return;
59054004Sfujita #ifndef NODISCONNECT
59154004Sfujita 		} else if (hs->sc_msg[0] == MSG_DISCONNECT) {
59254004Sfujita #ifdef DEBUGPRINT
59354004Sfujita 			dbgprintf("scintr: DISCONNECT : ctlr = %d, slave = %d, cdb = %s\n",
59454004Sfujita 			       dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0]));
59554004Sfujita #endif
59654004Sfujita 
59754004Sfujita 			hd->scsi_ints = ints;
59854004Sfujita 
59954004Sfujita 			scpend(dq);
60054004Sfujita 
60154004Sfujita 			dq = hs->sc_sq.dq_forw;
60254004Sfujita 
60354004Sfujita 			if (dq != &hs->sc_sq)
60454004Sfujita 				(dq->dq_driver->d_start)(dq->dq_unit);
60554004Sfujita 
60654004Sfujita 			return;
60754004Sfujita #endif
60854004Sfujita 		} else
60954004Sfujita 			goto abort;
61054004Sfujita 
61154004Sfujita #ifndef NODISCONNECT
61254004Sfujita 	} else if (ints & INTS_RESEL) {
61354004Sfujita 		temp = hd->scsi_temp & ~(1 << SCSI_ID);
61454004Sfujita 		for (slave = 0; temp != 1; slave++) {
61554004Sfujita 			temp >>= 1;
61654004Sfujita 		}
61754004Sfujita 
61854004Sfujita 		hd->scsi_ints = ints;
61954004Sfujita 
62054004Sfujita 		scrschdl(ctlr, slave);
62154004Sfujita 
62254004Sfujita 		dq = hs->sc_sq.dq_forw;
62354004Sfujita #ifdef DEBUGPRINT
62454004Sfujita 		dbgprintf("\n");
62554004Sfujita 		dbgprintf("scintr: RESELECT : ctlr = %d, slave = %d, cdb = %s\n",
62654004Sfujita 		       dq->dq_ctlr, dq->dq_slave, scsi_command(dq->dq_cdb->cdb[0]));
62754004Sfujita #endif
62854004Sfujita #endif
62954004Sfujita 	} else if (ints & INTS_CMD_DONE) {
63054004Sfujita 		if (hs->sc_phase == BUS_FREE_PHASE)
63154004Sfujita 			goto abort;
63254004Sfujita 		else if (hs->sc_phase  == MESG_IN_PHASE) {
63354004Sfujita 			hd->scsi_scmd = SCMD_RST_ACK;
63454004Sfujita 
63554004Sfujita 			 if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) ||
63654004Sfujita 			     (hs->sc_msg[0] == MSG_DISCONNECT)) {
63754004Sfujita 				 hd->scsi_ints = ints;
63854004Sfujita 
63954004Sfujita 				 hs->sc_phase  = BUS_FREE_PHASE;
64054004Sfujita 
64154004Sfujita 				 return;
64254004Sfujita 			 }
64354004Sfujita 		}
64454004Sfujita 		if (hs->sc_flags & SC_SEL_TIMEOUT)
64554004Sfujita 			hs->sc_flags &= ~SC_SEL_TIMEOUT;
64654004Sfujita 	} else if (ints & INTS_SRV_REQ) {
64754004Sfujita 		if (hs->sc_phase != MESG_IN_PHASE)
64854004Sfujita 			goto abort;
64954004Sfujita 	} else if (ints & INTS_TIMEOUT) {
65054004Sfujita 		if (hs->sc_phase == ARB_SEL_PHASE) {
65154004Sfujita 			if (hs->sc_flags & SC_SEL_TIMEOUT) {
65254004Sfujita 				hd->scsi_ints = ints;
65354004Sfujita 				hs->sc_flags &= ~SC_SEL_TIMEOUT;
65454004Sfujita 				/* Such SCSI Device is not conected. */
65554004Sfujita 
65654004Sfujita 				if (hs->sc_lock != NULL) {
65754004Sfujita 					*(hs->sc_lock) = SC_DEV_NOT_FOUND;
65854004Sfujita 				} else {
65954004Sfujita 					(dq->dq_driver->d_intr)(dq->dq_unit, SC_DEV_NOT_FOUND);
66054004Sfujita 				}
66154004Sfujita 
66254004Sfujita 				return;
66354004Sfujita 			} else {
66454004Sfujita 				/* wait more 250 usec */
66554004Sfujita 				hs->sc_flags |= SC_SEL_TIMEOUT;
66654004Sfujita 				hd->scsi_temp = 0;
66754004Sfujita 				hd->scsi_tch  = 0;
66854004Sfujita 				hd->scsi_tcm  = 0x06;
66954004Sfujita 				hd->scsi_tcl  = 0x40;
67054004Sfujita 				hd->scsi_ints = ints;
67154004Sfujita 				return;
67254004Sfujita 			}
67354004Sfujita 		} else
67454004Sfujita 			goto abort;
67554004Sfujita 	} else
67654004Sfujita 		goto abort;
67754004Sfujita 
67854004Sfujita 	hd->scsi_ints = ints;
67954004Sfujita 
68054004Sfujita 	/*
68154004Sfujita 	 * Next SCSI Transfer
68254004Sfujita 	 */
68354004Sfujita 
68454004Sfujita 	wait = SC_TIMEOUT;
68554004Sfujita 	while ((hd->scsi_psns & PSNS_REQ) == 0) {
68654004Sfujita 		if (wait < 0) {
68754004Sfujita /*			hd->scsi_scmd = SCMD_SET_ATN;	*/
68854004Sfujita 			hd->scsi_scmd = SCMD_RST;
68954004Sfujita 			DELAY(40);			/* wait 25 micro sec */
69054004Sfujita 			hd->scsi_scmd = 0;
69154004Sfujita 
69254004Sfujita 			wait = SC_TIMEOUT;
69354004Sfujita 			while (wait-- > 0)
69454004Sfujita 				DELAY(1);
69554004Sfujita 
69654004Sfujita 			if (hs->sc_lock != NULL) {
69754004Sfujita 				*(hs->sc_lock) = SC_IO_TIMEOUT;
69854004Sfujita 			} else {
69954004Sfujita 				(dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT);
70054004Sfujita 			}
70154004Sfujita 
70254004Sfujita 			return;
70354004Sfujita 		}
70454004Sfujita 		DELAY(1);
70554004Sfujita 		wait--;
70654004Sfujita 	}
70754004Sfujita 
70854004Sfujita 	hs->sc_phase = hd->scsi_psns & PHASE;
70954004Sfujita 
71054004Sfujita #ifdef DEBUGPRINT
71154004Sfujita 	dbgprintf("scintr: %s\n", phase_name(hs->sc_phase));
71254004Sfujita #endif
71354004Sfujita 
71454004Sfujita 	if ((hs->sc_phase == DATA_OUT_PHASE) || (hs->sc_phase == DATA_IN_PHASE)) {
71554004Sfujita 		len = ( hs->sc_lock != NULL ? hs->sc_len : dq->dq_bp->b_bcount );
71654004Sfujita 		buf = ( hs->sc_lock != NULL ? hs->sc_buf : (u_char *) dq->dq_bp->b_un.b_addr );
71754004Sfujita 	} else if (hs->sc_phase == CMD_PHASE) {
71854004Sfujita 		len = ( hs->sc_lock != NULL ? hs->sc_cdblen : dq->dq_cdb->len );
71954004Sfujita 		buf = ( hs->sc_lock != NULL ? hs->sc_cdb    : dq->dq_cdb->cdb );
72054004Sfujita 	} else if (hs->sc_phase == STATUS_PHASE) {
72154004Sfujita 		len = 1;
72254004Sfujita 		buf = &hs->sc_stat;
72354004Sfujita 	} else {
72454004Sfujita 		if (hs->sc_phase == MESG_OUT_PHASE) {
72554004Sfujita #ifndef NODISCONNECT
72654004Sfujita 			hs->sc_msg[0] = MSG_IDENTIFY_DR;
72754004Sfujita #else
72854004Sfujita 			hs->sc_msg[0] = MSG_IDENTIFY;
72954004Sfujita #endif
73054004Sfujita 		}
73154004Sfujita 		len = 1;
73254004Sfujita 		buf = hs->sc_msg;
73354004Sfujita 	}
73454004Sfujita 
73554004Sfujita #ifdef XFER_ENABLE
73654004Sfujita 	if ((hs->sc_lock == NULL) && (hs->sc_phase == DATA_IN_PHASE)) {
73754004Sfujita 		dq->dq_xferp   = buf;
73854004Sfujita 		dq->dq_xfercnt = len;
73954004Sfujita 		txfer_start(hd, len, hs->sc_phase);
74054004Sfujita 		return;
74154004Sfujita 	}
74254004Sfujita #endif
74354004Sfujita 
74454004Sfujita 	ixfer_start(hd, len, hs->sc_phase);
74554004Sfujita 	if (hs->sc_phase & PHASE_IO) {
74654004Sfujita 		if ((wait = ixfer_in(hd, len, buf)) == -1) {
74754004Sfujita 			goto time_out;
74854004Sfujita 		}
74954004Sfujita 		if (dq->dq_imin == -1)
75054004Sfujita 			dq->dq_imin = wait;
75154004Sfujita 		else
75255175Saki 			dq->dq_imin = min(wait, dq->dq_imin);
75355175Saki 		dq->dq_imax = max(wait, dq->dq_imax);
75454004Sfujita 	} else {
75554004Sfujita 		if ((wait = ixfer_out(hd, len, buf)) == -1) {
75654004Sfujita 			goto time_out;
75754004Sfujita 		}
75854004Sfujita 		if (dq->dq_omin == -1)
75954004Sfujita 			dq->dq_omin = wait;
76054004Sfujita 		else
76155175Saki 			dq->dq_omin = min(wait, dq->dq_omin);
76255175Saki 		dq->dq_omax = max(wait, dq->dq_omax);
76354004Sfujita 	}
76454004Sfujita 
76554004Sfujita 	return;
76654004Sfujita 
76754004Sfujita  time_out:
76854004Sfujita 	scabort(hs, hd);
76954004Sfujita 	printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Current Status\n",
77054004Sfujita 	       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
77154004Sfujita 
77254004Sfujita 	if (hs->sc_lock != NULL) {
77354004Sfujita 		*(hs->sc_lock) = SC_IO_TIMEOUT;
77454004Sfujita 	} else {
77554004Sfujita 		(dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_TIMEOUT);
77654004Sfujita 	}
77754004Sfujita 
77854004Sfujita 	return;
77954004Sfujita 
78054004Sfujita 	/*
78154004Sfujita 	 * SCSI Abort
78254004Sfujita 	 */
78354004Sfujita  abort:
78454004Sfujita 
78554004Sfujita 	/* SCSI IO failed */
78654004Sfujita 	scabort(hs, hd);
78754004Sfujita 	hd->scsi_ints = ints;
78854004Sfujita 
78954004Sfujita 	if (hs->sc_lock != NULL) {
79054004Sfujita 		*(hs->sc_lock) = SC_IO_FAILED;
79154004Sfujita 	} else {
79254004Sfujita 		(dq->dq_driver->d_intr)(dq->dq_unit, SC_IO_FAILED);
79354004Sfujita 	}
79454004Sfujita 
79554004Sfujita 	return;
79654004Sfujita }
79754004Sfujita 
79854004Sfujita int
scabort(hs,hd)79954004Sfujita scabort(hs, hd)
800*65034Sakito 	register struct sc_softc *hs;
80154004Sfujita 	volatile register struct scsidevice *hd;
80254004Sfujita {
80354004Sfujita 	int len;
80454004Sfujita 	u_char junk;
80554004Sfujita 
80654004Sfujita #ifdef DEBUGPRINT
80754004Sfujita 	dbgprintall();
80854004Sfujita 	printf("\n");
80954004Sfujita #endif
81054004Sfujita 
81154004Sfujita 	printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Current Status\n",
81254004Sfujita 	       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
81354004Sfujita 
81454004Sfujita 	if (hd->scsi_ints != 0)
81554004Sfujita 		hd->scsi_ints = hd->scsi_ints;
81654004Sfujita 	printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Reset INTS reg.\n",
81754004Sfujita 	       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
81854004Sfujita 
81954004Sfujita 	if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
82054004Sfujita 		/* no longer connected to scsi target */
82154004Sfujita 		return;
82254004Sfujita 
82354004Sfujita 	/* get the number of bytes remaining in current xfer + fudge */
82454004Sfujita 	len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
82554004Sfujita 	printf("scabort: Current xfer count = %d\n", len);
82654004Sfujita 
82754004Sfujita 	/* for that many bus cycles, try to send an abort msg */
82854004Sfujita 	for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) {
82954004Sfujita /*
83054004Sfujita 		hd->scsi_scmd = SCMD_SET_ATN;
83154004Sfujita 		printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Set ATN\n",
83254004Sfujita 		       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
83354004Sfujita  */
83454004Sfujita 		while ((hd->scsi_psns & PSNS_REQ) == 0) {
83554004Sfujita 			printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Wait for REQ\n",
83654004Sfujita 			       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
83754004Sfujita 			if (! (hd->scsi_ssts & SSTS_INITIATOR))
83854004Sfujita 				goto out;
83954004Sfujita 			DELAY(1);
84054004Sfujita 		}
84154004Sfujita /*
84254004Sfujita 		if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE) {
84354004Sfujita 			hd->scsi_scmd = SCMD_RST_ATN;
84454004Sfujita 			printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Reset ATN\n",
84554004Sfujita 			       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
84654004Sfujita 		}
84754004Sfujita  */
84854004Sfujita 		hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE;
84954004Sfujita 		printf("scabort: Phase = %s\n", phase_name(hs->sc_phase));
85054004Sfujita 
85154004Sfujita 		if (hd->scsi_psns & PHASE_IO) {
85254004Sfujita 			/* one of the input phases - read & discard a byte */
85354004Sfujita 			hd->scsi_scmd = SCMD_SET_ACK;
85454004Sfujita 			printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Set ACK\n",
85554004Sfujita 			       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
85654004Sfujita 
85754004Sfujita 			while (hd->scsi_psns & PSNS_REQ) {
85854004Sfujita 				printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Wait for REQ\n",
85954004Sfujita 				       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
86054004Sfujita 				DELAY(1);
86154004Sfujita 			}
86254004Sfujita 
86354004Sfujita 			junk = hd->scsi_temp;
86454004Sfujita 			printf("scabort: TEMP = 0x%s\n", hexstr(junk, 2));
86554004Sfujita 		} else {
86654004Sfujita 			/* one of the output phases - send an abort msg */
86754004Sfujita 			hd->scsi_temp = MSG_ABORT;
86854004Sfujita 			hd->scsi_scmd = SCMD_SET_ACK;
86954004Sfujita 			printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Set ACK\n",
87054004Sfujita 			       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
87154004Sfujita 
87254004Sfujita 			while (hd->scsi_psns & PSNS_REQ) {
87354004Sfujita 				printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Wait for REQ\n",
87454004Sfujita 				       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
87554004Sfujita 				DELAY(1);
87654004Sfujita 			}
87754004Sfujita 		}
87854004Sfujita 
87954004Sfujita 		hd->scsi_scmd = SCMD_RST_ACK;
88054004Sfujita 		printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Reset ACK\n",
88154004Sfujita 		       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
88254004Sfujita 	}
88354004Sfujita out:
88454004Sfujita 	/*
88554004Sfujita 	 * Either the abort was successful & the bus is disconnected or
88654004Sfujita 	 * the device didn't listen.  If the latter, announce the problem.
88754004Sfujita 	 * Either way, reset the card & the SPC.
88854004Sfujita 	 */
88954004Sfujita 	if (len < 0 && hs)
89054004Sfujita 		printf("sc%d: abort failed.  phase=0x%x, ssts=0x%x\n",
89154004Sfujita 			hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts);
89254004Sfujita 
89354004Sfujita 	while (hd->scsi_ints == 0)
89454004Sfujita 		DELAY(1);
89554004Sfujita 
89654004Sfujita 	hd->scsi_ints = hd->scsi_ints;
89754004Sfujita 
89854004Sfujita 	printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x   Current Status\n",
89954004Sfujita 	       hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
90054004Sfujita 
90154004Sfujita 	printf("scabort: SCSI abort operation is done\n");
90254004Sfujita }
90354004Sfujita 
90454004Sfujita 
90554004Sfujita /*
90654004Sfujita  * SPC device queue handling
90754004Sfujita  */
90854004Sfujita 
90954004Sfujita int
screq(dq)91054004Sfujita screq(dq)
91154004Sfujita 	register struct scsi_queue *dq;
91254004Sfujita {
913*65034Sakito 	register struct sc_softc *hs = &sc_softc[dq->dq_ctlr];
91454004Sfujita 	register struct scsi_queue *hq = &hs->sc_sq;
91554004Sfujita 
91654004Sfujita 	insque(dq, hq->dq_back);
91754004Sfujita 
91854004Sfujita 	if (dq->dq_back == hq) {
91954004Sfujita #ifdef QUE_DEBUG
92054004Sfujita 		printf("screq: slave = %d, command = %s\n",
92154004Sfujita 		       hq->dq_forw->dq_slave,
92254004Sfujita 		       scsi_command(hq->dq_forw->dq_cdb->cdb[0]));
92354004Sfujita #endif
92454004Sfujita 		return(1);
92554004Sfujita 	}
92654004Sfujita 
92754004Sfujita 	return(0);
92854004Sfujita }
92954004Sfujita 
93054004Sfujita #ifndef NODISCONNECT
93154004Sfujita int
scpend(dq)93254004Sfujita scpend(dq)
93354004Sfujita 	register struct scsi_queue *dq;
93454004Sfujita {
935*65034Sakito 	register struct sc_softc *hs = &sc_softc[dq->dq_ctlr];
93654004Sfujita 	register struct scsi_queue *hq = &hs->sc_sq;
93754004Sfujita 	register struct scsi_queue *wq = &hs->sc_wq;
93854004Sfujita 
93954004Sfujita 	remque(dq);
94054004Sfujita 
94154004Sfujita 	insque(dq, wq->dq_back);
94254004Sfujita }
94354004Sfujita 
94454004Sfujita int
scrschdl(ctlr,slave)94554004Sfujita scrschdl(ctlr, slave)
94654004Sfujita 	register int ctlr;
94754004Sfujita 	register int slave;
94854004Sfujita {
949*65034Sakito 	register struct sc_softc *hs = &sc_softc[ctlr];
95054004Sfujita 	register struct scsi_queue *wq = &hs->sc_wq;
95154004Sfujita 	register struct scsi_queue *hq = &hs->sc_sq;
95254004Sfujita 	register struct scsi_queue *dq;
95354004Sfujita 
95454004Sfujita 	for (dq = wq->dq_forw; dq != wq; dq = dq->dq_forw) {
95554004Sfujita 		if (dq->dq_slave == slave)
95654004Sfujita 			goto found;
95754004Sfujita 	}
95854004Sfujita 
95954004Sfujita 	return(0);
96054004Sfujita 
96154004Sfujita  found:
96254004Sfujita 	remque(dq);
96354004Sfujita 	insque(dq, hq);
96454004Sfujita 
96554004Sfujita 	return(1);
96654004Sfujita }
96754004Sfujita #endif
96854004Sfujita 
96954004Sfujita int
scfree(dq)97054004Sfujita scfree(dq)
97154004Sfujita 	register struct scsi_queue *dq;
97254004Sfujita {
973*65034Sakito 	register struct sc_softc *hs = &sc_softc[dq->dq_ctlr];
97454004Sfujita 	register struct scsi_queue *hq = &hs->sc_sq;
97554004Sfujita 	int status = hs->sc_stat;
97654004Sfujita 
97754004Sfujita 	remque(dq);
97854004Sfujita 
97954004Sfujita 	hs->sc_flags  = 0;
98054004Sfujita 	hs->sc_phase  = BUS_FREE_PHASE;
98154004Sfujita 
98254004Sfujita 	hs->sc_stat   = 0;
98354004Sfujita 	hs->sc_msg[0] = 0;
98454004Sfujita 
98554004Sfujita 	if ((dq = hq->dq_forw) != hq) {
98654004Sfujita #ifdef QUE_DEBUG
98754004Sfujita 		printf("scfree: slave = %d, command = %s\n",
98854004Sfujita 		       dq->dq_slave,
98954004Sfujita 		       scsi_command(dq->dq_cdb->cdb[0]));
99054004Sfujita #endif
99154004Sfujita 		(dq->dq_driver->d_start)(dq->dq_unit);
99254004Sfujita 	}
99354004Sfujita 
99454004Sfujita 	return(status);
99554004Sfujita }
99654004Sfujita 
99754004Sfujita /*
99854004Sfujita  * SCSI common interface
99954004Sfujita  */
100054004Sfujita 
100154004Sfujita int scsi_lock[NSC];
100254004Sfujita 
100354004Sfujita int
scsi_result(unit,stat)100454004Sfujita scsi_result(unit, stat)
100554004Sfujita 	int unit, stat;
100654004Sfujita {
100754004Sfujita #ifdef SCSI_DEBUG
100854004Sfujita 	printf("scsi_result: stat = %s\n", scsi_status(stat));
100954004Sfujita #endif
101054004Sfujita 	if (stat < 0)
101154004Sfujita 		scsi_lock[unit] = stat;
101254004Sfujita 	else
101354004Sfujita 		scsi_lock[unit] = SC_IO_COMPLETE;
101454004Sfujita }
101554004Sfujita 
101654004Sfujita struct	driver scsi_driver = {
101754004Sfujita 	(int (*)()) 0, "scsi", (int (*)()) 0, (int (*)()) 0, scsi_result, (int (*)()) 0
101854004Sfujita };
101954004Sfujita 
102054004Sfujita struct scsi_queue scsi_entry[NSC];
102154004Sfujita 
102254004Sfujita int
scsi_immed_command(ctlr,slave,lun,cdb,buf,len)102354004Sfujita scsi_immed_command(ctlr, slave, lun, cdb, buf, len)
102454004Sfujita 	int ctlr, slave, lun;
102554004Sfujita 	struct scsi_fmt_cdb *cdb;
102654004Sfujita 	u_char *buf;
102754004Sfujita 	unsigned len;
102854004Sfujita {
1029*65034Sakito 	register struct sc_softc *hs = &sc_softc[ctlr];
103054004Sfujita 	volatile register struct scsidevice *hd =
103154004Sfujita 		(struct scsidevice *) hs->sc_hc->hp_addr;
103254004Sfujita 	register struct scsi_queue *dq = &scsi_entry[ctlr];
103354004Sfujita 	register struct buf *bp;
103454004Sfujita 	int s, status, wait = 30;
103554004Sfujita 
103654004Sfujita #ifdef SCSI_DEBUG
103754004Sfujita 	printf("scsi_immed_command( %d, %d, %d, cdb(%d,%s), buf, %d): Start\n",
103854004Sfujita 	       ctlr, slave, lun, cdb->len, scsi_command(cdb->cdb[0]), len);
103954004Sfujita #endif
104057057Sakito 	bp = geteblk(len);
104157057Sakito 	bp->b_flags = B_BUSY;
104254004Sfujita 
104354004Sfujita 	s = splbio();
104454004Sfujita 
104554004Sfujita 	dq->dq_unit   = ctlr;
104654004Sfujita 	dq->dq_ctlr   = ctlr;
104754004Sfujita 	dq->dq_slave  = slave;
104854004Sfujita 	dq->dq_driver = &scsi_driver;
104954004Sfujita 	dq->dq_cdb    = cdb;
105054004Sfujita 	dq->dq_bp     = bp;
105154004Sfujita 
105254004Sfujita 	scsi_lock[ctlr] = SC_IN_PROGRESS;
105354004Sfujita 	if (screq(dq))
105454004Sfujita 		scstart(ctlr);
105554004Sfujita 
105654004Sfujita 	splx(s);
105754004Sfujita 
105854004Sfujita 	while (scsi_lock[ctlr] == SC_IN_PROGRESS) {
105954004Sfujita 		if (wait < 0) {
106054004Sfujita 			scabort(hs, hd);
106154004Sfujita 
106254004Sfujita 			s = splbio();
106354004Sfujita 			status = scfree(dq);
106454004Sfujita 			splx(s);
106554004Sfujita 
106654004Sfujita 			bp->b_flags = 0;
106754004Sfujita 
106854004Sfujita 			return(SC_IO_FAILED);
106954004Sfujita 		}
107054004Sfujita 
107154004Sfujita 		DELAY(100000);
107254004Sfujita 		wait--;
107354004Sfujita 	}
107454004Sfujita 
107554004Sfujita 	s = splbio();
107654004Sfujita 	status = scfree(dq);
107754004Sfujita 	splx(s);
107854004Sfujita 
107954004Sfujita 	if (scsi_lock[ctlr] < 0)
108054004Sfujita 		status = scsi_lock[ctlr];
108154004Sfujita 
108257057Sakito 	bcopy(bp->b_un.b_addr, buf, len);
108354004Sfujita 
108457057Sakito 	brelse(bp);
108557057Sakito 
108654004Sfujita #ifdef SCSI_DEBUG
108754004Sfujita 		printf("scsi_immed_command: Status -- 0x%x\n", status);
108854004Sfujita #endif
108954004Sfujita 	return(status);
109054004Sfujita }
109154004Sfujita 
109254004Sfujita int
sc_test_unit_rdy(ctlr,slave,lun)1093*65034Sakito sc_test_unit_rdy(ctlr, slave, lun)
109454004Sfujita 	int ctlr, slave, lun;
109554004Sfujita {
109654004Sfujita 	static struct scsi_fmt_cdb cdb = { 6, CMD_TEST_UNIT_READY };
109754004Sfujita 	int stat;
109854004Sfujita 
109954004Sfujita 	while ((stat = scsi_immed_command(ctlr, slave, lun,
110054004Sfujita 					  &cdb, (u_char *) 0, 0)) == SC_BUSY) {
110154004Sfujita 		DELAY(10000);
110254004Sfujita 	}
110354004Sfujita 
110454004Sfujita 	return(stat);
110554004Sfujita }
110654004Sfujita 
110754004Sfujita int
sc_request_sense(ctlr,slave,lun,buf,len)1108*65034Sakito sc_request_sense(ctlr, slave, lun, buf, len)
110954004Sfujita 	int ctlr, slave, lun;
111054004Sfujita 	u_char *buf;
111154004Sfujita 	unsigned len;
111254004Sfujita {
1113*65034Sakito 	register struct sc_softc *hs = &sc_softc[ctlr];
111454004Sfujita 	volatile register struct scsidevice *hd =
111554004Sfujita 		(struct scsidevice *) hs->sc_hc->hp_addr;
111654004Sfujita 	static struct scsi_fmt_cdb req_cmd = { 6, CMD_REQUEST_SENSE };
111754004Sfujita 	int s, status, lock;
111854004Sfujita 
111954004Sfujita #ifdef REQ_DEBUG
1120*65034Sakito 	printf("sc_request_sense( %d, %d, %d, buf, %d) -- Start\n",
112154004Sfujita 	       ctlr, slave, lun, len);
112254004Sfujita #endif
112354004Sfujita 
112454004Sfujita         req_cmd.cdb[1] = lun;
112554004Sfujita         req_cmd.cdb[4] = len;
112654004Sfujita 
112754004Sfujita 	if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
112854004Sfujita 		return(0);
112954004Sfujita 
113054004Sfujita 	s = splbio();
113154004Sfujita 
113254004Sfujita 	hs->sc_flags  = 0;
113354004Sfujita 	hs->sc_phase  = ARB_SEL_PHASE;
113454004Sfujita 
113554004Sfujita 	hs->sc_cdb    = req_cmd.cdb;
113654004Sfujita 	hs->sc_cdblen = req_cmd.len;
113754004Sfujita 	hs->sc_buf    = buf;
113854004Sfujita 	hs->sc_len    = len;
113954004Sfujita 
114054004Sfujita 	hs->sc_stat   = 0;
114154004Sfujita 	hs->sc_msg[0] = 0;
114254004Sfujita 
114354004Sfujita 	lock = SC_IN_PROGRESS;
114454004Sfujita 	hs->sc_lock   = &lock;
114554004Sfujita 
114654004Sfujita 	issue_select(hd, slave, 0);
114754004Sfujita 
114854004Sfujita 	spl0();
114954004Sfujita 
115054004Sfujita 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
115154004Sfujita 		DELAY(10);
115254004Sfujita 
115354004Sfujita 	splbio();
115454004Sfujita 
115554004Sfujita 	hs->sc_flags  = 0;
115654004Sfujita 	hs->sc_phase  = BUS_FREE_PHASE;
115754004Sfujita 
115854004Sfujita 	hs->sc_cdb    = NULL;
115954004Sfujita 	hs->sc_cdblen = 0;
116054004Sfujita 	hs->sc_buf    = NULL;
116154004Sfujita 	hs->sc_len    = 0;
116254004Sfujita 	hs->sc_lock   = NULL;
116354004Sfujita 
116454004Sfujita 	status = hs->sc_stat;
116554004Sfujita 
116654004Sfujita 	hs->sc_stat   = 0;
116754004Sfujita 	hs->sc_msg[0] = 0;
116854004Sfujita 
116954004Sfujita 	splx(s);
117054004Sfujita 
117154004Sfujita 	if (lock == SC_IO_COMPLETE) {
117254004Sfujita #ifdef REQ_DEBUG
1173*65034Sakito 		printf("sc_request_sense: Status -- 0x%x\n", status);
117454004Sfujita #endif
117554004Sfujita 		return(status);
117654004Sfujita 	} else {
117754004Sfujita 		return(lock);
117854004Sfujita 	}
117954004Sfujita }
118054004Sfujita #endif
1181