xref: /csrg-svn/sys/luna68k/stand/sc.c (revision 63199)
157096Sakito /*
257096Sakito  * Copyright (c) 1992 OMRON Corporation.
3*63199Sbostic  * Copyright (c) 1992, 1993
4*63199Sbostic  *	The Regents of the University of California.  All rights reserved.
557096Sakito  *
657096Sakito  * This code is derived from software contributed to Berkeley by
757096Sakito  * OMRON Corporation.
857096Sakito  *
957096Sakito  * %sccs.include.redist.c%
1057096Sakito  *
11*63199Sbostic  *	@(#)sc.c	8.1 (Berkeley) 06/10/93
1257096Sakito  */
1357096Sakito 
1457096Sakito /*
1557096Sakito  * sc.c -- SCSI Protocole Controller (SPC)  driver
1657096Sakito  * remaked by A.Fujita, MAR-11-199
1757096Sakito  */
1857096Sakito 
1957096Sakito 
2057096Sakito #define NSC	1
2157096Sakito 
2257096Sakito #include <sys/param.h>
2357096Sakito #include <luna68k/dev/scsireg.h>
2457096Sakito #include <luna68k/stand/device.h>
2557096Sakito #include <luna68k/stand/scsivar.h>
2657096Sakito 
2757096Sakito #define SCSI_IPL	2
2857096Sakito #define SCSI_ID		7
2957096Sakito 
3057096Sakito int	scinit(), scstart(), scgo(), scintr(), scdone();
3157096Sakito void	screset();
3257096Sakito struct	driver scdriver = {
3357096Sakito 	scinit, "sc", scstart, scgo, scintr, scdone
3457096Sakito };
3557096Sakito 
3657096Sakito struct	scsi_softc scsi_softc[NSC];
3757096Sakito 
3857096Sakito /*
3957096Sakito  * Initialize SPC & Data Structure
4057096Sakito  */
4157096Sakito 
4257096Sakito int
scinit(hc)4357096Sakito scinit(hc)
4457096Sakito 	register struct hp_ctlr *hc;
4557096Sakito {
4657096Sakito 	register struct scsi_softc *hs = &scsi_softc[hc->hp_unit];
4757096Sakito 	register int i;
4857096Sakito 
4957096Sakito 	hc->hp_ipl    = SCSI_IPL;
5057096Sakito 	hs->sc_hc     = hc;
5157096Sakito 
5257096Sakito 	hs->sc_flags  = 0;
5357096Sakito 	hs->sc_phase  = BUS_FREE_PHASE;
5457096Sakito 	hs->sc_target = SCSI_ID;
5557096Sakito 
5657096Sakito 	hs->sc_cdb    = NULL;
5757096Sakito 	hs->sc_cdblen = 0;
5857096Sakito 	hs->sc_buf    = NULL;
5957096Sakito 	hs->sc_len    = 0;
6057096Sakito 	hs->sc_lock   = NULL;
6157096Sakito 
6257096Sakito 	hs->sc_stat   = 0;
6357096Sakito 	hs->sc_msg[0] = 0;
6457096Sakito 
6557096Sakito 	screset(hc->hp_unit);
6657096Sakito 	return(1);
6757096Sakito }
6857096Sakito 
6957096Sakito void
screset(unit)7057096Sakito screset(unit)
7157096Sakito 	register int unit;
7257096Sakito {
7357096Sakito 	register struct scsi_softc *hs = &scsi_softc[unit];
7457096Sakito 	volatile register struct scsidevice *hd =
7557096Sakito 				(struct scsidevice *)hs->sc_hc->hp_addr;
7657096Sakito 
7757096Sakito 	printf("sc%d: ", unit);
7857096Sakito 
7957096Sakito 	/*
8057096Sakito 	 * Disable interrupts then reset the FUJI chip.
8157096Sakito 	 */
8257096Sakito 
8357096Sakito 	hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
8457096Sakito 	hd->scsi_scmd = 0;
8557096Sakito 	hd->scsi_pctl = 0;
8657096Sakito 	hd->scsi_temp = 0;
8757096Sakito 	hd->scsi_tch  = 0;
8857096Sakito 	hd->scsi_tcm  = 0;
8957096Sakito 	hd->scsi_tcl  = 0;
9057096Sakito 	hd->scsi_ints = 0;
9157096Sakito 
9257096Sakito 	/* We can use Asynchronous Transfer only */
9357096Sakito 	printf("async");
9457096Sakito 
9557096Sakito 	/*
9657096Sakito 	 * Configure MB89352 with its SCSI address, all
9757096Sakito 	 * interrupts enabled & appropriate parity.
9857096Sakito 	 */
9957096Sakito 	hd->scsi_bdid = SCSI_ID;
10057096Sakito 	hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB|
10157096Sakito 			SCTL_PARITY_ENAB | SCTL_RESEL_ENAB |
10257096Sakito 			SCTL_INTR_ENAB;
10357096Sakito 	printf(", parity");
10457096Sakito 
10557096Sakito 	DELAY(400);
10657096Sakito 	hd->scsi_sctl &= ~SCTL_DISABLE;
10757096Sakito 
10857096Sakito 	printf(", scsi id %d\n", SCSI_ID);
10957096Sakito }
11057096Sakito 
11157096Sakito 
11257096Sakito /*
11357096Sakito  * SPC Arbitration/Selection routine
11457096Sakito  */
11557096Sakito 
11657096Sakito int
issue_select(hd,target)11757096Sakito issue_select(hd, target)
11857096Sakito 	volatile register struct scsidevice *hd;
11957096Sakito 	u_char target;
12057096Sakito {
12157096Sakito 	hd->scsi_pctl = 0;
12257096Sakito 	hd->scsi_temp = (1 << SCSI_ID) | (1 << target);
12357096Sakito 
12457096Sakito 	/* select timeout is hardcoded to 2ms */
12557096Sakito 	hd->scsi_tch = 0;
12657096Sakito 	hd->scsi_tcm = 32;
12757096Sakito 	hd->scsi_tcl = 4;
12857096Sakito 
12957096Sakito 	hd->scsi_scmd = SCMD_SELECT;
13057096Sakito 
13157096Sakito 	return (1);
13257096Sakito }
13357096Sakito 
13457096Sakito 
13557096Sakito /*
13657096Sakito  * SPC Manual Transfer routines
13757096Sakito  */
13857096Sakito 
13957096Sakito /* not yet */
14057096Sakito 
14157096Sakito 
14257096Sakito /*
14357096Sakito  * SPC Program Transfer routines
14457096Sakito  */
14557096Sakito 
14657096Sakito int
ixfer_start(hd,len,phase,wait)14757096Sakito ixfer_start(hd, len, phase, wait)
14857096Sakito 	volatile register struct scsidevice *hd;
14957096Sakito 	int len;
15057096Sakito 	u_char phase;
15157096Sakito 	register int wait;
15257096Sakito {
15357096Sakito 	hd->scsi_tch  = ((len & 0xff0000) >> 16);
15457096Sakito 	hd->scsi_tcm  = ((len & 0x00ff00) >>  8);
15557096Sakito 	hd->scsi_tcl  =  (len & 0x0000ff);
15657096Sakito 	hd->scsi_pctl = phase;
15757096Sakito 	hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
15857096Sakito }
15957096Sakito 
16057096Sakito int
ixfer_out(hd,len,buf)16157096Sakito ixfer_out(hd, len, buf)
16257096Sakito 	volatile register struct scsidevice *hd;
16357096Sakito 	int len;
16457096Sakito 	register u_char *buf;
16557096Sakito {
16657096Sakito 	for(; len > 0; len--) {
16757096Sakito 		while (hd->scsi_ssts & SSTS_DREG_FULL) {
16857096Sakito 			DELAY(5);
16957096Sakito 		}
17057096Sakito 		hd->scsi_dreg = *buf++;
17157096Sakito 	}
17257096Sakito }
17357096Sakito 
17457096Sakito int
ixfer_in(hd,len,buf)17557096Sakito ixfer_in(hd, len, buf)
17657096Sakito 	volatile register struct scsidevice *hd;
17757096Sakito 	int len;
17857096Sakito 	register u_char *buf;
17957096Sakito {
18057096Sakito 	for (; len > 0; len--) {
18157096Sakito 		int i;
18257096Sakito 		while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
18357096Sakito 			DELAY(5);
18457096Sakito 		}
18557096Sakito 		*buf++ = hd->scsi_dreg;
18657096Sakito 	}
18757096Sakito }
18857096Sakito 
18957096Sakito 
19057096Sakito /*
19157096Sakito  * SPC drive routines
19257096Sakito  */
19357096Sakito 
19457096Sakito int
scrun(ctlr,slave,cdb,cdblen,buf,len,lock)19557096Sakito scrun(ctlr, slave, cdb, cdblen, buf, len, lock)
19657096Sakito 	int ctlr, slave;
19757096Sakito 	u_char *cdb;
19857096Sakito 	int cdblen;
19957096Sakito 	u_char *buf;
20057096Sakito 	int len;
20157096Sakito 	int *lock;
20257096Sakito {
20357096Sakito 	register struct scsi_softc *hs = &scsi_softc[ctlr];
20457096Sakito 	volatile register struct scsidevice *hd =
20557096Sakito 		(struct scsidevice *) hs->sc_hc->hp_addr;
20657096Sakito 
20757096Sakito 	if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
20857096Sakito 		return(0);
20957096Sakito 
21057096Sakito 	hs->sc_flags  = 0;
21157096Sakito 	hs->sc_phase  = ARB_SEL_PHASE;
21257096Sakito 	hs->sc_target = slave;
21357096Sakito 
21457096Sakito 	hs->sc_cdb    = cdb;
21557096Sakito 	hs->sc_cdblen = cdblen;
21657096Sakito 	hs->sc_buf    = buf;
21757096Sakito 	hs->sc_len    = len;
21857096Sakito 	hs->sc_lock   = lock;
21957096Sakito 
22057096Sakito 	hs->sc_stat   = 0;
22157096Sakito 	hs->sc_msg[0] = 0;
22257096Sakito 
22357096Sakito 	*(hs->sc_lock) = SC_IN_PROGRESS;
22457096Sakito 	issue_select(hd, hs->sc_target);
22557096Sakito 
22657096Sakito 	return(1);
22757096Sakito }
22857096Sakito 
22957096Sakito int
scfinish(ctlr)23057096Sakito scfinish(ctlr)
23157096Sakito 	int ctlr;
23257096Sakito {
23357096Sakito 	register struct scsi_softc *hs = &scsi_softc[ctlr];
23457096Sakito 	int status = hs->sc_stat;
23557096Sakito 
23657096Sakito 	hs->sc_flags  = 0;
23757096Sakito 	hs->sc_phase  = BUS_FREE_PHASE;
23857096Sakito 	hs->sc_target = SCSI_ID;
23957096Sakito 
24057096Sakito 	hs->sc_cdb    = NULL;
24157096Sakito 	hs->sc_cdblen = 0;
24257096Sakito 	hs->sc_buf    = NULL;
24357096Sakito 	hs->sc_len    = 0;
24457096Sakito 	hs->sc_lock   = NULL;
24557096Sakito 
24657096Sakito 	hs->sc_stat   = 0;
24757096Sakito 	hs->sc_msg[0] = 0;
24857096Sakito 
24957096Sakito 	return(status);
25057096Sakito }
25157096Sakito 
25257096Sakito int
scabort(hs,hd)25357096Sakito scabort(hs, hd)
25457096Sakito 	register struct scsi_softc *hs;
25557096Sakito 	volatile register struct scsidevice *hd;
25657096Sakito {
25757096Sakito 	int len;
25857096Sakito 	u_char junk;
25957096Sakito 
26057096Sakito 	printf("sc%d: abort  phase=0x%x, ssts=0x%x, ints=0x%x\n",
26157096Sakito 		hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts,
26257096Sakito 		hd->scsi_ints);
26357096Sakito 
26457096Sakito 	if (hd->scsi_ints != 0)
26557096Sakito 		hd->scsi_ints = hd->scsi_ints;
26657096Sakito 
26757096Sakito 	if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
26857096Sakito 		/* no longer connected to scsi target */
26957096Sakito 		return;
27057096Sakito 
27157096Sakito 	/* get the number of bytes remaining in current xfer + fudge */
27257096Sakito 	len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
27357096Sakito 
27457096Sakito 	/* for that many bus cycles, try to send an abort msg */
27557096Sakito 	for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) {
27657096Sakito 		hd->scsi_scmd = SCMD_SET_ATN;
27757096Sakito 
27857096Sakito 		while ((hd->scsi_psns & PSNS_REQ) == 0) {
27957096Sakito 			if (! (hd->scsi_ssts & SSTS_INITIATOR))
28057096Sakito 				goto out;
28157096Sakito 			DELAY(1);
28257096Sakito 		}
28357096Sakito 
28457096Sakito 		if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)
28557096Sakito 			hd->scsi_scmd = SCMD_RST_ATN;
28657096Sakito 		hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE;
28757096Sakito 
28857096Sakito 		if (hd->scsi_psns & PHASE_IO) {
28957096Sakito 			/* one of the input phases - read & discard a byte */
29057096Sakito 			hd->scsi_scmd = SCMD_SET_ACK;
29157096Sakito 			while (hd->scsi_psns & PSNS_REQ)
29257096Sakito 				DELAY(1);
29357096Sakito 			junk = hd->scsi_temp;
29457096Sakito 		} else {
29557096Sakito 			/* one of the output phases - send an abort msg */
29657096Sakito 			hd->scsi_temp = MSG_ABORT;
29757096Sakito 			hd->scsi_scmd = SCMD_SET_ACK;
29857096Sakito 			while (hd->scsi_psns & PSNS_REQ)
29957096Sakito 				DELAY(1);
30057096Sakito 		}
30157096Sakito 
30257096Sakito 		hd->scsi_scmd = SCMD_RST_ACK;
30357096Sakito 	}
30457096Sakito out:
30557096Sakito 	/*
30657096Sakito 	 * Either the abort was successful & the bus is disconnected or
30757096Sakito 	 * the device didn't listen.  If the latter, announce the problem.
30857096Sakito 	 * Either way, reset the card & the SPC.
30957096Sakito 	 */
31057096Sakito 	if (len < 0 && hs)
31157096Sakito 		printf("sc%d: abort failed.  phase=0x%x, ssts=0x%x\n",
31257096Sakito 			hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts);
31357096Sakito }
31457096Sakito 
31557096Sakito 
31657096Sakito /*
31757096Sakito  * SCSI Command Handler
31857096Sakito  */
31957096Sakito 
32057096Sakito int
scsi_test_unit_rdy(ctlr,slave,unit)32157096Sakito scsi_test_unit_rdy(ctlr, slave, unit)
32257096Sakito 	int ctlr, slave, unit;
32357096Sakito {
32457096Sakito 	static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
32557096Sakito 	int status, lock;
32657096Sakito 
32757096Sakito #ifdef DEBUG
32857096Sakito 	printf("scsi_test_unit_rdy( %d, %d, %d): Start\n", ctlr, slave, unit);
32957096Sakito #endif
33057096Sakito 
33157096Sakito 	cdb.lun = unit;
33257096Sakito 
33357096Sakito 	if (!(scrun(ctlr, slave, &cdb, 6, (u_char *) 0, 0, &lock))) {
33457096Sakito #ifdef DEBUG
33557096Sakito 		printf("scsi_test_unit_rdy: Command Transfer Failed.\n");
33657096Sakito #endif
33757096Sakito 		return(-1);
33857096Sakito 	}
33957096Sakito 
34057096Sakito 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
34157096Sakito 		DELAY(10);
34257096Sakito 
34357096Sakito 	status = scfinish(ctlr);
34457096Sakito 
34557096Sakito 	if (lock == SC_IO_COMPLETE) {
34657096Sakito #ifdef DEBUG
34757096Sakito 		printf("scsi_test_unit_rdy: Status -- 0x%x\n", status);
34857096Sakito #endif
34957096Sakito 		return(status);
35057096Sakito 	} else {
35157096Sakito 		return(lock);
35257096Sakito 	}
35357096Sakito }
35457096Sakito 
35557096Sakito int
scsi_request_sense(ctlr,slave,unit,buf,len)35657096Sakito scsi_request_sense(ctlr, slave, unit, buf, len)
35757096Sakito 	int ctlr, slave, unit;
35857096Sakito 	u_char *buf;
35957096Sakito 	unsigned len;
36057096Sakito {
36157096Sakito 	static struct scsi_cdb6 cdb = {	CMD_REQUEST_SENSE };
36257096Sakito 	int status, lock;
36357096Sakito 
36457096Sakito #ifdef DEBUG
36557096Sakito 	printf("scsi_request_sense: Start\n");
36657096Sakito #endif
36757096Sakito 
36857096Sakito 	/* Request Sense$N>l9g!"E>Aw$5$l$k%G!<%?D9$O%?!<%2368H$K0MB8$7!"        */
36957096Sakito 	/* %;%s%9%G!<%?$N#8/usr/home/csrg/sccs/sys/luna68k/stand/SCCS/s.sc.c$%HL\$NAddtional Sens Length$K$h$jF0E*$K7hDj$9$k!#*/
37057096Sakito 	/* $3$3$G$O%G!<%?!<E>Aw?t$rcdb$NAllocation Length$K:GDcD9$G$"$k#8/usr/home/csrg/sccs/sys/luna68k/stand/SCCS/s.sc.c$%H */
37157096Sakito 	/* $r8GDj$7$F!"#S#P#C$N=hM}%7!<%1%s%9$rJx$5$J$$$h$&$K$7$F$$$k!#         */
37257096Sakito 
373*63199Sbostic 	/* %F!<@(#)sc.c	8.1f%K373H$N>uBV$rD4$Y$k$?$a!"Addtional Sens Field$r%"%/%;%9$9$k */
374*63199Sbostic 	/* I,MW$,$"$k$N$G06/10/93P%$%98.1i%$%PB&$Glen$r7hDj$9$k$3$H$K$9$k            */
37557096Sakito 
37657096Sakito 	cdb.lun = unit;
37757096Sakito 	cdb.len = len;
37857096Sakito 
37957096Sakito 	if (!(scrun(ctlr, slave, &cdb, 6, buf, len, &lock))) {
38057096Sakito #ifdef DEBUG
38157096Sakito 		printf("scsi_request_sense: Command Transfer Failed.\n");
38257096Sakito #endif
38357096Sakito 		return(-1);
38457096Sakito 	}
38557096Sakito 
38657096Sakito 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
38757096Sakito 		DELAY(10);
38857096Sakito 
38957096Sakito 	status = scfinish(ctlr);
39057096Sakito 
39157096Sakito 	if (lock == SC_IO_COMPLETE) {
39257096Sakito #ifdef DEBUG
39357096Sakito 		printf("scsi_request_sense: Status -- 0x%x\n", status);
39457096Sakito #endif
39557096Sakito 		return(status);
39657096Sakito 	} else {
39757096Sakito 		return(lock);
39857096Sakito 	}
39957096Sakito }
40057096Sakito 
40157096Sakito int
scsi_immed_command(ctlr,slave,unit,cdb,buf,len)40257096Sakito scsi_immed_command(ctlr, slave, unit, cdb, buf, len)
40357096Sakito 	int ctlr, slave, unit;
40457096Sakito 	struct scsi_fmt_cdb *cdb;
40557096Sakito 	u_char *buf;
40657096Sakito 	unsigned len;
40757096Sakito {
40857096Sakito 	int lock, status;
40957096Sakito 
41057096Sakito #ifdef DEBUG
41157096Sakito 	printf("scsi_immed_command( %d, %d, %d, cdb(%d), buf, %d): Start\n",
41257096Sakito 	       ctlr, slave, unit, cdb->len, len);
41357096Sakito #endif
41457096Sakito 
41557096Sakito 	cdb->cdb[1] |= unit << 5;
41657096Sakito 
41757096Sakito 	if (!(scrun(ctlr, slave, &cdb->cdb[0], cdb->len, buf, len, &lock))) {
41857096Sakito #ifdef DEBUG
41957096Sakito 		printf("scsi_immed_command: Command Transfer Failed.\n");
42057096Sakito #endif
42157096Sakito 		return(-1);
42257096Sakito 	}
42357096Sakito 
42457096Sakito 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
42557096Sakito 		DELAY(10);
42657096Sakito 
42757096Sakito 	status = scfinish(ctlr);
42857096Sakito 
42957096Sakito 	if (lock == SC_IO_COMPLETE) {
43057096Sakito #ifdef DEBUG
43157096Sakito 		printf("scsi_immed_command: Status -- 0x%x\n", status);
43257096Sakito #endif
43357096Sakito 		return(status);
43457096Sakito 	} else {
43557096Sakito 		return(lock);
43657096Sakito 	}
43757096Sakito }
43857096Sakito 
43957096Sakito int
scsi_format_unit(ctlr,slave,unit)44057096Sakito scsi_format_unit(ctlr, slave, unit)
44157096Sakito 	int ctlr, slave, unit;
44257096Sakito {
44357096Sakito 	static struct scsi_cdb6 cdb = { CMD_FORMAT_UNIT, 0, 0, 0, 0, 0 };
44457096Sakito 	int status, lock, count = 0;
44557096Sakito 
44657096Sakito #ifdef DEBUG
44757096Sakito 	printf("scsi_format_unit( %d, %d, %d): Start\n", ctlr, slave, unit);
44857096Sakito #endif
44957096Sakito 
45057096Sakito 	cdb.lun = unit;
45157096Sakito 
45257096Sakito 	if (!(scrun(ctlr, slave, &cdb, 6, (u_char *) 0, 0, &lock))) {
45357096Sakito #ifdef DEBUG
45457096Sakito 		printf("scsi_format_unit: Command Transfer Failed.\n");
45557096Sakito #endif
45657096Sakito 		return(-1);
45757096Sakito 	}
45857096Sakito 
45957096Sakito 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) {
46057096Sakito 		DELAY(1000000);
46157096Sakito #ifdef DEBUG
46257096Sakito 		if ((count % 60) == 0)
46357096Sakito 			printf("scsi_format_unit: %d\n");
46457096Sakito #endif
46557096Sakito 	}
46657096Sakito 
46757096Sakito 	status = scfinish(ctlr);
46857096Sakito 
46957096Sakito 	if (lock == SC_IO_COMPLETE) {
47057096Sakito #ifdef DEBUG
47157096Sakito 		printf("scsi_format_unit: Status -- 0x%x\n", status);
47257096Sakito #endif
47357096Sakito 		return(status);
47457096Sakito 	} else {
47557096Sakito 		return(lock);
47657096Sakito 	}
47757096Sakito }
47857096Sakito 
47957096Sakito 
48057096Sakito /*
48157096Sakito  * ????
48257096Sakito  */
48357096Sakito 
48457096Sakito int
scstart()48557096Sakito scstart()
48657096Sakito {
48757096Sakito }
48857096Sakito 
48957096Sakito int
scgo()49057096Sakito scgo()
49157096Sakito {
49257096Sakito }
49357096Sakito 
49457096Sakito int
scdone()49557096Sakito scdone()
49657096Sakito {
49757096Sakito }
49857096Sakito 
49957096Sakito 
50057096Sakito /*
50157096Sakito  * Interrupt Routine
50257096Sakito  */
50357096Sakito 
50457096Sakito int
scintr()50557096Sakito scintr()
50657096Sakito {
50757096Sakito 	register struct scsi_softc *hs;
50857096Sakito 	volatile register struct scsidevice *hd;
50957096Sakito 	register u_char ints, temp;
51057096Sakito 	register int i;
51157096Sakito 	u_char *buf;
51257096Sakito 	int len;
51357096Sakito 
51457096Sakito 	for (i = 0; i < NSC; i++) {
51557096Sakito 		hs = &scsi_softc[i];
51657096Sakito 		hd = (struct scsidevice *) hs->sc_hc->hp_addr;
51757096Sakito 		if ((ints = hd->scsi_ints) != 0)
51857096Sakito 			goto get_intr;
51957096Sakito 	}
52057096Sakito 
52157096Sakito 	/* Unknown Interrupt occured */
52257096Sakito 	return;
52357096Sakito 
52457096Sakito 
52557096Sakito 	/*
52657096Sakito 	 * Interrupt
52757096Sakito 	 */
52857096Sakito 
52957096Sakito  get_intr:
53057096Sakito #ifdef DEBUG
53157096Sakito 	printf("scintr: INTS 0x%x, SSTS 0x%x,  PCTL 0x%x,  PSNS 0x%x    0x%x\n",
53257096Sakito 	        ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns,
53357096Sakito 	        hs->sc_phase);
53457096Sakito #endif
53557096Sakito 	if (ints & INTS_RESEL) {
53657096Sakito 		if (hs->sc_phase == BUS_FREE_PHASE) {
53757096Sakito 			temp = hd->scsi_temp & ~(1 << SCSI_ID);
53857096Sakito 			for (i = 0; temp != 1; i++) {
53957096Sakito 				temp >>= 1;
54057096Sakito 			}
54157096Sakito 			hs->sc_target = i;
54257096Sakito 			*(hs->sc_lock) = SC_IN_PROGRESS;
54357096Sakito 		} else
54457096Sakito 			goto abort;
54557096Sakito 	} else if (ints & INTS_DISCON) {
54657096Sakito 		if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) || (hs->sc_msg[0] == MSG_DISCONNECT)) {
54757096Sakito 			hs->sc_phase  = BUS_FREE_PHASE;
54857096Sakito 			hs->sc_target = SCSI_ID;
54957096Sakito 			if (hs->sc_msg[0] == MSG_CMD_COMPLETE)
55057096Sakito 				/* SCSI IO complete */
55157096Sakito 				*(hs->sc_lock) = SC_IO_COMPLETE;
55257096Sakito 			else
55357096Sakito 				/* Cisconnected from Target */
55457096Sakito 				*(hs->sc_lock) = SC_DISCONNECTED;
55557096Sakito 			hd->scsi_ints = ints;
55657096Sakito 			return;
55757096Sakito 		} else
55857096Sakito 			goto abort;
55957096Sakito 	} else if (ints & INTS_CMD_DONE) {
56057096Sakito 		if (hs->sc_phase == BUS_FREE_PHASE)
56157096Sakito 			goto abort;
56257096Sakito 		else if (hs->sc_phase == MESG_IN_PHASE) {
56357096Sakito 			hd->scsi_scmd = SCMD_RST_ACK;
56457096Sakito 			hd->scsi_ints = ints;
56557096Sakito 			hs->sc_phase  = hd->scsi_psns & PHASE;
56657096Sakito 			return;
56757096Sakito 		}
56857096Sakito 		if (hs->sc_flags & SC_SEL_TIMEOUT)
56957096Sakito 			hs->sc_flags &= ~SC_SEL_TIMEOUT;
57057096Sakito 	} else if (ints & INTS_SRV_REQ) {
57157096Sakito 		if (hs->sc_phase != MESG_IN_PHASE)
57257096Sakito 			goto abort;
57357096Sakito 	} else if (ints & INTS_TIMEOUT) {
57457096Sakito 		if (hs->sc_phase == ARB_SEL_PHASE) {
57557096Sakito 			if (hs->sc_flags & SC_SEL_TIMEOUT) {
57657096Sakito 				hs->sc_flags &= ~SC_SEL_TIMEOUT;
57757096Sakito 				hs->sc_phase  = BUS_FREE_PHASE;
57857096Sakito 				hs->sc_target = SCSI_ID;
57957096Sakito 				/* Such SCSI Device is not conected. */
58057096Sakito 				*(hs->sc_lock) = SC_DEV_NOT_FOUND;
58157096Sakito 				hd->scsi_ints = ints;
58257096Sakito 				return;
58357096Sakito 			} else {
58457096Sakito 				/* wait more 250 usec */
58557096Sakito 				hs->sc_flags |= SC_SEL_TIMEOUT;
58657096Sakito 				hd->scsi_temp = 0;
58757096Sakito 				hd->scsi_tch  = 0;
58857096Sakito 				hd->scsi_tcm  = 0x06;
58957096Sakito 				hd->scsi_tcl  = 0x40;
59057096Sakito 				hd->scsi_ints = ints;
59157096Sakito 				return;
59257096Sakito 			}
59357096Sakito 		} else
59457096Sakito 			goto abort;
59557096Sakito 	} else
59657096Sakito 		goto abort;
59757096Sakito 
59857096Sakito 	hd->scsi_ints = ints;
59957096Sakito 
60057096Sakito 	/*
60157096Sakito 	 * Next SCSI Transfer
60257096Sakito 	 */
60357096Sakito 
60457096Sakito 	while ((hd->scsi_psns & PSNS_REQ) == 0) {
60557096Sakito 		DELAY(1);
60657096Sakito 	}
60757096Sakito 
60857096Sakito 	hs->sc_phase = hd->scsi_psns & PHASE;
60957096Sakito 
61057096Sakito 	if ((hs->sc_phase == DATA_OUT_PHASE) || (hs->sc_phase == DATA_IN_PHASE)) {
61157096Sakito 		len = hs->sc_len;
61257096Sakito 		buf = hs->sc_buf;
61357096Sakito 	} else if (hs->sc_phase == CMD_PHASE) {
61457096Sakito 		len = hs->sc_cdblen;
61557096Sakito 		buf = hs->sc_cdb;
61657096Sakito 	} else if (hs->sc_phase == STATUS_PHASE) {
61757096Sakito 		len = 1;
61857096Sakito 		buf = &hs->sc_stat;
61957096Sakito 	} else {
62057096Sakito 		len = 1;
62157096Sakito 		buf = hs->sc_msg;
62257096Sakito 	}
62357096Sakito 
62457096Sakito 	ixfer_start(hd, len, hs->sc_phase, 0);
62557096Sakito 	if (hs->sc_phase & PHASE_IO)
62657096Sakito 		ixfer_in(hd, len, buf);
62757096Sakito 	else
62857096Sakito 		ixfer_out(hd, len, buf);
62957096Sakito 
63057096Sakito 	return;
63157096Sakito 
63257096Sakito 	/*
63357096Sakito 	 * SCSI Abort
63457096Sakito 	 */
63557096Sakito  abort:
63657096Sakito 	/* SCSI IO failed */
63757096Sakito 	scabort(hs, hd);
63857096Sakito 	hd->scsi_ints = ints;
63957096Sakito 	*(hs->sc_lock) = SC_IO_FAILED;
64057096Sakito 	return;
64157096Sakito }
642