Subject: MI 53c700 SCSI driver
To: None <tech-kern@netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: tech-kern
Date: 04/05/2003 01:43:14
Hi,

The following patch is the MI NCR 53c700 SCSI driver.
This "oosiop" driver was originally written by Shuichiro URATA
for arc port, and then it was modified by me to make it work
also on hp700.

This driver has been tested on my NEC Express5800/240 with 53c700-66
for several months, and also tested on HP9000 735/125 with 53c700
(though current hp700 port has been broken since SA merge).
Both sync transfer and disconnect/reselect work fine,
but tagged queuing is not implemented yet.

Actually it's better for oosiop to share some code with 53c710
(osiop) driver, but it will happen eventually after osiop driver
(which is based on the old amiga's siop driver) is more cleaned up.

I'll commit this unless someone objects.
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp

Index: conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.604
diff -u -r1.604 files
--- conf/files	2003/03/16 11:50:27	1.604
+++ conf/files	2003/04/04 12:45:48
@@ -385,6 +385,10 @@
 attach	lfmport at lfmiop
 file	dev/ic/lfmiop.c			lfmiop
 
+# Symbios/NCR 53c700 SCSI controllers
+device	oosiop: scsi
+file	dev/ic/oosiop.c			oosiop
+
 # Symbios/NCR 53c710 SCSI controllers
 #
 device	osiop: scsi
Index: arch/arc/conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/conf/GENERIC,v
retrieving revision 1.82
diff -u -r1.82 GENERIC
--- arch/arc/conf/GENERIC	2003/02/27 19:22:39	1.82
+++ arch/arc/conf/GENERIC	2003/04/04 12:45:49
@@ -193,13 +193,11 @@
 asc0		at jazzio?			# NCR53C9x SCSI
 scsibus* 	at asc?
 
-osiop0		at jazzio? flags 0x00000	# NCR53C710 SCSI
-osiop1		at jazzio? flags 0x00000
+osiop*		at jazzio? flags 0x00000	# NCR53C710 SCSI
 scsibus* 	at osiop?
 
-#oosiop0 	at jazzio?			# NCR53C700 SCSI
-#oosiop1 	at jazzio?
-#scsibus* 	at oosiop?
+oosiop* 	at jazzio?			# NCR53C700 SCSI
+scsibus* 	at oosiop?
 
 #### ISA bus devices
 
Index: arch/arc/conf/files.arc
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/conf/files.arc,v
retrieving revision 1.41
diff -u -r1.41 files.arc
--- arch/arc/conf/files.arc	2002/11/30 19:23:46	1.41
+++ arch/arc/conf/files.arc	2003/04/04 12:49:26
@@ -168,6 +168,10 @@
 attach	osiop at jazzio with osiop_jazzio
 file	arch/arc/jazz/osiop_jazzio.c	osiop_jazzio
 
+#	NCR53C700 SCSI I/O processor on Jazz-Internal bus
+attach	oosiop at jazzio with oosiop_jazzio
+file	arch/arc/jazz/oosiop_jazzio.c		oosiop_jazzio
+
 #	Floppy disk controller on Jazz-internal bus
 device	fdc {drive = -1}
 file	arch/arc/jazz/fd.c		fdc	needs-flag
Index: arch/hp700/conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/hp700/conf/GENERIC,v
retrieving revision 1.12
diff -u -r1.12 GENERIC
--- arch/hp700/conf/GENERIC	2003/02/27 19:22:40	1.12
+++ arch/hp700/conf/GENERIC	2003/04/04 16:09:31
@@ -286,7 +286,8 @@
 # SCSI Controllers and Devices
 
 # GSC SCSI controllers
-osiop*	at gsc? flags 0xffff		# NCR 53c700 or NCR 53c710
+oosiop*	at gsc?				# NCR 53c700
+osiop*	at gsc? flags 0x00000		# NCR 53c710
 #siop*	at gsc? 			# NCR 53c720 (Fast/Wide)
 
 # EISA SCSI controllers
Index: arch/hp700/conf/files.hp700
===================================================================
RCS file: /cvsroot/src/sys/arch/hp700/conf/files.hp700,v
retrieving revision 1.4
diff -u -r1.4 files.hp700
--- arch/hp700/conf/files.hp700	2002/11/28 05:53:23	1.4
+++ arch/hp700/conf/files.hp700	2003/04/04 12:49:26
@@ -138,11 +138,14 @@
 attach	ie at gsc with ie_gsc
 file	arch/hp700/gsc/if_ie_gsc.c	ie_gsc
 
-attach	siop at gsc
-file	arch/hp700/gsc/siop_gsc.c	siop
+attach	siop at gsc with siop_gsc
+file	arch/hp700/gsc/siop_gsc.c	siop_gsc
 
 attach	osiop at gsc with osiop_gsc
-file	arch/hp700/gsc/osiop_gsc.c	osiop
+file	arch/hp700/gsc/osiop_gsc.c	osiop_gsc
+
+attach	oosiop at gsc with oosiop_gsc
+file	arch/hp700/gsc/oosiop_gsc.c	oosiop_gsc
 
 device	hil: tty
 attach	hil at gsc
Index: arch/hp700/gsc/osiop_gsc.c
===================================================================
RCS file: /cvsroot/src/sys/arch/hp700/gsc/osiop_gsc.c,v
retrieving revision 1.6
diff -u -r1.6 osiop_gsc.c
--- arch/hp700/gsc/osiop_gsc.c	2002/10/02 05:17:50	1.6
+++ arch/hp700/gsc/osiop_gsc.c	2003/04/04 12:45:51
@@ -2,7 +2,7 @@
 
 /*
  * Copyright (c) 2001 Matt Fredette.  All rights reserved.
- * Copyright (c) 2001 Izumi Tsutsui.  All rights reserved.
+ * Copyright (c) 2001,2002 Izumi Tsutsui.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -103,12 +103,11 @@
 	int rv = 1;
 
 	if (ga->ga_type.iodc_type != HPPA_TYPE_FIO ||
-	    (ga->ga_type.iodc_sv_model != HPPA_FIO_GSCSI &&
-	     ga->ga_type.iodc_sv_model != HPPA_FIO_SCSI))
+	    (ga->ga_type.iodc_sv_model != HPPA_FIO_GSCSI))
 		return 0;
 
 	if (bus_space_map(ga->ga_iot, ga->ga_hpa, 
-			  OSIOP_GSC_OFFSET + OSIOP_NREGS, 0, &ioh))
+	    OSIOP_GSC_OFFSET + OSIOP_NREGS, 0, &ioh))
 		return 0;
 
 
@@ -128,27 +127,18 @@
 	sc->sc_bst = ga->ga_iot;
 	sc->sc_dmat = ga->ga_dmatag;
 	if (bus_space_map(sc->sc_bst, ga->ga_hpa,
-			  OSIOP_GSC_OFFSET + OSIOP_NREGS, 0, &ioh))
+	    OSIOP_GSC_OFFSET + OSIOP_NREGS, 0, &ioh))
 		panic("osiop_gsc_attach: couldn't map I/O ports");
 	if (bus_space_subregion(sc->sc_bst, ioh, 
-				OSIOP_GSC_OFFSET, OSIOP_NREGS, &sc->sc_reg))
+	    OSIOP_GSC_OFFSET, OSIOP_NREGS, &sc->sc_reg))
 		panic("osiop_gsc_attach: couldn't get chip ports");
 
 	sc->sc_clock_freq = ga->ga_ca.ca_pdc_iodc_read->filler2[14] / 1000000;
 	if (!sc->sc_clock_freq)
 		sc->sc_clock_freq = 50;
 
-	if (ga->ga_ca.ca_type.iodc_sv_model == HPPA_FIO_GSCSI) {
-		sc->sc_rev = OSIOP_VARIANT_NCR53C710;
-		sc->sc_byteorder = OSIOP_BYTEORDER_NATIVE;
-		sc->sc_ctest7 = 0; /* | OSIOP_CTEST7_TT1 */
-		sc->sc_dcntl = OSIOP_DCNTL_EA;
-	} else {
-		sc->sc_rev = OSIOP_VARIANT_NCR53C700;
-		sc->sc_byteorder = OSIOP_BYTEORDER_NONNATIVE;
-		sc->sc_ctest7 = 0;
-		sc->sc_dcntl = 0;
-	}
+	sc->sc_ctest7 = 0; /* | OSIOP_CTEST7_TT1 */
+	sc->sc_dcntl = OSIOP_DCNTL_EA;
 
 	sc->sc_flags = 0;
 	sc->sc_id = ga->ga_scsi_target;
@@ -170,9 +160,8 @@
 #endif /* OSIOP_DEBUG */
 	osiop_attach(sc);
 
-	(void) hp700_intr_establish(&sc->sc_dev, IPL_BIO,
-				    osiop_gsc_intr, sc,
-				    ga->ga_int_reg, ga->ga_irq);
+	(void)hp700_intr_establish(&sc->sc_dev, IPL_BIO,
+	    osiop_gsc_intr, sc, ga->ga_int_reg, ga->ga_irq);
 }
 
 /*
Index: dev/microcode/siop/Makefile
===================================================================
RCS file: /cvsroot/src/sys/dev/microcode/siop/Makefile,v
retrieving revision 1.5
diff -u -r1.5 Makefile
--- dev/microcode/siop/Makefile	2002/04/21 22:52:06	1.5
+++ dev/microcode/siop/Makefile	2003/04/04 15:34:34
@@ -20,4 +20,4 @@
 	./${PROG} osiop.ss -p osiop.out
 
 oosiop.out: oosiop.ss ${PROG}
-	./${PROG} oosiop.ss -o oosiop.out
+	./${PROG} oosiop.ss -p oosiop.out
Index: dev/microcode/siop/ncr53cxxx.c
===================================================================
RCS file: /cvsroot/src/sys/dev/microcode/siop/ncr53cxxx.c,v
retrieving revision 1.10
diff -u -r1.10 ncr53cxxx.c
--- dev/microcode/siop/ncr53cxxx.c	2002/04/21 22:40:10	1.10
+++ dev/microcode/siop/ncr53cxxx.c	2003/04/04 15:43:06
@@ -188,8 +188,9 @@
 	{"temp3",	{0x1f, 0x1f, 0x1f, 0x1f, 0x1f}},
 	{"dfifo",	{0x20, 0x20, 0x20, 0x20, 0x20}},
 	{"istat", 	{0x21, 0x21, 0x14, 0x14, 0x14}},
-	{"ctest8",	{  -1, 0x22,   -1,   -1,   -1}},
+	{"ctest8",	{0x22, 0x22,   -1,   -1,   -1}},
 	{"lcrc",	{  -1, 0x23,   -1,   -1,   -1}},
+	{"ctest9",	{0x23,   -1,   -1,   -1,   -1}},
 	{"dbc0",	{0x24, 0x24, 0x24, 0x24, 0x24}},
 	{"dbc1",	{0x25, 0x25, 0x25, 0x25, 0x25}},
 	{"dbc2",	{0x26, 0x26, 0x26, 0x26, 0x26}},
@@ -210,10 +211,10 @@
 	{"scratch1",	{  -1, 0x35,   -1,   -1,   -1}},
 	{"scratch2",	{  -1, 0x36,   -1,   -1,   -1}},
 	{"scratch3",	{  -1, 0x37,   -1,   -1,   -1}},
-	{"scratcha0",	{  -1,   -1, 0x34, 0x34, 0x34}},
-	{"scratcha1",	{  -1,   -1, 0x35, 0x35, 0x35}},
-	{"scratcha2",	{  -1,   -1, 0x36, 0x36, 0x36}},
-	{"scratcha3",	{  -1,   -1, 0x37, 0x37, 0x37}},
+	{"scratcha0",	{0x10,   -1, 0x34, 0x34, 0x34}},
+	{"scratcha1",	{0x11,   -1, 0x35, 0x35, 0x35}},
+	{"scratcha2",	{0x12,   -1, 0x36, 0x36, 0x36}},
+	{"scratcha3",	{0x13,   -1, 0x37, 0x37, 0x37}},
 	{"dmode",	{0x34, 0x38, 0x38, 0x38, 0x38}},
 	{"dien",	{0x39, 0x39, 0x39, 0x39, 0x39}},
 	{"dwt",		{0x3a, 0x3a, 0x3a,   -1,   -1}},
@@ -245,10 +246,10 @@
 	{"sodl1",	{  -1,   -1, 0x55,   -1, 0x55}},
 	{"sbdl0",	{  -1,   -1, 0x58, 0x58, 0x58}},
 	{"sbdl1",	{  -1,   -1, 0x59,   -1, 0x59}},
-	{"scratchb0",	{  -1,   -1, 0x5c, 0x5c, 0x5c}},
-	{"scratchb1",	{  -1,   -1, 0x5d, 0x5d, 0x5d}},
-	{"scratchb2",	{  -1,   -1, 0x5e, 0x5e, 0x5e}},
-	{"scratchb3",	{  -1,   -1, 0x5f, 0x5f, 0x5f}},
+	{"scratchb0",	{0x3c,   -1, 0x5c, 0x5c, 0x5c}},
+	{"scratchb1",	{0x3d,   -1, 0x5d, 0x5d, 0x5d}},
+	{"scratchb2",	{0x3e,   -1, 0x5e, 0x5e, 0x5e}},
+	{"scratchb3",	{0x3f,   -1, 0x5f, 0x5f, 0x5f}},
 	{"scratchc0",	{  -1,   -1,   -1,   -1, 0x60}},
 	{"scratchc1",	{  -1,   -1,   -1,   -1, 0x61}},
 	{"scratchc2",	{  -1,   -1,   -1,   -1, 0x62}},
@@ -1037,10 +1038,11 @@
 			errout ("Expected SELECT or RESELECT");
 		++i;
 		if (reserved ("rel", i)) {
+#if 0 /* driver will fix relative dsps to absolute */
 			if (arch < ARCH710) {
 				errout ("Wrong arch for relative dsps");
-				return;
 			}
+#endif
 			i += 2;
 			inst1 = evaluate (i) - dsps - 8;
 			inst0 |= 0x04000000;
@@ -1148,10 +1150,11 @@
 	i = tokenix;
 	inst0 = word0;
 	if (type == 0 && reserved ("rel", i)) {
+#if 0 /* driver will fix relative dsps to absolute */
 		if (arch < ARCH710) {
 			errout ("Wrong arch for relative dsps");
-			return;
 		}
+#endif
 		inst1 = evaluate (i + 2) - dsps - 8;
 		i += 4;
 		inst0 |= 0x00800000;
@@ -1235,10 +1238,11 @@
 		inst0 |= (evaluate (t++) & 0xff) << 16;
 	if (tokens[t++].type == ',') {
 		if (reserved ("rel", t)) {
+#if 0 /* driver will fix relative dsps to absolute */
 			if (arch < ARCH710) {
 				errout ("Wrong arch for relative dsps");
-				return;
 			}
+#endif
 			inst0 |= 0x04000000;
 			inst1 = evaluate (t + 2) - dsps - 8;
 		}
Index: dev/microcode/siop/oosiop.out
===================================================================
RCS file: /cvsroot/src/sys/dev/microcode/siop/oosiop.out,v
retrieving revision 1.2
diff -u -r1.2 oosiop.out
--- dev/microcode/siop/oosiop.out	2002/07/07 23:01:51	1.2
+++ dev/microcode/siop/oosiop.out	2003/04/04 12:45:51
@@ -1,298 +1,79 @@
-/*	$NetBSD: oosiop.out,v 1.2 2002/07/07 23:01:51 fredette Exp $	*/
+/*	$NetBSD: ncr53cxxx.c,v 1.10 2002/04/21 22:40:10 bouyer Exp $	*/
 /*
  *	DO NOT EDIT - this file is automatically generated.
- *	created from oosiop.ss on Sun Jul  7 19:00:49 2002
+ *	created from oosiop.ss on Mon Mar 24 21:23:21 2003
  */
 const u_int32_t oosiop_script[] = {
-	0x41000000, 0x00000130,			/* 000 -   0 */
-	0x870b0000, 0x00000040,			/* 008 -   8 */
-	0x860a0000, 0x00000190,			/* 010 -  16 */
-	0x820a0000, 0x000001a0,			/* 018 -  24 */
-	0x800a0000, 0x000001b8,			/* 020 -  32 */
-	0x810a0000, 0x000002c8,			/* 028 -  40 */
-	0x830a0000, 0x000003d8,			/* 030 -  48 */
-	0x98080000, 0x0000ff05,			/* 038 -  56 */
-	0x0f000000, 0x00000000,			/* 040 -  64 */
-	0x800c0001, 0x00000090,			/* 048 -  72 */
-	0x800c0004, 0x000000e0,			/* 050 -  80 */
-	0x800c0002, 0x000000f8,			/* 058 -  88 */
-	0x800c0007, 0x00000078,			/* 060 -  96 */
-	0x800c0003, 0x00000078,			/* 068 - 104 */
-	0x98080000, 0x0000ff06,			/* 070 - 112 */
-	0x60000040, 0x00000000,			/* 078 - 120 */
-	0x60000008, 0x00000000,			/* 080 - 128 */
-	0x80080000, 0x00000008,			/* 088 - 136 */
-	0x60000040, 0x00000000,			/* 090 - 144 */
-	0x0f000000, 0x00000000,			/* 098 - 152 */
-	0x800c0003, 0x000000b0,			/* 0a0 - 160 */
-	0x98080000, 0x0000ff07,			/* 0a8 - 168 */
-	0x60000040, 0x00000000,			/* 0b0 - 176 */
-	0x0f000000, 0x00000000,			/* 0b8 - 184 */
-	0x98080000, 0x0000ff0b,			/* 0c0 - 192 */
-	0x58000008, 0x00000000,			/* 0c8 - 200 */
-	0x60000040, 0x00000000,			/* 0d0 - 208 */
-	0x80080000, 0x00000008,			/* 0d8 - 216 */
-	0x60000040, 0x00000000,			/* 0e0 - 224 */
-	0x48000000, 0x00000000,			/* 0e8 - 232 */
-	0x98080000, 0x0000ff02,			/* 0f0 - 240 */
-	0x60000040, 0x00000000,			/* 0f8 - 248 */
-	0x87030000, 0x00000008,			/* 100 - 256 */
-	0x0f000000, 0x00000000,			/* 108 - 264 */
-	0x98040004, 0x0000ff08,			/* 110 - 272 */
+	0x54000000, 0x00000008,			/* 000 -   0 */
+	0x98080000, 0xbeef0003,			/* 008 -   8 */
+	0x98080000, 0xbeef0005,			/* 010 -  16 */
+	0x9f030000, 0xdeadbeef,			/* 018 -  24 */
+	0x0f000000, 0x00000000,			/* 020 -  32 */
+	0x98080000, 0xbeef0004,			/* 028 -  40 */
+	0x45000000, 0xffffffc8,			/* 030 -  48 */
+	0x878b0000, 0x00000030,			/* 038 -  56 */
+	0x868b0000, 0x00000078,			/* 040 -  64 */
+	0x838b0000, 0x000000a0,			/* 048 -  72 */
+	0x828b0000, 0x00000080,			/* 050 -  80 */
+	0x810b0000, 0x00000000,			/* 058 -  88 */
+	0x800b0000, 0x00000000,			/* 060 -  96 */
+	0x98080000, 0xdeadbeef,			/* 068 - 104 */
+	0x60000008, 0x00000000,			/* 070 - 112 */
+	0x0f000000, 0x00000000,			/* 078 - 120 */
+	0x808c0000, 0x00000090,			/* 080 - 128 */
+	0x808c0001, 0x000000a0,			/* 088 - 136 */
+	0x808c0004, 0x00000068,			/* 090 - 144 */
+	0x98080000, 0xbeef0001,			/* 098 - 152 */
+	0x60000040, 0x00000000,			/* 0a0 - 160 */
+	0x80880000, 0xffffff88,			/* 0a8 - 168 */
+	0x58000008, 0x00000000,			/* 0b0 - 176 */
+	0x60000040, 0x00000000,			/* 0b8 - 184 */
+	0x0e000000, 0x00000000,			/* 0c0 - 192 */
+	0x60000008, 0x00000000,			/* 0c8 - 200 */
+	0x80880000, 0xffffff60,			/* 0d0 - 208 */
+	0x60000008, 0x00000000,			/* 0d8 - 216 */
+	0x0a000000, 0x00000000,			/* 0e0 - 224 */
+	0x80880000, 0xffffff48,			/* 0e8 - 232 */
+	0x0b000000, 0x00000000,			/* 0f0 - 240 */
+	0x80880000, 0xffffff38,			/* 0f8 - 248 */
+	0x60000040, 0x00000000,			/* 100 - 256 */
+	0x48000000, 0x00000000,			/* 108 - 264 */
+	0x98080000, 0xbeef0006,			/* 110 - 272 */
 	0x60000040, 0x00000000,			/* 118 - 280 */
 	0x48000000, 0x00000000,			/* 120 - 288 */
-	0x98080000, 0x0000ff01,			/* 128 - 296 */
-	0x50000000, 0x00000170,			/* 130 - 304 */
-	0x80000000, 0x00000000,			/* 138 - 312 */
-	0x80000000, 0x00000000,			/* 140 - 320 */
-	0x9f030000, 0x0000ff09,			/* 148 - 328 */
-	0x0f000000, 0x00000000,			/* 150 - 336 */
-	0x98080000, 0x0000ff03,			/* 158 - 344 */
-	0x60000040, 0x00000000,			/* 160 - 352 */
-	0x80080000, 0x00000008,			/* 168 - 360 */
-	0x74011000, 0x00000000,			/* 170 - 368 */
-	0x980c0000, 0x0000ff04,			/* 178 - 376 */
-	0x80000000, 0x00000000,			/* 180 - 384 */
-	0x80080000, 0x00000130,			/* 188 - 392 */
-	0x0e000000, 0x00000000,			/* 190 - 400 */
-	0x80080000, 0x00000008,			/* 198 - 408 */
-	0x60000008, 0x00000000,			/* 1a0 - 416 */
-	0x0a000000, 0x00000000,			/* 1a8 - 424 */
-	0x80080000, 0x00000008,			/* 1b0 - 432 */
-	0x08000000, 0x00000000,			/* 1b8 - 440 */
-	0x88030000, 0x00000008,			/* 1c0 - 448 */
-	0x08000000, 0x00000000,			/* 1c8 - 456 */
-	0x88030000, 0x00000008,			/* 1d0 - 464 */
-	0x08000000, 0x00000000,			/* 1d8 - 472 */
-	0x88030000, 0x00000008,			/* 1e0 - 480 */
-	0x08000000, 0x00000000,			/* 1e8 - 488 */
-	0x88030000, 0x00000008,			/* 1f0 - 496 */
-	0x08000000, 0x00000000,			/* 1f8 - 504 */
-	0x88030000, 0x00000008,			/* 200 - 512 */
-	0x08000000, 0x00000000,			/* 208 - 520 */
-	0x88030000, 0x00000008,			/* 210 - 528 */
-	0x08000000, 0x00000000,			/* 218 - 536 */
-	0x88030000, 0x00000008,			/* 220 - 544 */
-	0x08000000, 0x00000000,			/* 228 - 552 */
-	0x88030000, 0x00000008,			/* 230 - 560 */
-	0x08000000, 0x00000000,			/* 238 - 568 */
-	0x88030000, 0x00000008,			/* 240 - 576 */
-	0x08000000, 0x00000000,			/* 248 - 584 */
-	0x88030000, 0x00000008,			/* 250 - 592 */
-	0x08000000, 0x00000000,			/* 258 - 600 */
-	0x88030000, 0x00000008,			/* 260 - 608 */
-	0x08000000, 0x00000000,			/* 268 - 616 */
-	0x88030000, 0x00000008,			/* 270 - 624 */
-	0x08000000, 0x00000000,			/* 278 - 632 */
-	0x88030000, 0x00000008,			/* 280 - 640 */
-	0x08000000, 0x00000000,			/* 288 - 648 */
-	0x88030000, 0x00000008,			/* 290 - 656 */
-	0x08000000, 0x00000000,			/* 298 - 664 */
-	0x88030000, 0x00000008,			/* 2a0 - 672 */
-	0x08000000, 0x00000000,			/* 2a8 - 680 */
-	0x88030000, 0x00000008,			/* 2b0 - 688 */
-	0x08000000, 0x00000000,			/* 2b8 - 696 */
-	0x88080000, 0x00000008,			/* 2c0 - 704 */
-	0x09000000, 0x00000000,			/* 2c8 - 712 */
-	0x89030000, 0x00000008,			/* 2d0 - 720 */
-	0x09000000, 0x00000000,			/* 2d8 - 728 */
-	0x89030000, 0x00000008,			/* 2e0 - 736 */
-	0x09000000, 0x00000000,			/* 2e8 - 744 */
-	0x89030000, 0x00000008,			/* 2f0 - 752 */
-	0x09000000, 0x00000000,			/* 2f8 - 760 */
-	0x89030000, 0x00000008,			/* 300 - 768 */
-	0x09000000, 0x00000000,			/* 308 - 776 */
-	0x89030000, 0x00000008,			/* 310 - 784 */
-	0x09000000, 0x00000000,			/* 318 - 792 */
-	0x89030000, 0x00000008,			/* 320 - 800 */
-	0x09000000, 0x00000000,			/* 328 - 808 */
-	0x89030000, 0x00000008,			/* 330 - 816 */
-	0x09000000, 0x00000000,			/* 338 - 824 */
-	0x89030000, 0x00000008,			/* 340 - 832 */
-	0x09000000, 0x00000000,			/* 348 - 840 */
-	0x89030000, 0x00000008,			/* 350 - 848 */
-	0x09000000, 0x00000000,			/* 358 - 856 */
-	0x89030000, 0x00000008,			/* 360 - 864 */
-	0x09000000, 0x00000000,			/* 368 - 872 */
-	0x89030000, 0x00000008,			/* 370 - 880 */
-	0x09000000, 0x00000000,			/* 378 - 888 */
-	0x89030000, 0x00000008,			/* 380 - 896 */
-	0x09000000, 0x00000000,			/* 388 - 904 */
-	0x89030000, 0x00000008,			/* 390 - 912 */
-	0x09000000, 0x00000000,			/* 398 - 920 */
-	0x89030000, 0x00000008,			/* 3a0 - 928 */
-	0x09000000, 0x00000000,			/* 3a8 - 936 */
-	0x89030000, 0x00000008,			/* 3b0 - 944 */
-	0x09000000, 0x00000000,			/* 3b8 - 952 */
-	0x89030000, 0x00000008,			/* 3c0 - 960 */
-	0x09000000, 0x00000000,			/* 3c8 - 968 */
-	0x88080000, 0x00000008,			/* 3d0 - 976 */
-	0x0b000000, 0x00000000,			/* 3d8 - 984 */
-	0x9f030000, 0x0000ff0a,			/* 3e0 - 992 */
-	0x0f000000, 0x00000000,			/* 3e8 - 1000 */
-	0x60000040, 0x00000000,			/* 3f0 - 1008 */
-	0x48000000, 0x00000000,			/* 3f8 - 1016 */
-	0x98080000, 0x0000ff00,			/* 400 - 1024 */
-	0x80080000, 0x00000130,			/* 408 - 1032 */
-};
-
-#define	E_ds_Device	0x00000000
-u_int32_t E_ds_Device_Used[] = {
-	0x00000001,
-};
-
-#define	E_ds_MsgOut	0x00000000
-u_int32_t E_ds_MsgOut_Used[] = {
-	0x00000065,
-};
-
-#define	E_ds_Cmd	0x00000000
-u_int32_t E_ds_Cmd_Used[] = {
-	0x0000006b,
-};
-
-#define	E_ds_Status	0x00000000
-u_int32_t E_ds_Status_Used[] = {
-	0x000000f7,
-};
-
-#define	E_ds_Msg	0x00000000
-u_int32_t E_ds_Msg_Used[] = {
-	0x00000055,
-	0x000000fb,
-};
-
-#define	E_ds_MsgIn	0x00000000
-u_int32_t E_ds_MsgIn_Used[] = {
-	0x00000011,
-};
-
-#define	E_ds_ExtMsg	0x00000000
-u_int32_t E_ds_ExtMsg_Used[] = {
-	0x00000027,
-	0x00000043,
-};
-
-#define	E_ds_SyncMsg	0x00000000
-u_int32_t E_ds_SyncMsg_Used[] = {
-	0x0000002f,
-};
-
-#define	E_ds_Data1	0x00000000
-u_int32_t E_ds_Data1_Used[] = {
-	0x0000006f,
-	0x00000073,
-	0x00000077,
-	0x0000007b,
-	0x0000007f,
-	0x00000083,
-	0x00000087,
-	0x0000008b,
-	0x0000008f,
-	0x00000093,
-	0x00000097,
-	0x0000009b,
-	0x0000009f,
-	0x000000a3,
-	0x000000a7,
-	0x000000ab,
-	0x000000af,
-	0x000000b3,
-	0x000000b7,
-	0x000000bb,
-	0x000000bf,
-	0x000000c3,
-	0x000000c7,
-	0x000000cb,
-	0x000000cf,
-	0x000000d3,
-	0x000000d7,
-	0x000000db,
-	0x000000df,
-	0x000000e3,
-	0x000000e7,
-	0x000000eb,
-	0x000000ef,
-	0x000000f3,
-};
-
-#define	A_ok	0x0000ff00
-#define	A_int_disc	0x0000ff01
-#define	A_int_disc_wodp	0x0000ff02
-#define	A_int_reconnect	0x0000ff03
-#define	A_int_connect	0x0000ff04
-#define	A_int_phase	0x0000ff05
-#define	A_int_msgin	0x0000ff06
-#define	A_int_extmsg	0x0000ff07
-#define	A_int_msgsdp	0x0000ff08
-#define	A_int_identify	0x0000ff09
-#define	A_int_status	0x0000ff0a
-#define	A_int_syncmsg	0x0000ff0b
-#define	Ent_scripts	0x00000000
-#define	Ent_switch	0x00000008
-#define	Ent_wait_reselect	0x00000130
-#define	Ent_dataout	0x000001b8
-#define	Ent_datain	0x000002c8
-#define	Ent_clear_ack	0x00000078
-
-u_int32_t INSTRUCTIONS = 0x00000082;
-u_int32_t PATCHES = 0x00000038;
-u_int32_t LABELPATCHES[] = {
-	0x00000001,
-	0x00000003,
-	0x00000005,
-	0x00000007,
-	0x00000009,
-	0x0000000b,
-	0x0000000d,
-	0x00000013,
-	0x00000015,
-	0x00000017,
-	0x00000019,
-	0x0000001b,
-	0x00000023,
-	0x00000029,
-	0x00000037,
-	0x00000041,
-	0x0000004d,
-	0x0000005b,
-	0x00000063,
-	0x00000067,
-	0x0000006d,
-	0x00000071,
-	0x00000075,
-	0x00000079,
-	0x0000007d,
-	0x00000081,
-	0x00000085,
-	0x00000089,
-	0x0000008d,
-	0x00000091,
-	0x00000095,
-	0x00000099,
-	0x0000009d,
-	0x000000a1,
-	0x000000a5,
-	0x000000a9,
-	0x000000ad,
-	0x000000b1,
-	0x000000b5,
-	0x000000b9,
-	0x000000bd,
-	0x000000c1,
-	0x000000c5,
-	0x000000c9,
-	0x000000cd,
-	0x000000d1,
-	0x000000d5,
-	0x000000d9,
-	0x000000dd,
-	0x000000e1,
-	0x000000e5,
-	0x000000e9,
-	0x000000ed,
-	0x000000f1,
-	0x000000f5,
-	0x00000103,
-};
-
+	0x98080000, 0xbeef0000,			/* 128 - 296 */
+	0x60000040, 0x00000000,			/* 130 - 304 */
+	0x9f020000, 0xdeadbeef,			/* 138 - 312 */
+	0x0f000000, 0x00000000,			/* 140 - 320 */
+	0x98080000, 0xbeef0002,			/* 148 - 328 */
+	0x60000040, 0x00000000,			/* 150 - 336 */
+	0x9f020000, 0xdeadbeef,			/* 158 - 344 */
+	0x0f000000, 0x00000000,			/* 160 - 352 */
+	0x98080000, 0xbeef0001,			/* 168 - 360 */
+};
+
+#define	A_int_done	0xbeef0000
+#define	A_int_msgin	0xbeef0001
+#define	A_int_extmsg	0xbeef0002
+#define	A_int_resel	0xbeef0003
+#define	A_int_res_id	0xbeef0004
+#define	A_int_resfail	0xbeef0005
+#define	A_int_disc	0xbeef0006
+#define	A_int_err	0xdeadbeef
+#define	Ent_p_resel_msgin_move	0x00000020
+#define	Ent_p_select	0x00000030
+#define	Ent_p_datain_jump	0x00000058
+#define	Ent_p_dataout_jump	0x00000060
+#define	Ent_p_msgin_move	0x00000078
+#define	Ent_p_msgout_move	0x000000c0
+#define	Ent_p_cmdout_move	0x000000e0
+#define	Ent_p_status_move	0x000000f0
+#define	Ent_p_extmsglen_move	0x00000140
+#define	Ent_p_extmsgin_move	0x00000160
+#define	Ent_wait_reselect	0x00000000
+#define	Ent_wait_resel_identify	0x00000018
+#define	Ent_start_select	0x00000030
+#define	Ent_phasedispatch	0x00000038
+#define	Ent_ack_msgin	0x000000a0
+#define	Ent_sendmsg	0x000000b0
+#define	Ent_rcv_extmsg	0x00000150
Index: dev/microcode/siop/oosiop.ss
===================================================================
RCS file: /cvsroot/src/sys/dev/microcode/siop/oosiop.ss,v
retrieving revision 1.1
diff -u -r1.1 oosiop.ss
--- dev/microcode/siop/oosiop.ss	2001/12/05 18:27:13	1.1
+++ dev/microcode/siop/oosiop.ss	2003/04/04 12:45:51
@@ -1,9 +1,7 @@
-;	$NetBSD: oosiop.ss,v 1.1 2001/12/05 18:27:13 fredette Exp $
+;	$NetBSD$
 
 ;
-; Copyright (c) 2001 Matt Fredette
-; Copyright (c) 1995 Michael L. Hitch
-; All rights reserved.
+; Copyright (c) 2001 Shuichiro URATA.  All rights reserved.
 ;
 ; Redistribution and use in source and binary forms, with or without
 ; modification, are permitted provided that the following conditions
@@ -13,11 +11,8 @@
 ; 2. Redistributions in binary form must reproduce the above copyright
 ;    notice, this list of conditions and the following disclaimer in the
 ;    documentation and/or other materials provided with the distribution.
-; 3. All advertising materials mentioning features or use of this software
-;    must display the following acknowledgement:
-;      This product includes software developed by Michael L. Hitch.
-; 4. The name of the author may not be used to endorse or promote products
-;    derived from this software without specific prior written permission
+; 3. The name of the author may not be used to endorse or promote products
+;    derived from this software without specific prior written permission.
 ;
 ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -33,211 +28,123 @@
 
 ; NCR 53c700 script
 ;
+
 ARCH 700
-;
-EXTERNAL ds_Device
-EXTERNAL ds_MsgOut
-EXTERNAL ds_Cmd
-EXTERNAL ds_Status
-EXTERNAL ds_Msg
-EXTERNAL ds_MsgIn
-EXTERNAL ds_ExtMsg
-EXTERNAL ds_SyncMsg
-EXTERNAL ds_Data1
-
-
-ABSOLUTE ok		= 0xff00
-ABSOLUTE int_disc	= 0xff01
-ABSOLUTE int_disc_wodp	= 0xff02
-ABSOLUTE int_reconnect	= 0xff03
-ABSOLUTE int_connect	= 0xff04
-ABSOLUTE int_phase	= 0xff05
-ABSOLUTE int_msgin	= 0xff06
-ABSOLUTE int_extmsg	= 0xff07
-ABSOLUTE int_msgsdp	= 0xff08
-ABSOLUTE int_identify	= 0xff09
-ABSOLUTE int_status	= 0xff0a
-ABSOLUTE int_syncmsg	= 0xff0b
-
-ENTRY	scripts
-ENTRY	switch
-ENTRY	wait_reselect
-ENTRY	dataout
-ENTRY	datain
-ENTRY	clear_ack
 
-PROC	oosiop_script:
+; interrupt codes
+ABSOLUTE int_done	= 0xbeef0000
+ABSOLUTE int_msgin	= 0xbeef0001
+ABSOLUTE int_extmsg	= 0xbeef0002
+ABSOLUTE int_resel	= 0xbeef0003
+ABSOLUTE int_res_id	= 0xbeef0004
+ABSOLUTE int_resfail	= 0xbeef0005
+ABSOLUTE int_disc	= 0xbeef0006
+ABSOLUTE int_err 	= 0xdeadbeef
+
+; patch entries
+ENTRY p_resel_msgin_move
+ENTRY p_select
+ENTRY p_datain_jump
+ENTRY p_dataout_jump
+ENTRY p_msgin_move
+ENTRY p_msgout_move
+ENTRY p_cmdout_move
+ENTRY p_status_move
+ENTRY p_extmsglen_move
+ENTRY p_extmsgin_move
 
-scripts:
 
-	SELECT ATN ds_Device, reselect
-;
-switch:
-	JUMP msgin, WHEN MSG_IN
-	JUMP msgout, IF MSG_OUT
-	JUMP command_phase, IF CMD
-	JUMP dataout, IF DATA_OUT
-	JUMP datain, IF DATA_IN
-	JUMP end, IF STATUS
+PROC  oosiop_script:
 
-	INT int_phase			; Unrecognized phase
+ENTRY wait_reselect
+wait_reselect:
+	WAIT RESELECT REL(reselect_fail)
+	INT int_resel
+reselect_fail:
+	INT int_resfail
+
+ENTRY wait_resel_identify
+wait_resel_identify:
+	INT int_err, WHEN NOT MSG_IN
+p_resel_msgin_move:
+	MOVE 0, 0, WHEN MSG_IN
+	INT int_res_id
+
+ENTRY start_select
+start_select:
+p_select:
+	SELECT ATN 0, REL(wait_reselect)
+
+ENTRY phasedispatch
+phasedispatch:
+	JUMP REL(msgin), WHEN MSG_IN
+	JUMP REL(msgout), WHEN MSG_OUT
+	JUMP REL(status), WHEN STATUS
+	JUMP REL(cmdout), WHEN CMD
+p_datain_jump:
+	JUMP 0, WHEN DATA_IN
+p_dataout_jump:
+	JUMP 0, WHEN DATA_OUT
+	INT int_err
 
 msgin:
-	MOVE 0, ds_MsgIn, WHEN MSG_IN
-	JUMP ext_msg, IF 0x01		; extended message
-	JUMP disc, IF 0x04		; disconnect message
-	JUMP msg_sdp, IF 0x02		; save data pointers
-	JUMP msg_rej, IF 0x07		; message reject
-	JUMP msg_rdp, IF 0x03		; restore data pointers
-	INT int_msgin			; unrecognized message
-
-msg_rej:
-; Do we need to interrupt host here to let it handle the reject?
-msg_rdp:
-clear_ack:
-	CLEAR ACK
 	CLEAR ATN
-	JUMP switch
+p_msgin_move:
+	MOVE 0, 0, WHEN MSG_IN
+	JUMP REL(complete), IF 0x00
+	JUMP REL(extmsgsetup), IF 0x01
+	JUMP REL(disconnect), IF 0x04
+	INT int_msgin
 
-ext_msg:
+ENTRY ack_msgin
+ack_msgin:
 	CLEAR ACK
-	MOVE 0, ds_ExtMsg, WHEN MSG_IN
-	JUMP sync_msg, IF 0x03
-	int int_extmsg			; extended message not SDTR
+	JUMP REL(phasedispatch)
 
-sync_msg:
-	CLEAR ACK
-	MOVE 0, ds_SyncMsg, WHEN MSG_IN
-	int int_syncmsg			; Let host handle the message
-; If we continue from the interrupt, the host has set up a response
-; message to be sent.  Set ATN, clear ACK, and continue.
+ENTRY sendmsg
+sendmsg:
 	SET ATN
 	CLEAR ACK
-	JUMP switch
+msgout:
+p_msgout_move:
+	MOVE 0, 0, WHEN MSG_OUT
+	CLEAR ATN
+	JUMP REL(phasedispatch)
+
+cmdout:
+	CLEAR ATN
+p_cmdout_move:
+	MOVE 0, 0, WHEN CMD
+	JUMP REL(phasedispatch)
+
+status:
+p_status_move:
+	MOVE 0, 0, WHEN STATUS
+	JUMP REL(phasedispatch)
 
-disc:
+disconnect:
 	CLEAR ACK
 	WAIT DISCONNECT
+	INT int_disc
 
-	int int_disc_wodp		; signal disconnect w/o save DP
-
-msg_sdp:
-	CLEAR ACK			; acknowledge message
-	JUMP switch, WHEN NOT MSG_IN
-	MOVE 0, ds_ExtMsg, WHEN MSG_IN
-	INT int_msgsdp, IF NOT 0x04	; interrupt if not disconnect
+complete:
 	CLEAR ACK
 	WAIT DISCONNECT
-
-	INT int_disc			; signal disconnect
+	INT int_done
 
-reselect:
-wait_reselect:
-	WAIT RESELECT select_adr
-	; NB: these NOPs are CRITICAL to preserve the 1:1
-	; correspondence between instructions in this script
-	; and instructions in the osiop (53c710) script:
-	NOP
-	NOP				; reselect ID already in SFBR
-
-	INT int_identify, WHEN NOT MSG_IN
-	MOVE 0, ds_Msg, WHEN MSG_IN
-	INT int_reconnect		; let host know about reconnect
-	CLEAR ACK			; acknowlege the message
-	JUMP switch
-
-select_adr:
-	MOVE SCNTL1 & 0x10 to SFBR	; get connected status
-	INT int_connect, IF 0x00	; tell host if not connected
-	NOP				; Sig_P doesn't exist on the 53c700
-	JUMP wait_reselect		; and try reselect again
-
-msgout:
-	MOVE 0, ds_MsgOut, WHEN MSG_OUT
-	JUMP switch
-
-command_phase:
-	CLEAR ATN
-	MOVE 0, ds_Cmd, WHEN CMD
-	JUMP switch
-
-dataout:
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch, WHEN NOT DATA_OUT
-	MOVE 0, ds_Data1, WHEN DATA_OUT
-	CALL switch
-
-datain:
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch, WHEN NOT DATA_IN
-	MOVE 0, ds_Data1, WHEN DATA_IN
-	CALL switch
-
-end:
-	MOVE 0, ds_Status, WHEN STATUS
-	int int_status, WHEN NOT MSG_IN	; status not followed by msg
-	MOVE 0, ds_Msg, WHEN MSG_IN
+; receive extended message length
+extmsgsetup:
 	CLEAR ACK
-	WAIT DISCONNECT
-	INT ok				; signal completion
-	JUMP wait_reselect
+	INT int_err, IF NOT MSG_IN
+p_extmsglen_move:
+	MOVE 0, 0, WHEN MSG_IN
+	INT int_extmsg
+
+; receive extended message
+ENTRY rcv_extmsg
+rcv_extmsg:
+	CLEAR ACK
+	INT int_err, IF NOT MSG_IN
+p_extmsgin_move:
+	MOVE 0, 0, WHEN MSG_IN
+	INT int_msgin
--- /dev/null	2003-04-02 23:49:50.000000000 +0900
+++ arch/arc/jazz/oosiop_jazzio.c	2002-12-29 01:27:12.000000000 +0900
@@ -0,0 +1,107 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 2001 Shuichiro URATA.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+
+#include <dev/scsipi/scsi_all.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsi_message.h>
+
+#include <machine/cpu.h>
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+
+#include <dev/ic/oosiopreg.h>
+#include <dev/ic/oosiopvar.h>
+#include <arc/jazz/jazziovar.h>
+
+int	oosiop_jazzio_match(struct device *, struct cfdata *, void *);
+void	oosiop_jazzio_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(oosiop_jazzio, sizeof(struct oosiop_softc),
+    oosiop_jazzio_match, oosiop_jazzio_attach, NULL, NULL);
+extern struct cfdriver oosiop_cd;
+
+/*
+ * Match driver based on name
+ */
+int
+oosiop_jazzio_match(parent, match, aux)
+	struct device *parent;
+	struct cfdata *match;
+	void *aux;
+{
+	struct jazzio_attach_args *ja = aux;
+
+	if (strcmp(ja->ja_name, "NCRC700") != 0)
+		return (0);
+
+	return (1);
+}
+
+void
+oosiop_jazzio_attach(parent, self, aux)
+	struct device *parent;
+	struct device *self;
+	void *aux;
+{
+	struct jazzio_attach_args *ja = aux;
+	struct oosiop_softc *sc = (void *)self;
+	int i, scid;
+
+	sc->sc_bst = ja->ja_bust;
+	sc->sc_dmat = ja->ja_dmat;
+
+	if (bus_space_map(sc->sc_bst, ja->ja_addr,
+	    OOSIOP_NREGS, 0, &sc->sc_bsh) != 0) {
+		printf(": failed to map regsters\n");
+		return;
+	}
+
+	sc->sc_chip = OOSIOP_700_66;
+	sc->sc_freq = 50000000;
+
+	/* Preserve host id */
+	scid = oosiop_read_1(sc, OOSIOP_SCID);
+	for (i = 0; i < OOSIOP_NTGT; i++)
+		if (scid & (1 << i))
+			break;
+	if (i == OOSIOP_NTGT)
+		i = OOSIOP_NTGT - 1;
+
+	sc->sc_id = i;
+
+	jazzio_intr_establish(ja->ja_intr, (intr_handler_t)oosiop_intr, sc);
+
+	oosiop_attach(sc);
+}
--- /dev/null	2003-04-02 23:49:50.000000000 +0900
+++ arch/hp700/gsc/oosiop_gsc.c	2003-02-19 01:29:50.000000000 +0900
@@ -0,0 +1,174 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (c) 2001 Matt Fredette.  All rights reserved.
+ * Copyright (c) 2001,2002 Izumi Tsutsui.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*	$OpenBSD: siop_gsc.c,v 1.1 1998/11/04 17:01:35 mickey Exp $	*/
+
+/*
+ * Copyright (c) 1998 Michael Shalayeff
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Michael Shalayeff.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+
+#include <dev/scsipi/scsi_all.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsiconf.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/iomod.h>
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+
+#include <dev/ic/oosiopreg.h>
+#include <dev/ic/oosiopvar.h>
+
+#include <hp700/dev/cpudevs.h>
+#include <hp700/gsc/gscbusvar.h>
+#include <hp700/hp700/machdep.h>
+
+#define OOSIOP_GSC_RESET	0x0000
+#define OOSIOP_GSC_OFFSET	0x0100
+
+int oosiop_gsc_match(struct device *, struct cfdata *, void *);
+void oosiop_gsc_attach(struct device *, struct device *, void *);
+int oosiop_gsc_intr(void *);
+
+CFATTACH_DECL(oosiop_gsc, sizeof(struct oosiop_softc),
+    oosiop_gsc_match, oosiop_gsc_attach, NULL, NULL);
+
+int
+oosiop_gsc_match(parent, match, aux)
+	struct device *parent;
+	struct cfdata *match;
+	void *aux;
+{
+	struct gsc_attach_args *ga = aux;
+	bus_space_handle_t ioh;
+	int rv = 1;
+
+	if (ga->ga_type.iodc_type != HPPA_TYPE_FIO ||
+	    ga->ga_type.iodc_sv_model != HPPA_FIO_SCSI)
+		return 0;
+
+	if (bus_space_map(ga->ga_iot, ga->ga_hpa, 
+	    OOSIOP_GSC_OFFSET + OOSIOP_NREGS, 0, &ioh))
+		return 0;
+
+
+	bus_space_unmap(ga->ga_iot, ioh, OOSIOP_GSC_OFFSET + OOSIOP_NREGS);
+	return rv;
+}
+
+void
+oosiop_gsc_attach(parent, self, aux)
+	struct device *parent, *self;
+	void *aux;
+{
+	struct oosiop_softc *sc = (void *)self;
+	struct gsc_attach_args *ga = aux;
+	bus_space_handle_t ioh;
+
+	sc->sc_bst = ga->ga_iot;
+	sc->sc_dmat = ga->ga_dmatag;
+	if (bus_space_map(sc->sc_bst, ga->ga_hpa,
+	    OOSIOP_GSC_OFFSET + OOSIOP_NREGS, 0, &ioh))
+		panic("oosiop_gsc_attach: couldn't map I/O ports");
+	if (bus_space_subregion(sc->sc_bst, ioh, 
+	    OOSIOP_GSC_OFFSET, OOSIOP_NREGS, &sc->sc_bsh))
+		panic("oosiop_gsc_attach: couldn't get chip ports");
+
+	sc->sc_freq = ga->ga_ca.ca_pdc_iodc_read->filler2[14];
+	if (sc->sc_freq == 0)
+		sc->sc_freq = 50000000;
+
+	sc->sc_chip = OOSIOP_700;
+	sc->sc_id = ga->ga_scsi_target;
+
+	/*
+	 * Reset SCSI subsystem.
+	 */
+	bus_space_write_1(sc->sc_bst, ioh, OOSIOP_GSC_RESET, 0);
+	DELAY(1000);
+
+	/*
+	 * Call common attachment
+	 */
+	oosiop_attach(sc);
+
+	(void)hp700_intr_establish(&sc->sc_dev, IPL_BIO,
+	    oosiop_gsc_intr, sc, ga->ga_int_reg, ga->ga_irq);
+}
+
+/*
+ * interrupt handler
+ */
+int
+oosiop_gsc_intr(arg)
+	void *arg;
+{
+	struct oosiop_softc *sc = arg;
+	int rv;
+
+	rv = oosiop_intr(sc);
+
+	/* Blink the LED. */
+	hp700_led_blink(HP700_LED_DISK);
+
+	return rv;
+}
--- /dev/null	2003-04-02 23:49:50.000000000 +0900
+++ dev/ic/oosiop.c	2003-03-24 21:34:22.000000000 +0900
@@ -0,0 +1,1325 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (c) 2001 Shuichiro URATA.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * NCR53C700 SCSI I/O processor (OOSIOP) driver
+ *
+ * TODO:
+ *   - More better error handling.
+ *   - Implement tagged queuing.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/callout.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <dev/scsipi/scsi_all.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsi_message.h>
+
+#include <machine/cpu.h>
+#include <machine/bus.h>
+
+#include <dev/ic/oosiopreg.h>
+#include <dev/ic/oosiopvar.h>
+#include <dev/microcode/siop/oosiop.out>
+
+static int	oosiop_alloc_cb(struct oosiop_softc *, int);
+
+static __inline void oosiop_relocate_io(struct oosiop_softc *, bus_addr_t);
+static __inline void oosiop_relocate_tc(struct oosiop_softc *, bus_addr_t);
+static __inline void oosiop_fixup_select(struct oosiop_softc *, bus_addr_t,
+		         int);
+static __inline void oosiop_fixup_jump(struct oosiop_softc *, bus_addr_t,
+		         bus_addr_t);
+static __inline void oosiop_fixup_move(struct oosiop_softc *, bus_addr_t,
+		         bus_size_t, bus_addr_t);
+
+static void	oosiop_load_script(struct oosiop_softc *);
+static void	oosiop_setup_sgdma(struct oosiop_softc *, struct oosiop_cb *);
+static void	oosiop_setup_dma(struct oosiop_softc *);
+static void	oosiop_flush_fifo(struct oosiop_softc *);
+static void	oosiop_clear_fifo(struct oosiop_softc *);
+static void	oosiop_phasemismatch(struct oosiop_softc *);
+static void	oosiop_setup_syncxfer(struct oosiop_softc *);
+static void	oosiop_set_syncparam(struct oosiop_softc *, int, int, int);
+static void	oosiop_minphys(struct buf *);
+static void	oosiop_scsipi_request(struct scsipi_channel *,
+		    scsipi_adapter_req_t, void *);
+static void	oosiop_done(struct oosiop_softc *, struct oosiop_cb *);
+static void	oosiop_timeout(void *);
+static void	oosiop_reset(struct oosiop_softc *);
+static void	oosiop_reset_bus(struct oosiop_softc *);
+static void	oosiop_scriptintr(struct oosiop_softc *);
+static void	oosiop_msgin(struct oosiop_softc *, struct oosiop_cb *);
+
+/* Trap interrupt code for unexpected data I/O */
+#define	DATAIN_TRAP	0xdead0001
+#define	DATAOUT_TRAP	0xdead0002
+
+/* Possible TP and SCF conbination */
+static const struct {
+	u_int8_t	tp;
+	u_int8_t	scf;
+} synctbl[] = {
+	{0, 1},		/* SCLK /  4.0 */
+	{1, 1},		/* SCLK /  5.0 */
+	{2, 1},		/* SCLK /  6.0 */
+	{3, 1},		/* SCLK /  7.0 */
+	{1, 2},		/* SCLK /  7.5 */
+	{4, 1},		/* SCLK /  8.0 */
+	{5, 1},		/* SCLK /  9.0 */
+	{6, 1},		/* SCLK / 10.0 */
+	{3, 2},		/* SCLK / 10.5 */
+	{7, 1},		/* SCLK / 11.0 */
+	{4, 2},		/* SCLK / 12.0 */
+	{5, 2},		/* SCLK / 13.5 */
+	{3, 3},		/* SCLK / 14.0 */
+	{6, 2},		/* SCLK / 15.0 */
+	{4, 3},		/* SCLK / 16.0 */
+	{7, 2},		/* SCLK / 16.5 */
+	{5, 3},		/* SCLK / 18.0 */
+	{6, 3},		/* SCLK / 20.0 */
+	{7, 3}		/* SCLK / 22.0 */
+};
+#define	NSYNCTBL	(sizeof(synctbl) / sizeof(synctbl[0]))
+
+#define	oosiop_period(sc, tp, scf)					\
+	    (((1000000000 / (sc)->sc_freq) * (tp) * (scf)) / 40)
+
+void
+oosiop_attach(struct oosiop_softc *sc)
+{
+	bus_size_t scrsize;
+	bus_dma_segment_t seg;
+	struct oosiop_cb *cb;
+	int err, i, nseg;
+
+	/*
+	 * Allocate DMA-safe memory for the script and map it.
+	 */
+	scrsize = sizeof(oosiop_script);
+	err = bus_dmamem_alloc(sc->sc_dmat, scrsize, PAGE_SIZE, 0, &seg, 1,
+	    &nseg, BUS_DMA_NOWAIT);
+	if (err) {
+		printf(": failed to allocate script memory, err=%d\n", err);
+		return;
+	}
+	err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, scrsize,
+	    (caddr_t *)&sc->sc_scr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
+	if (err) {
+		printf(": failed to map script memory, err=%d\n", err);
+		return;
+	}
+	err = bus_dmamap_create(sc->sc_dmat, scrsize, 1, scrsize, 0,
+	    BUS_DMA_NOWAIT, &sc->sc_scrdma);
+	if (err) {
+		printf(": failed to create script map, err=%d\n", err);
+		return;
+	}
+	err = bus_dmamap_load(sc->sc_dmat, sc->sc_scrdma, sc->sc_scr, scrsize,
+	    NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE);
+	if (err) {
+		printf(": failed to load script map, err=%d\n", err);
+		return;
+	}
+	sc->sc_scrbase = sc->sc_scrdma->dm_segs[0].ds_addr;
+
+	/* Initialize command block array */
+	TAILQ_INIT(&sc->sc_free_cb);
+	TAILQ_INIT(&sc->sc_cbq);
+	if (oosiop_alloc_cb(sc, OOSIOP_NCB) != 0)
+		return;
+
+	/* Use first cb to reselection msgin buffer */
+	cb = TAILQ_FIRST(&sc->sc_free_cb);
+	sc->sc_reselbuf = cb->xferdma->dm_segs[0].ds_addr +
+	    offsetof(struct oosiop_xfer, msgin[0]);
+
+	for (i = 0; i < OOSIOP_NTGT; i++) {
+		sc->sc_tgt[i].nexus = NULL;
+		sc->sc_tgt[i].flags = 0;
+	}
+
+	/* Setup asynchronous clock divisor parameters */
+	if (sc->sc_freq <= 25000000) {
+		sc->sc_ccf = 10;
+		sc->sc_dcntl = OOSIOP_DCNTL_CF_1;
+	} else if (sc->sc_freq <= 37500000) {
+		sc->sc_ccf = 15;
+		sc->sc_dcntl = OOSIOP_DCNTL_CF_1_5;
+	} else if (sc->sc_freq <= 50000000) {
+		sc->sc_ccf = 20;
+		sc->sc_dcntl = OOSIOP_DCNTL_CF_2;
+	} else {
+		sc->sc_ccf = 30;
+		sc->sc_dcntl = OOSIOP_DCNTL_CF_3;
+	}
+
+	if (sc->sc_chip == OOSIOP_700)
+		sc->sc_minperiod = oosiop_period(sc, 4, sc->sc_ccf);
+	else
+		sc->sc_minperiod = oosiop_period(sc, 4, 10);
+
+	if (sc->sc_minperiod < 25)
+		sc->sc_minperiod = 25;	/* limit to 10MB/s */
+
+	printf(": NCR53C700%s rev %d, %dMHz, SCSI ID %d\n",
+	    sc->sc_chip == OOSIOP_700_66 ? "-66" : "",
+	    oosiop_read_1(sc, OOSIOP_CTEST7) >> 4,
+	    sc->sc_freq / 1000000, sc->sc_id);
+	/*
+	 * Reset all
+	 */
+	oosiop_reset(sc);
+	oosiop_reset_bus(sc);
+
+	/*
+	 * Start SCRIPTS processor
+	 */
+	oosiop_load_script(sc);
+	sc->sc_active = 0;
+	oosiop_write_4(sc, OOSIOP_DSP, sc->sc_scrbase + Ent_wait_reselect);
+
+	/*
+	 * Fill in the scsipi_adapter.
+	 */
+	sc->sc_adapter.adapt_dev = &sc->sc_dev;
+	sc->sc_adapter.adapt_nchannels = 1;
+	sc->sc_adapter.adapt_openings = OOSIOP_NCB;
+	sc->sc_adapter.adapt_max_periph = 1;
+	sc->sc_adapter.adapt_ioctl = NULL;
+	sc->sc_adapter.adapt_minphys = oosiop_minphys;
+	sc->sc_adapter.adapt_request = oosiop_scsipi_request;
+
+	/*
+	 * Fill in the scsipi_channel.
+	 */
+	sc->sc_channel.chan_adapter = &sc->sc_adapter;
+	sc->sc_channel.chan_bustype = &scsi_bustype;
+	sc->sc_channel.chan_channel = 0;
+	sc->sc_channel.chan_ntargets = OOSIOP_NTGT;
+	sc->sc_channel.chan_nluns = 8;
+	sc->sc_channel.chan_id = sc->sc_id;
+
+	/*
+	 * Now try to attach all the sub devices.
+	 */
+	config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
+}
+
+static int
+oosiop_alloc_cb(struct oosiop_softc *sc, int ncb)
+{
+	struct oosiop_cb *cb;
+	struct oosiop_xfer *xfer;
+	bus_size_t xfersize;
+	bus_dma_segment_t seg;
+	int i, s, err, nseg;
+
+	/*
+	 * Allocate oosiop_cb.
+	 */
+	cb = malloc(sizeof(struct oosiop_cb) * ncb, M_DEVBUF, M_NOWAIT|M_ZERO);
+	if (cb == NULL) {
+		printf(": failed to allocate cb memory\n");
+		return (ENOMEM);
+	}
+
+	/*
+	 * Allocate DMA-safe memory for the oosiop_xfer and map it.
+	 */
+	xfersize = sizeof(struct oosiop_xfer) * ncb;
+	err = bus_dmamem_alloc(sc->sc_dmat, xfersize, PAGE_SIZE, 0, &seg, 1,
+	    &nseg, BUS_DMA_NOWAIT);
+	if (err) {
+		printf(": failed to allocate xfer block memory, err=%d\n", err);
+		return (err);
+	}
+	err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, xfersize,
+	    (caddr_t *)&xfer, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
+	if (err) {
+		printf(": failed to map xfer block memory, err=%d\n", err);
+		return (err);
+	}
+
+	/* Initialize each command block */
+	for (i = 0; i < ncb; i++) {
+		err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE,
+		    0, BUS_DMA_NOWAIT, &cb->cmddma);
+		if (err) {
+			printf(": failed to create cmddma map, err=%d\n", err);
+			return (err);
+		}
+		err = bus_dmamap_create(sc->sc_dmat, OOSIOP_MAX_XFER,
+		    OOSIOP_NSG, OOSIOP_DBC_MAX, 0, BUS_DMA_NOWAIT,
+		    &cb->datadma);
+		if (err) {
+			printf(": failed to create datadma map, err=%d\n", err);
+			return (err);
+		}
+
+		err = bus_dmamap_create(sc->sc_dmat,
+		    sizeof(struct oosiop_xfer), 1, sizeof(struct oosiop_xfer),
+		    0, BUS_DMA_NOWAIT, &cb->xferdma);
+		if (err) {
+			printf(": failed to create xfer block map, err=%d\n",
+			    err);
+			return (err);
+		}
+		err = bus_dmamap_load(sc->sc_dmat, cb->xferdma, xfer,
+		    sizeof(struct oosiop_xfer), NULL, BUS_DMA_NOWAIT);
+		if (err) {
+			printf(": failed to load xfer block, err=%d\n", err);
+			return (err);
+		}
+
+		cb->xfer = xfer;
+
+		s = splbio();
+		TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
+		splx(s);
+
+		cb++;
+		xfer++;
+	}
+
+	return (0);
+}
+
+static __inline void
+oosiop_relocate_io(struct oosiop_softc *sc, bus_addr_t addr)
+{
+	u_int32_t dcmd;
+	int32_t dsps;
+
+	dcmd = le32toh(sc->sc_scr[addr / 4 + 0]);
+	dsps = le32toh(sc->sc_scr[addr / 4 + 1]);
+
+	/* convert relative to absolute */
+	if (dcmd & 0x04000000) {
+		dcmd &= ~0x04000000;
+#if 0
+		/*
+		 * sign extention isn't needed here because
+		 * ncr53cxxx.c generates 32 bit dsps.
+		 */
+		dsps <<= 8;
+		dsps >>= 8;
+#endif
+		sc->sc_scr[addr / 4 + 0] = htole32(dcmd);
+		dsps += addr + 8;
+	}
+
+	sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase);
+}
+
+static __inline void
+oosiop_relocate_tc(struct oosiop_softc *sc, bus_addr_t addr)
+{
+	u_int32_t dcmd;
+	int32_t dsps;
+
+	dcmd = le32toh(sc->sc_scr[addr / 4 + 0]);
+	dsps = le32toh(sc->sc_scr[addr / 4 + 1]);
+
+	/* convert relative to absolute */
+	if (dcmd & 0x00800000) {
+		dcmd &= ~0x00800000;
+		sc->sc_scr[addr / 4] = htole32(dcmd);
+#if 0
+		/*
+		 * sign extention isn't needed here because
+		 * ncr53cxxx.c generates 32 bit dsps.
+		 */
+		dsps <<= 8;
+		dsps >>= 8;
+#endif
+		dsps += addr + 8;
+	}
+
+	sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase);
+}
+
+static __inline void
+oosiop_fixup_select(struct oosiop_softc *sc, bus_addr_t addr, int id)
+{
+	u_int32_t dcmd;
+
+	dcmd = le32toh(sc->sc_scr[addr / 4]);
+	dcmd &= 0xff00ffff;
+	dcmd |= 0x00010000 << id;
+	sc->sc_scr[addr / 4] = htole32(dcmd);
+}
+
+static __inline void
+oosiop_fixup_jump(struct oosiop_softc *sc, bus_addr_t addr, bus_addr_t dst)
+{
+
+	sc->sc_scr[addr / 4 + 1] = htole32(dst);
+}
+
+static __inline void
+oosiop_fixup_move(struct oosiop_softc *sc, bus_addr_t addr, bus_size_t dbc,
+    bus_addr_t dsps)
+{
+	u_int32_t dcmd;
+
+	dcmd = le32toh(sc->sc_scr[addr / 4]);
+	dcmd &= 0xff000000;
+	dcmd |= dbc & 0x00ffffff;
+	sc->sc_scr[addr / 4 + 0] = htole32(dcmd);
+	sc->sc_scr[addr / 4 + 1] = htole32(dsps);
+}
+
+static void
+oosiop_load_script(struct oosiop_softc *sc)
+{
+	int i;
+
+	/* load script */
+	for (i = 0; i < sizeof(oosiop_script) / sizeof(oosiop_script[0]); i++)
+		sc->sc_scr[i] = htole32(oosiop_script[i]);
+
+	/* relocate script */
+	for (i = 0; i < (sizeof(oosiop_script) / 8); i++) {
+		switch (oosiop_script[i * 2] >> 27) {
+		case 0x08:	/* select */
+		case 0x0a:	/* wait reselect */
+			oosiop_relocate_io(sc, i * 8);
+			break;
+		case 0x10:	/* jump */
+		case 0x11:	/* call */
+			oosiop_relocate_tc(sc, i * 8);
+			break;
+		}
+	}
+
+	oosiop_fixup_move(sc, Ent_p_resel_msgin_move, 1, sc->sc_reselbuf);
+	OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
+}
+
+static void
+oosiop_setup_sgdma(struct oosiop_softc *sc, struct oosiop_cb *cb)
+{
+	int i, n, off;
+	struct oosiop_xfer *xfer;
+
+	OOSIOP_XFERSCR_SYNC(sc, cb,
+	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+	off = cb->curdp;
+	xfer = cb->xfer;
+
+	/* Find start segment */
+	if (cb->xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
+		for (i = 0; i < cb->datadma->dm_nsegs; i++) {
+			if (off < cb->datadma->dm_segs[i].ds_len)
+				break;
+			off -= cb->datadma->dm_segs[i].ds_len;
+		}
+	}
+
+	/* build MOVE block */
+	if (cb->xs->xs_control & XS_CTL_DATA_IN) {
+		n = 0;
+		while (i < cb->datadma->dm_nsegs) {
+			xfer->datain_scr[n * 2 + 0] = htole32(0x09000000 |
+			    (cb->datadma->dm_segs[i].ds_len - off));
+			xfer->datain_scr[n * 2 + 1] =
+			     htole32(cb->datadma->dm_segs[i].ds_addr + off);
+			n++;
+			i++;
+			off = 0;
+		}
+		xfer->datain_scr[n * 2 + 0] = htole32(0x80080000);
+		xfer->datain_scr[n * 2 + 1] =
+		    htole32(sc->sc_scrbase + Ent_phasedispatch);
+	} else {
+		xfer->datain_scr[0] = htole32(0x98080000);
+		xfer->datain_scr[1] = htole32(DATAIN_TRAP);
+	}
+
+	if (cb->xs->xs_control & XS_CTL_DATA_OUT) {
+		n = 0;
+		while (i < cb->datadma->dm_nsegs) {
+			xfer->dataout_scr[n * 2 + 0] = htole32(0x08000000 |
+			    (cb->datadma->dm_segs[i].ds_len - off));
+			xfer->dataout_scr[n * 2 + 1] =
+			    htole32(cb->datadma->dm_segs[i].ds_addr + off);
+			n++;
+			i++;
+			off = 0;
+		}
+		xfer->dataout_scr[n * 2 + 0] = htole32(0x80080000);
+		xfer->dataout_scr[n * 2 + 1] =
+		    htole32(sc->sc_scrbase + Ent_phasedispatch);
+	} else {
+		xfer->dataout_scr[0] = htole32(0x98080000);
+		xfer->dataout_scr[1] = htole32(DATAOUT_TRAP);
+	}
+	OOSIOP_XFERSCR_SYNC(sc, cb,
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+}
+
+/*
+ * Setup DMA pointer into script.
+ */
+static void
+oosiop_setup_dma(struct oosiop_softc *sc)
+{
+	struct oosiop_cb *cb;
+	bus_addr_t xferbase;
+
+	cb = sc->sc_curcb;
+	xferbase = cb->xferdma->dm_segs[0].ds_addr;
+
+	OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
+
+	oosiop_fixup_select(sc, Ent_p_select, cb->id);
+	oosiop_fixup_jump(sc, Ent_p_datain_jump, xferbase + 
+	    offsetof(struct oosiop_xfer, datain_scr[0]));
+	oosiop_fixup_jump(sc, Ent_p_dataout_jump, xferbase +
+	    offsetof(struct oosiop_xfer, dataout_scr[0]));
+	oosiop_fixup_move(sc, Ent_p_msgin_move, 1, xferbase +
+	    offsetof(struct oosiop_xfer, msgin[0]));
+	oosiop_fixup_move(sc, Ent_p_extmsglen_move, 1, xferbase +
+	    offsetof(struct oosiop_xfer, msgin[1]));
+	oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen, xferbase +
+	    offsetof(struct oosiop_xfer, msgout[0]));
+	oosiop_fixup_move(sc, Ent_p_status_move, 1, xferbase +
+	    offsetof(struct oosiop_xfer, status));
+	oosiop_fixup_move(sc, Ent_p_cmdout_move, cb->xs->cmdlen,
+	    cb->cmddma->dm_segs[0].ds_addr);
+
+	OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
+}
+
+static void
+oosiop_flush_fifo(struct oosiop_softc *sc)
+{
+
+	oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) |
+	    OOSIOP_DFIFO_FLF);
+	while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) !=
+	    OOSIOP_CTEST1_FMT)
+		;
+	oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) &
+	    ~OOSIOP_DFIFO_FLF);
+}
+
+static void
+oosiop_clear_fifo(struct oosiop_softc *sc)
+{
+
+	oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) |
+	    OOSIOP_DFIFO_CLF);
+	while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) !=
+	    OOSIOP_CTEST1_FMT)
+		;
+	oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) &
+	    ~OOSIOP_DFIFO_CLF);
+}
+
+static void
+oosiop_phasemismatch(struct oosiop_softc *sc)
+{
+	struct oosiop_cb *cb;
+	u_int32_t dsp, dbc, n, i, len;
+	u_int8_t dfifo, sstat1;
+
+	cb = sc->sc_curcb;
+	if (cb == NULL)
+		return;
+
+	dsp = oosiop_read_4(sc, OOSIOP_DSP);
+	dbc = oosiop_read_4(sc, OOSIOP_DBC) & OOSIOP_DBC_MAX;
+	len = 0;
+
+	n = dsp - cb->xferdma->dm_segs[0].ds_addr - 8;
+	if (n >= offsetof(struct oosiop_xfer, datain_scr[0]) &&
+	    n < offsetof(struct oosiop_xfer, datain_scr[OOSIOP_NSG * 2])) {
+		n -= offsetof(struct oosiop_xfer, datain_scr[0]);
+		n >>= 3;
+		OOSIOP_DINSCR_SYNC(sc, cb,
+		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+		for (i = 0; i <= n; i++)
+			len += le32toh(cb->xfer->datain_scr[i * 2]) &
+			    0x00ffffff;
+		OOSIOP_DINSCR_SYNC(sc, cb,
+		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+		/* All data in the chip are already flushed */
+	} else if (n >= offsetof(struct oosiop_xfer, dataout_scr[0]) &&
+	    n < offsetof(struct oosiop_xfer, dataout_scr[OOSIOP_NSG * 2])) {
+		n -= offsetof(struct oosiop_xfer, dataout_scr[0]);
+		n >>= 3;
+		OOSIOP_DOUTSCR_SYNC(sc, cb,
+		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+		for (i = 0; i <= n; i++)
+			len += le32toh(cb->xfer->dataout_scr[i * 2]) &
+			    0x00ffffff;
+		OOSIOP_DOUTSCR_SYNC(sc, cb,
+		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+		dfifo = oosiop_read_1(sc, OOSIOP_DFIFO);
+		dbc += ((dfifo & OOSIOP_DFIFO_BO) - (dbc & OOSIOP_DFIFO_BO)) &
+		    OOSIOP_DFIFO_BO;
+
+		sstat1 = oosiop_read_1(sc, OOSIOP_SSTAT1);
+		if (sstat1 & OOSIOP_SSTAT1_OLF)
+			dbc++;
+		if ((sc->sc_tgt[cb->id].sxfer != 0) && 
+		    (sstat1 & OOSIOP_SSTAT1_ORF) != 0)
+			dbc++;
+
+		oosiop_clear_fifo(sc);
+	} else {
+		printf("%s: phase mismatch addr=%08x\n", sc->sc_dev.dv_xname,
+		    oosiop_read_4(sc, OOSIOP_DSP) - 8);
+		oosiop_clear_fifo(sc);
+		return;
+	}
+
+	len -= dbc;
+	if (len) {
+		cb->curdp += len;
+		oosiop_setup_sgdma(sc, cb);
+	}
+}
+
+static void
+oosiop_setup_syncxfer(struct oosiop_softc *sc)
+{
+	int id;
+
+	id = sc->sc_curcb->id;
+	if (sc->sc_chip != OOSIOP_700)
+		oosiop_write_1(sc, OOSIOP_SBCL, sc->sc_tgt[id].scf);
+
+	oosiop_write_1(sc, OOSIOP_SXFER, sc->sc_tgt[id].sxfer);
+}
+
+static void
+oosiop_set_syncparam(struct oosiop_softc *sc, int id, int period, int offset)
+{
+	int i, p;
+	struct scsipi_xfer_mode xm;
+
+	xm.xm_target = id;
+	xm.xm_mode = 0;
+	xm.xm_period = 0;
+	xm.xm_offset = 0;
+
+	if (offset == 0) {
+		/* Asynchronous */
+		sc->sc_tgt[id].scf = 0;
+		sc->sc_tgt[id].sxfer = 0;
+	} else {
+		/* Synchronous */
+		if (sc->sc_chip == OOSIOP_700) {
+			for (i = 4; i < 12; i++) {
+				p = oosiop_period(sc, i, sc->sc_ccf);
+				if (p >= period)
+					break;
+			}
+			if (i == 12) {
+				printf("%s: target %d period too large\n",
+				    sc->sc_dev.dv_xname, id);
+				i = 11;	/* XXX */
+			}
+			sc->sc_tgt[id].scf = 0;
+			sc->sc_tgt[id].sxfer = ((i - 4) << 4) | offset;
+		} else {
+			for (i = 0; i < NSYNCTBL; i++) {
+				p = oosiop_period(sc, synctbl[i].tp + 4,
+				    (synctbl[i].scf + 1) * 5);
+				if (p >= period)
+					break;
+			}
+			if (i == NSYNCTBL) {
+				printf("%s: target %d period too large\n",
+				    sc->sc_dev.dv_xname, id);
+				i = NSYNCTBL - 1;	/* XXX */
+			}
+			sc->sc_tgt[id].scf = synctbl[i].scf;
+			sc->sc_tgt[id].sxfer = (synctbl[i].tp << 4) | offset;
+		}
+
+		xm.xm_mode |= PERIPH_CAP_SYNC;
+		xm.xm_period = period;
+		xm.xm_offset = offset;
+	}
+
+	scsipi_async_event(&sc->sc_channel, ASYNC_EVENT_XFER_MODE, &xm);
+}
+
+static void
+oosiop_minphys(struct buf *bp)
+{
+
+	if (bp->b_bcount > OOSIOP_MAX_XFER)
+		bp->b_bcount = OOSIOP_MAX_XFER;
+	minphys(bp);
+}
+
+static void
+oosiop_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
+    void *arg)
+{
+	struct scsipi_xfer *xs;
+	struct oosiop_softc *sc;
+	struct oosiop_cb *cb;
+	struct oosiop_xfer *xfer;
+	struct scsipi_xfer_mode *xm;
+	int s, err;
+
+	sc = (struct oosiop_softc *)chan->chan_adapter->adapt_dev;
+
+	switch (req) {
+	case ADAPTER_REQ_RUN_XFER:
+		xs = arg;
+
+		s = splbio();
+		cb = TAILQ_FIRST(&sc->sc_free_cb);
+		TAILQ_REMOVE(&sc->sc_free_cb, cb, chain);
+		splx(s);
+
+		cb->xs = xs;
+		cb->flags = 0;
+		cb->id = xs->xs_periph->periph_target;
+		cb->lun = xs->xs_periph->periph_lun;
+		cb->curdp = 0;
+		cb->savedp = 0;
+		xfer = cb->xfer;
+
+		/* Setup SCSI command buffer DMA */
+		err = bus_dmamap_load(sc->sc_dmat, cb->cmddma, xs->cmd,
+		    xs->cmdlen, NULL, ((xs->xs_control & XS_CTL_NOSLEEP) ?
+		    BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | BUS_DMA_WRITE);
+		if (err) {
+			printf("%s: unable to load cmd DMA map: %d",
+			    sc->sc_dev.dv_xname, err);
+			xs->error = XS_RESOURCE_SHORTAGE;
+			TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
+			scsipi_done(xs);
+			return;
+		}
+		bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, xs->cmdlen,
+		    BUS_DMASYNC_PREWRITE);
+
+		/* Setup data buffer DMA */
+		if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
+			err = bus_dmamap_load(sc->sc_dmat, cb->datadma,
+			    xs->data, xs->datalen, NULL,
+			    ((xs->xs_control & XS_CTL_NOSLEEP) ?
+			    BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
+			    BUS_DMA_STREAMING |
+			    ((xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMA_READ :
+			    BUS_DMA_WRITE));
+			if (err) {
+				printf("%s: unable to load data DMA map: %d",
+				    sc->sc_dev.dv_xname, err);
+				xs->error = XS_RESOURCE_SHORTAGE;
+				bus_dmamap_unload(sc->sc_dmat, cb->cmddma);
+				TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
+				scsipi_done(xs);
+				return;
+			}
+			bus_dmamap_sync(sc->sc_dmat, cb->datadma,
+			    0, xs->datalen,
+			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+		}
+
+		oosiop_setup_sgdma(sc, cb);
+
+		/* Setup msgout buffer */
+		OOSIOP_XFERMSG_SYNC(sc, cb,
+		   BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+		xfer->msgout[0] = MSG_IDENTIFY(cb->lun,
+		    (xs->xs_control & XS_CTL_REQSENSE) == 0);
+		cb->msgoutlen = 1;
+
+		if (sc->sc_tgt[cb->id].flags & TGTF_SYNCNEG) {
+			/* Send SDTR */
+			xfer->msgout[1] = MSG_EXTENDED;
+			xfer->msgout[2] = MSG_EXT_SDTR_LEN;
+			xfer->msgout[3] = MSG_EXT_SDTR;
+			xfer->msgout[4] = sc->sc_minperiod;
+			xfer->msgout[5] = OOSIOP_MAX_OFFSET;
+			cb->msgoutlen = 6;
+			sc->sc_tgt[cb->id].flags &= ~TGTF_SYNCNEG;
+			sc->sc_tgt[cb->id].flags |= TGTF_WAITSDTR;
+		}
+
+		xfer->status = SCSI_OOSIOP_NOSTATUS;
+
+		OOSIOP_XFERMSG_SYNC(sc, cb,
+		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+		s = splbio();
+
+		TAILQ_INSERT_TAIL(&sc->sc_cbq, cb, chain);
+
+		if (!sc->sc_active) {
+			/* Abort script to start selection */
+			oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT);
+		}
+		if (xs->xs_control & XS_CTL_POLL) {
+			/* Poll for command completion */
+			while ((xs->xs_status & XS_STS_DONE) == 0) {
+				delay(1000);
+				oosiop_intr(sc);
+			}
+		}
+
+		splx(s);
+
+		return;
+
+	case ADAPTER_REQ_GROW_RESOURCES:
+		return;
+
+	case ADAPTER_REQ_SET_XFER_MODE:
+		xm = arg;
+		if (xm->xm_mode & PERIPH_CAP_SYNC)
+			sc->sc_tgt[xm->xm_target].flags |= TGTF_SYNCNEG;
+		else
+			oosiop_set_syncparam(sc, xm->xm_target, 0, 0);
+
+		return;
+	}
+}
+
+static void
+oosiop_done(struct oosiop_softc *sc, struct oosiop_cb *cb)
+{
+	struct scsipi_xfer *xs;
+
+	xs = cb->xs;
+	if (cb == sc->sc_curcb)
+		sc->sc_curcb = NULL;
+	if (cb == sc->sc_lastcb)
+		sc->sc_lastcb = NULL;
+	sc->sc_tgt[cb->id].nexus = NULL;
+
+	callout_stop(&xs->xs_callout);
+
+	bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, xs->cmdlen,
+	    BUS_DMASYNC_POSTWRITE);
+	bus_dmamap_unload(sc->sc_dmat, cb->cmddma);
+
+	if (xs->datalen > 0) {
+		bus_dmamap_sync(sc->sc_dmat, cb->datadma, 0, xs->datalen,
+		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+		bus_dmamap_unload(sc->sc_dmat, cb->datadma);
+	}
+
+	xs->status = cb->xfer->status;
+	xs->resid = 0;	/* XXX */
+
+	if (cb->flags & CBF_SELTOUT)
+		xs->error = XS_SELTIMEOUT;
+	else if (cb->flags & CBF_TIMEOUT)
+		xs->error = XS_TIMEOUT;
+	else switch (xs->status) {
+	case SCSI_OK:
+		xs->error = XS_NOERROR;
+		break;
+
+	case SCSI_BUSY:
+	case SCSI_CHECK:
+		xs->error = XS_BUSY;
+		break;
+	case SCSI_OOSIOP_NOSTATUS:
+		/* the status byte was not updated, cmd was aborted. */
+		xs->error = XS_SELTIMEOUT;
+		break;
+
+	default:
+		xs->error = XS_RESET;
+		break;
+	}
+
+	scsipi_done(xs);
+
+	/* Put it on the free list. */
+	TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
+}
+
+static void
+oosiop_timeout(void *arg)
+{
+	struct oosiop_cb *cb;
+	struct scsipi_periph *periph;
+	struct oosiop_softc *sc;
+	int s;
+
+	cb = arg;
+	periph = cb->xs->xs_periph;
+	sc = (void *)periph->periph_channel->chan_adapter->adapt_dev;
+	scsipi_printaddr(periph);
+	printf("timed out\n");
+
+	s = splbio();
+
+	cb->flags |= CBF_TIMEOUT;
+	oosiop_done(sc, cb);
+
+	splx(s);
+}
+
+static void
+oosiop_reset(struct oosiop_softc *sc)
+{
+	int i, s;
+
+	s = splbio();
+
+	/* Stop SCRIPTS processor */
+	oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT);
+	delay(100);
+	oosiop_write_1(sc, OOSIOP_ISTAT, 0);
+
+	/* Reset the chip */
+	oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl | OOSIOP_DCNTL_RST);
+	delay(100);
+	oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl);
+	delay(10000);
+
+	/* Set up various chip parameters */
+	oosiop_write_1(sc, OOSIOP_SCNTL0, OOSIOP_ARB_FULL | OOSIOP_SCNTL0_EPG);
+	oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_ESR);
+	oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl);
+	oosiop_write_1(sc, OOSIOP_DMODE, OOSIOP_DMODE_BL_8);
+	oosiop_write_1(sc, OOSIOP_SCID, OOSIOP_SCID_VALUE(sc->sc_id));
+	oosiop_write_1(sc, OOSIOP_DWT, 0xff);	/* Enable DMA timeout */
+	oosiop_write_1(sc, OOSIOP_CTEST7, 0);
+	oosiop_write_1(sc, OOSIOP_SXFER, 0);
+
+	/* Clear all interrupts */
+	(void)oosiop_read_1(sc, OOSIOP_SSTAT0);
+	(void)oosiop_read_1(sc, OOSIOP_SSTAT1);
+	(void)oosiop_read_1(sc, OOSIOP_DSTAT);
+
+	/* Enable interrupts */
+	oosiop_write_1(sc, OOSIOP_SIEN,
+	    OOSIOP_SIEN_M_A | OOSIOP_SIEN_STO | OOSIOP_SIEN_SGE |
+	    OOSIOP_SIEN_UDC | OOSIOP_SIEN_RST | OOSIOP_SIEN_PAR);
+	oosiop_write_1(sc, OOSIOP_DIEN,
+	    OOSIOP_DIEN_ABRT | OOSIOP_DIEN_SSI | OOSIOP_DIEN_SIR |
+	    OOSIOP_DIEN_WTD | OOSIOP_DIEN_IID);
+
+	/* Set target state to asynchronous */
+	for (i = 0; i < OOSIOP_NTGT; i++) {
+		sc->sc_tgt[i].flags = 0;
+		sc->sc_tgt[i].scf = 0;
+		sc->sc_tgt[i].sxfer = 0;
+	}
+
+	splx(s);
+}
+
+static void
+oosiop_reset_bus(struct oosiop_softc *sc)
+{
+	int s, i;
+
+	s = splbio();
+
+	/* Assert SCSI RST */
+	oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_RST);
+	delay(25);	/* Reset hold time (25us) */
+	oosiop_write_1(sc, OOSIOP_SCNTL1, 0);
+
+	/* Remove all nexuses */
+	for (i = 0; i < OOSIOP_NTGT; i++) {
+		if (sc->sc_tgt[i].nexus) {
+			sc->sc_tgt[i].nexus->xfer->status =
+			    SCSI_OOSIOP_NOSTATUS; /* XXX */
+			oosiop_done(sc, sc->sc_tgt[i].nexus);
+		}
+	}
+
+	sc->sc_curcb = NULL;
+
+	delay(250000);	/* Reset to selection (250ms) */
+
+	splx(s);
+}
+
+/*
+ * interrupt handler
+ */
+int
+oosiop_intr(struct oosiop_softc *sc)
+{
+	struct oosiop_cb *cb;
+	u_int32_t dcmd;
+	int timeout;
+	u_int8_t istat, dstat, sstat0;
+
+	istat = oosiop_read_1(sc, OOSIOP_ISTAT);
+
+	if ((istat & (OOSIOP_ISTAT_SIP | OOSIOP_ISTAT_DIP)) == 0)
+		return (0);
+
+	sc->sc_nextdsp = Ent_wait_reselect;
+
+	/* DMA interrupts */
+	if (istat & OOSIOP_ISTAT_DIP) {
+		oosiop_write_1(sc, OOSIOP_ISTAT, 0);
+
+		dstat = oosiop_read_1(sc, OOSIOP_DSTAT);
+
+		if (dstat & OOSIOP_DSTAT_ABRT) {
+			sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) -
+			    sc->sc_scrbase - 8;
+
+			if (sc->sc_nextdsp == Ent_p_resel_msgin_move &&
+			    (oosiop_read_1(sc, OOSIOP_SBCL) & OOSIOP_ACK)) {
+				if ((dstat & OOSIOP_DSTAT_DFE) == 0)
+					oosiop_flush_fifo(sc);
+				sc->sc_nextdsp += 8;
+			}
+		}
+
+		if (dstat & OOSIOP_DSTAT_SSI) {
+			sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) -
+			    sc->sc_scrbase;
+			printf("%s: single step %08x\n", sc->sc_dev.dv_xname,
+			    sc->sc_nextdsp);
+		}
+
+		if (dstat & OOSIOP_DSTAT_SIR) {
+			if ((dstat & OOSIOP_DSTAT_DFE) == 0)
+				oosiop_flush_fifo(sc);
+			oosiop_scriptintr(sc);
+		}
+
+		if (dstat & OOSIOP_DSTAT_WTD) {
+			printf("%s: DMA time out\n", sc->sc_dev.dv_xname);
+			oosiop_reset(sc);
+		}
+
+		if (dstat & OOSIOP_DSTAT_IID) {
+			dcmd = oosiop_read_4(sc, OOSIOP_DBC);
+			if ((dcmd & 0xf8000000) == 0x48000000) {
+				printf("%s: REQ asserted on WAIT DISCONNECT\n",
+				    sc->sc_dev.dv_xname);
+				sc->sc_nextdsp = Ent_phasedispatch; /* XXX */
+			} else {
+				printf("%s: invalid SCRIPTS instruction "
+				    "addr=%08x dcmd=%08x dsps=%08x\n",
+				    sc->sc_dev.dv_xname,
+				    oosiop_read_4(sc, OOSIOP_DSP) - 8, dcmd,
+				    oosiop_read_4(sc, OOSIOP_DSPS));
+				oosiop_reset(sc);
+				OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
+				oosiop_load_script(sc);
+			}
+		}
+
+		if ((dstat & OOSIOP_DSTAT_DFE) == 0)
+			oosiop_clear_fifo(sc);
+	}
+
+	/* SCSI interrupts */
+	if (istat & OOSIOP_ISTAT_SIP) {
+		if (istat & OOSIOP_ISTAT_DIP)
+			delay(1);
+		sstat0 = oosiop_read_1(sc, OOSIOP_SSTAT0);
+
+		if (sstat0 & OOSIOP_SSTAT0_M_A) {
+			/* SCSI phase mismatch during MOVE operation */
+			oosiop_phasemismatch(sc);
+			sc->sc_nextdsp = Ent_phasedispatch;
+		}
+
+		if (sstat0 & OOSIOP_SSTAT0_STO) {
+			if (sc->sc_curcb) {
+				sc->sc_curcb->flags |= CBF_SELTOUT;
+				oosiop_done(sc, sc->sc_curcb);
+			}
+		}
+
+		if (sstat0 & OOSIOP_SSTAT0_SGE) {
+			printf("%s: SCSI gross error\n", sc->sc_dev.dv_xname);
+			oosiop_reset(sc);
+		}
+
+		if (sstat0 & OOSIOP_SSTAT0_UDC) {
+			/* XXX */
+			if (sc->sc_curcb) {
+				printf("%s: unexpected disconnect\n",
+				    sc->sc_dev.dv_xname);
+				oosiop_done(sc, sc->sc_curcb);
+			}
+		}
+
+		if (sstat0 & OOSIOP_SSTAT0_RST)
+			oosiop_reset(sc);
+
+		if (sstat0 & OOSIOP_SSTAT0_PAR)
+			printf("%s: parity error\n", sc->sc_dev.dv_xname);
+	}
+
+	/* Start next command if available */
+	if (sc->sc_nextdsp == Ent_wait_reselect && TAILQ_FIRST(&sc->sc_cbq)) {
+		cb = sc->sc_curcb = TAILQ_FIRST(&sc->sc_cbq);
+		TAILQ_REMOVE(&sc->sc_cbq, cb, chain);
+		sc->sc_tgt[cb->id].nexus = cb;
+
+		oosiop_setup_dma(sc);
+		oosiop_setup_syncxfer(sc);
+		sc->sc_lastcb = cb;
+		sc->sc_nextdsp = Ent_start_select;
+
+		/* Schedule timeout */
+		if ((cb->xs->xs_control & XS_CTL_POLL) == 0) {
+			timeout = mstohz(cb->xs->timeout) + 1;
+			callout_reset(&cb->xs->xs_callout, timeout,
+			    oosiop_timeout, cb);
+		}
+	}
+
+	sc->sc_active = (sc->sc_nextdsp != Ent_wait_reselect);
+
+	/* Restart script */
+	oosiop_write_4(sc, OOSIOP_DSP, sc->sc_nextdsp + sc->sc_scrbase);
+
+	return (1);
+}
+
+static void
+oosiop_scriptintr(struct oosiop_softc *sc)
+{
+	struct oosiop_cb *cb;
+	u_int32_t icode;
+	u_int32_t dsp;
+	int i;
+	u_int8_t sfbr, resid, resmsg;
+
+	cb = sc->sc_curcb;
+	icode = oosiop_read_4(sc, OOSIOP_DSPS);
+
+	switch (icode) {
+	case A_int_done:
+		if (cb)
+			oosiop_done(sc, cb);
+		break;
+
+	case A_int_msgin:
+		if (cb)
+			oosiop_msgin(sc, cb);
+		break;
+
+	case A_int_extmsg:
+		/* extended message in DMA setup request */
+		sfbr = oosiop_read_1(sc, OOSIOP_SFBR);
+		OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
+		oosiop_fixup_move(sc, Ent_p_extmsgin_move, sfbr,
+		    cb->xferdma->dm_segs[0].ds_addr +
+		    offsetof(struct oosiop_xfer, msgin[2]));
+		OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
+		sc->sc_nextdsp = Ent_rcv_extmsg;
+		break;
+
+	case A_int_resel:
+		/* reselected */
+		resid = oosiop_read_1(sc, OOSIOP_SFBR);
+		for (i = 0; i < OOSIOP_NTGT; i++)
+			if (resid & (1 << i))
+				break;
+		if (i == OOSIOP_NTGT) {
+			printf("%s: missing reselection target id\n",
+			    sc->sc_dev.dv_xname);
+			break;
+		}
+		sc->sc_resid = i;
+		sc->sc_nextdsp = Ent_wait_resel_identify;
+
+		if (cb) {
+			/* Current command was lost arbitration */
+			sc->sc_tgt[cb->id].nexus = NULL;
+			TAILQ_INSERT_HEAD(&sc->sc_cbq, cb, chain);
+			sc->sc_curcb = NULL;
+		}
+
+		break;
+
+	case A_int_res_id:
+		cb = sc->sc_tgt[sc->sc_resid].nexus;
+		resmsg = oosiop_read_1(sc, OOSIOP_SFBR);
+		if (MSG_ISIDENTIFY(resmsg) && cb &&
+		    (resmsg & MSG_IDENTIFY_LUNMASK) == cb->lun) {
+			sc->sc_curcb = cb;
+			if (cb != sc->sc_lastcb) {
+				oosiop_setup_dma(sc);
+				oosiop_setup_syncxfer(sc);
+				sc->sc_lastcb = cb;
+			}
+			if (cb->curdp != cb->savedp) {
+				cb->curdp = cb->savedp;
+				oosiop_setup_sgdma(sc, cb);
+			}
+			sc->sc_nextdsp = Ent_ack_msgin;
+		} else {
+			/* Reselection from invalid target */
+			oosiop_reset_bus(sc);
+		}
+		break;
+
+	case A_int_resfail:
+		/* reselect failed */
+		break;
+
+	case A_int_disc:
+		/* disconnected */
+		sc->sc_curcb = NULL;
+		break;
+
+	case A_int_err:
+		/* generic error */
+		dsp = oosiop_read_4(sc, OOSIOP_DSP);
+		printf("%s: script error at 0x%08x\n", sc->sc_dev.dv_xname,
+		    dsp - 8);
+		sc->sc_curcb = NULL;
+		break;
+
+	case DATAIN_TRAP:
+		printf("%s: unexpected datain\n", sc->sc_dev.dv_xname);
+		/* XXX: need to reset? */
+		break;
+
+	case DATAOUT_TRAP:
+		printf("%s: unexpected dataout\n", sc->sc_dev.dv_xname);
+		/* XXX: need to reset? */
+		break;
+
+	default:
+		printf("%s: unknown intr code %08x\n", sc->sc_dev.dv_xname,
+		    icode);
+		break;
+	}
+}
+
+static void
+oosiop_msgin(struct oosiop_softc *sc, struct oosiop_cb *cb)
+{
+	struct oosiop_xfer *xfer;
+	int msgout;
+
+	xfer = cb->xfer;
+	sc->sc_nextdsp = Ent_ack_msgin;
+	msgout = 0;
+
+	OOSIOP_XFERMSG_SYNC(sc, cb,
+	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+	switch (xfer->msgin[0]) {
+	case MSG_EXTENDED:
+		switch (xfer->msgin[2]) {
+		case MSG_EXT_SDTR:
+			if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) {
+				/* Host initiated SDTR */
+				sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR;
+			} else {
+				/* Target initiated SDTR */
+				if (xfer->msgin[3] < sc->sc_minperiod)
+					xfer->msgin[3] = sc->sc_minperiod;
+				if (xfer->msgin[4] > OOSIOP_MAX_OFFSET)
+					xfer->msgin[4] = OOSIOP_MAX_OFFSET;
+				xfer->msgout[0] = MSG_EXTENDED;
+				xfer->msgout[1] = MSG_EXT_SDTR_LEN;
+				xfer->msgout[2] = MSG_EXT_SDTR;
+				xfer->msgout[3] = xfer->msgin[3];
+				xfer->msgout[4] = xfer->msgin[4];
+				cb->msgoutlen = 5;
+				msgout = 1;
+			}
+			oosiop_set_syncparam(sc, cb->id, (int)xfer->msgin[3],
+			    (int)xfer->msgin[4]);
+			oosiop_setup_syncxfer(sc);
+			break;
+
+		default:
+			/* Reject message */
+			xfer->msgout[0] = MSG_MESSAGE_REJECT;
+			cb->msgoutlen = 1;
+			msgout = 1;
+			break;
+		}
+		break;
+
+	case MSG_SAVEDATAPOINTER:
+		cb->savedp = cb->curdp;
+		break;
+
+	case MSG_RESTOREPOINTERS:
+		if (cb->curdp != cb->savedp) {
+			cb->curdp = cb->savedp;
+			oosiop_setup_sgdma(sc, cb);
+		}
+		break;
+
+	case MSG_MESSAGE_REJECT:
+		if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) {
+			/* SDTR rejected */
+			sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR;
+			oosiop_set_syncparam(sc, cb->id, 0, 0);
+			oosiop_setup_syncxfer(sc);
+		}
+		break;
+
+	default:
+		/* Reject message */
+		xfer->msgout[0] = MSG_MESSAGE_REJECT;
+		cb->msgoutlen = 1;
+		msgout = 1;
+	}
+
+	OOSIOP_XFERMSG_SYNC(sc, cb,
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+	if (msgout) {
+		OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
+		oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen,
+		    cb->xferdma->dm_segs[0].ds_addr +
+		    offsetof(struct oosiop_xfer, msgout[0]));
+		OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
+		sc->sc_nextdsp = Ent_sendmsg;
+	}
+}
--- /dev/null	2003-04-02 23:49:50.000000000 +0900
+++ dev/ic/oosiopreg.h	2003-03-21 13:20:37.000000000 +0900
@@ -0,0 +1,327 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)siopreg.h	7.3 (Berkeley) 2/5/91
+ */
+
+/*
+ * NCR 53C700 SCSI interface hardware description.
+ *
+ * From the Mach scsi driver for the 53C700 and amiga siop driver
+ */
+
+#define	OOSIOP_SCNTL0	0x00	/* rw: SCSI control reg 0 */
+#define	OOSIOP_SCNTL1	0x01	/* rw: SCSI control reg 1 */
+#define	OOSIOP_SDID	0x02	/* rw: SCSI destination ID */
+#define	OOSIOP_SIEN	0x03	/* rw: SCSI interrupt enable */
+#define	OOSIOP_SCID	0x04	/* rw: SCSI Chip ID reg */
+#define	OOSIOP_SXFER	0x05	/* rw: SCSI Transfer reg */
+#define	OOSIOP_SODL	0x06	/* rw: SCSI Output Data Latch */
+#define	OOSIOP_SOCL	0x07	/* rw: SCSI Output Control Latch */
+#define	OOSIOP_SFBR	0x08	/* ro: SCSI First Byte Received */
+#define	OOSIOP_SIDL	0x09	/* ro: SCSI Input Data Latch */
+#define	OOSIOP_SBDL	0x0a	/* ro: SCSI Bus Data Lines */
+#define	OOSIOP_SBCL	0x0b	/* rw: SCSI Bus Control Lines */
+#define	OOSIOP_DSTAT	0x0c	/* ro: DMA status */
+#define	OOSIOP_SSTAT0	0x0d	/* ro: SCSI status reg 0 */
+#define	OOSIOP_SSTAT1	0x0e	/* ro: SCSI status reg 1 */
+#define	OOSIOP_SSTAT2	0x0f	/* ro: SCSI status reg 2 */
+#define	OOSIOP_SCRA0	0x10	/* rw: Scratch A */
+#define	OOSIOP_SCRA1	0x11
+#define	OOSIOP_SCRA2	0x12
+#define	OOSIOP_SCRA3	0x13
+#define	OOSIOP_CTEST0	0x14	/* ro: Chip test register 0 */
+#define	OOSIOP_CTEST1	0x15	/* ro: Chip test register 1 */
+#define	OOSIOP_CTEST2	0x16	/* ro: Chip test register 2 */
+#define	OOSIOP_CTEST3	0x17	/* ro: Chip test register 3 */
+#define	OOSIOP_CTEST4	0x18	/* rw: Chip test register 4 */
+#define	OOSIOP_CTEST5	0x19	/* rw: Chip test register 5 */
+#define	OOSIOP_CTEST6	0x1a	/* rw: Chip test register 6 */
+#define	OOSIOP_CTEST7	0x1b	/* rw: Chip test register 7 */
+#define	OOSIOP_TEMP	0x1c	/* rw: Temporary Stack reg */
+#define	OOSIOP_DFIFO	0x20	/* rw: DMA FIFO */
+#define	OOSIOP_ISTAT	0x21	/* rw: Interrupt Status reg */
+#define	OOSIOP_CTEST8	0x22	/* rw: Chip test register 8 */
+#define	OOSIOP_CTEST9	0x23	/* ro: Chip test register 9 */
+#define	OOSIOP_DBC	0x24	/* rw: DMA Byte Counter reg */
+#define	OOSIOP_DCMD	0x27	/* rw: DMA Command Register */
+#define	OOSIOP_DNAD	0x28	/* rw: DMA Next Address */
+#define	OOSIOP_DSP	0x2c	/* rw: DMA SCRIPTS Pointer reg */
+#define	OOSIOP_DSPS	0x30	/* rw: DMA SCRIPTS Pointer Save reg */
+#define	OOSIOP_DMODE	0x34	/* rw: DMA Mode reg */
+#define	OOSIOP_RES35	0x35
+#define	OOSIOP_RES36	0x36
+#define	OOSIOP_RES37	0x37
+#define	OOSIOP_RES38	0x38
+#define	OOSIOP_DIEN	0x39	/* rw: DMA Interrupt Enable */
+#define	OOSIOP_DWT	0x3a	/* rw: DMA Watchdog Timer */
+#define	OOSIOP_DCNTL	0x3b	/* rw: DMA Control reg */
+#define	OOSIOP_SCRB0	0x3c	/* rw: Scratch B */
+#define	OOSIOP_SCRB1	0x3d
+#define	OOSIOP_SCRB2	0x3e
+#define	OOSIOP_SCRB3	0x3f
+
+#define	OOSIOP_NREGS	0x40
+
+
+/*
+ * Register defines
+ */
+
+/* Scsi control register 0 (scntl0) */
+
+#define	OOSIOP_SCNTL0_ARB	0xc0	/* Arbitration mode */
+#define	 OOSIOP_ARB_SIMPLE	0x00
+#define	 OOSIOP_ARB_FULL	0xc0
+#define	OOSIOP_SCNTL0_START	0x20	/* Start Sequence */
+#define	OOSIOP_SCNTL0_WATN	0x10	/* (Select) With ATN */
+#define	OOSIOP_SCNTL0_EPC	0x08	/* Enable Parity Checking */
+#define	OOSIOP_SCNTL0_EPG	0x04	/* Enable Parity Generation */
+#define	OOSIOP_SCNTL0_AAP	0x02	/* Assert ATN on Parity Error */
+#define	OOSIOP_SCNTL0_TRG	0x01	/* Target Mode */
+
+/* Scsi control register 1 (scntl1) */
+
+#define	OOSIOP_SCNTL1_EXC	0x80	/* Extra Clock Cycle of data setup */
+#define	OOSIOP_SCNTL1_ADB	0x40	/* Assert Data Bus */
+#define	OOSIOP_SCNTL1_ESR	0x20	/* Enable Selection/Reselection */
+#define	OOSIOP_SCNTL1_CON	0x10	/* Connected */
+#define	OOSIOP_SCNTL1_RST	0x08	/* Assert RST */
+#define	OOSIOP_SCNTL1_AESP	0x04	/* Assert even SCSI parity */
+#define	OOSIOP_SCNTL1_SND	0x02	/* Start Send operation */
+#define	OOSIOP_SCNTL1_RCV	0x01	/* Start Receive operation */
+
+/* Scsi interrupt enable register (sien) */
+
+#define	OOSIOP_SIEN_M_A		0x80	/* Phase Mismatch or ATN active */
+#define	OOSIOP_SIEN_FC		0x40	/* Function Complete */
+#define	OOSIOP_SIEN_STO		0x20	/* (Re)Selection timeout */
+#define	OOSIOP_SIEN_SEL		0x10	/* (Re)Selected */
+#define	OOSIOP_SIEN_SGE		0x08	/* SCSI Gross Error */
+#define	OOSIOP_SIEN_UDC		0x04	/* Unexpected Disconnect */
+#define	OOSIOP_SIEN_RST		0x02	/* RST asserted */
+#define	OOSIOP_SIEN_PAR		0x01	/* Parity Error */
+
+/* Scsi chip ID (scid) */
+
+#define	OOSIOP_SCID_VALUE(i)	(1 << i)
+
+/* Scsi transfer register (sxfer) */
+
+#define	OOSIOP_SXFER_DHP	0x80	/* Disable Halt on Parity error/
+					   ATN asserted */
+#define	OOSIOP_SXFER_TP		0x70	/* Synch Transfer Period */
+					/* see specs for formulas:
+						Period = TCP * (4 + XFERP )
+						TCP = 1 + CLK + 1..2;
+					 */
+#define	OOSIOP_SXFER_MO		0x0f	/* Synch Max Offset */
+#define	OOSIOP_MAX_OFFSET	8
+
+/* Scsi output data latch register (sodl) */
+
+/* Scsi output control latch register (socl) */
+
+#define	OOSIOP_REQ		0x80	/* SCSI signal <x> asserted */
+#define	OOSIOP_ACK		0x40
+#define	OOSIOP_BSY		0x20
+#define	OOSIOP_SEL		0x10
+#define	OOSIOP_ATN		0x08
+#define	OOSIOP_MSG		0x04
+#define	OOSIOP_CD		0x02
+#define	OOSIOP_IO		0x01
+
+#define	OOSIOP_PHASE(socl)	SCSI_PHASE(socl)
+
+/* Scsi first byte received register (sfbr) */
+
+/* Scsi input data latch register (sidl) */
+
+/* Scsi bus data lines register (sbdl) */
+
+/* Scsi bus control lines register (sbcl).  Same as socl */
+
+#define	OOSIOP_SBCL_SSCF1	0x02	/* wo */
+#define	OOSIOP_SBCL_SSCF0	0x01	/* wo */
+
+/* DMA status register (dstat) */
+
+#define	OOSIOP_DSTAT_DFE	0x80	/* DMA FIFO empty */
+#define	OOSIOP_DSTAT_ABRT	0x10	/* Aborted */
+#define	OOSIOP_DSTAT_SSI	0x08	/* SCRIPT Single Step */
+#define	OOSIOP_DSTAT_SIR	0x04	/* SCRIPT Interrupt Instruction */
+#define	OOSIOP_DSTAT_WTD	0x02	/* Watchdog Timeout Detected */
+#define	OOSIOP_DSTAT_IID	0x01	/* Invalid Instruction Detected */
+
+/* Scsi status register 0 (sstat0) */
+
+#define	OOSIOP_SSTAT0_M_A	0x80	/* Phase Mismatch or ATN active */
+#define	OOSIOP_SSTAT0_FC	0x40	/* Function Complete */
+#define	OOSIOP_SSTAT0_STO	0x20	/* (Re)Selection timeout */
+#define	OOSIOP_SSTAT0_SEL	0x10	/* (Re)Selected */
+#define	OOSIOP_SSTAT0_SGE	0x08	/* SCSI Gross Error */
+#define	OOSIOP_SSTAT0_UDC	0x04	/* Unexpected Disconnect */
+#define	OOSIOP_SSTAT0_RST	0x02	/* RST asserted */
+#define	OOSIOP_SSTAT0_PAR	0x01	/* Parity Error */
+
+/* Scsi status register 1 (sstat1) */
+
+#define	OOSIOP_SSTAT1_ILF	0x80	/* Input latch (sidl) full */
+#define	OOSIOP_SSTAT1_ORF	0x40	/* output reg (sodr) full */
+#define	OOSIOP_SSTAT1_OLF	0x20	/* output latch (sodl) full */
+#define	OOSIOP_SSTAT1_AIP	0x10	/* Arbitration in progress */
+#define	OOSIOP_SSTAT1_LOA	0x08	/* Lost arbitration */
+#define	OOSIOP_SSTAT1_WOA	0x04	/* Won arbitration */
+#define	OOSIOP_SSTAT1_RST	0x02	/* SCSI RST current value */
+#define	OOSIOP_SSTAT1_SDP	0x01	/* SCSI SDP current value */
+
+/* Scsi status register 2 (sstat2) */
+
+#define	OOSIOP_SSTAT2_FF	0xf0	/* SCSI FIFO flags (bytecount) */
+#define	OOSIOP_SCSI_FIFO_DEEP	8
+#define	OOSIOP_SSTAT2_SDP	0x08	/* Latched (on REQ) SCSI SDP */
+#define	OOSIOP_SSTAT2_MSG	0x04	/* Latched SCSI phase */
+#define	OOSIOP_SSTAT2_CD	0x02
+#define	OOSIOP_SSTAT2_IO	0x01
+
+/* Chip test register 0 (ctest0) */
+
+#define	OOSIOP_CTEST0_RTRG	0x02	/* Real Target Mode */
+#define	OOSIOP_CTEST0_DDIR	0x01	/* Xfer direction (1-> from SCSI bus) */
+
+/* Chip test register 1 (ctest1) */
+
+#define	OOSIOP_CTEST1_FMT	0xf0	/* Byte empty in DMA FIFO bottom
+					   (high->byte3) */
+#define	OOSIOP_CTEST1_FFL	0x0f	/* Byte full in DMA FIFO top, same */
+
+/* Chip test register 2 (ctest2) */
+
+#define	OOSIOP_CTEST2_SOFF	0x20	/* Synch Offset compare
+					   (1-> zero Init, max Tgt) */
+#define	OOSIOP_CTEST2_SFP	0x10	/* SCSI FIFO Parity */
+#define	OOSIOP_CTEST2_DFP	0x08	/* DMA FIFO Parity */
+#define	OOSIOP_CTEST2_TEOP	0x04	/* True EOP (a-la 5380) */
+#define	OOSIOP_CTEST2_DREQ	0x02	/* DREQ status */
+#define	OOSIOP_CTEST2_DACK	0x01	/* DACK status */
+
+/* Chip test register 3 (ctest3) read-only, top of SCSI FIFO */
+
+/* Chip test register 4 (ctest4) */
+
+#define	OOSIOP_CTEST4_ZMOD	0x40	/* High-impedance outputs */
+#define	OOSIOP_CTEST4_SZM	0x20	/* ditto, SCSI "outputs" */
+#define	OOSIOP_CTEST4_SLBE	0x10	/* SCSI loobpack enable */
+#define	OOSIOP_CTEST4_SFWR	0x08	/* SCSI FIFO write enable (from sodl) */
+#define	OOSIOP_CTEST4_FBL	0x07	/* DMA FIFO Byte Lane select
+					   (from ctest6) 4->0, .. 7->3 */
+
+/* Chip test register 5 (ctest5) */
+
+#define	OOSIOP_CTEST5_ADCK	0x80	/* Clock Address Incrementor */
+#define	OOSIOP_CTEST5_BBCK	0x40	/* Clock Byte counter */
+#define	OOSIOP_CTEST5_ROFF	0x20	/* Reset SCSI offset */
+#define	OOSIOP_CTEST5_MASR	0x10	/* Master set/reset pulses
+					   (of bits 3-0) */
+#define	OOSIOP_CTEST5_DDIR	0x08	/* (re)set internal DMA direction */
+#define	OOSIOP_CTEST5_EOP	0x04	/* (re)set internal EOP */
+#define	OOSIOP_CTEST5_DREQ	0x02	/* (re)set internal REQ */
+#define	OOSIOP_CTEST5_DACK	0x01	/* (re)set internal ACK */
+
+/* Chip test register 6 (ctest6)  DMA FIFO access */
+
+/* Chip test register 7 (ctest7) */
+
+#define	OOSIOP_CTEST7_STD	0x10	/* Selection timeout disable */
+#define	OOSIOP_CTEST7_DFP	0x08	/* DMA FIFO parity bit */
+#define	OOSIOP_CTEST7_EVP	0x04	/* Even parity (to host bus) */
+#define	OOSIOP_CTEST7_DIFF	0x01	/* Differential mode */
+
+/* DMA FIFO register (dfifo) */
+
+#define	OOSIOP_DFIFO_FLF	0x80	/* Flush (spill) DMA FIFO */
+#define	OOSIOP_DFIFO_CLF	0x40	/* Clear DMA and SCSI FIFOs */
+#define	OOSIOP_DFIFO_BO		0x3f	/* FIFO byte offset counter */
+
+/* Interrupt status register (istat) */
+
+#define	OOSIOP_ISTAT_ABRT	0x80	/* Abort operation */
+#define	OOSIOP_ISTAT_CON	0x08	/* Connected */
+#define	OOSIOP_ISTAT_PRE	0x04	/* Pointer register empty */
+#define	OOSIOP_ISTAT_SIP	0x02	/* SCSI Interrupt pending */
+#define	OOSIOP_ISTAT_DIP	0x01	/* DMA Interrupt pending */
+
+/* Chip test register 8 (ctest8) */
+
+/* DMA Byte Counter register (dbc) */
+#define	OOSIOP_DBC_MAX		0x00ffffff
+
+/* DMA Mode register (dmode) */
+
+#define	OOSIOP_DMODE_BL_MASK	0xc0	/* 0->1 1->2 2->4 3->8 */
+#define	OOSIOP_DMODE_BL_1	0x00
+#define	OOSIOP_DMODE_BL_2	0x40
+#define	OOSIOP_DMODE_BL_4	0x80
+#define	OOSIOP_DMODE_BL_8	0xc0
+#define	OOSIOP_DMODE_BW16	0x20	/* Bus Width is 16 bits */
+#define	OOSIOP_DMODE_286	0x10	/* 286 mode */
+#define	OOSIOP_DMODE_IO_M	0x08	/* xfer data to memory or I/O space */
+#define	OOSIOP_DMODE_FAM	0x04	/* fixed address mode */
+#define	OOSIOP_DMODE_PIPE	0x02	/* SCRIPTS in Pipeline mode */
+#define	OOSIOP_DMODE_MAN	0x01	/* SCRIPTS in Manual start mode */
+
+/* DMA interrupt enable register (dien) */
+
+#define	OOSIOP_DIEN_BF		0x20	/* On Bus Fault */
+#define	OOSIOP_DIEN_ABRT	0x10	/* On Abort */
+#define	OOSIOP_DIEN_SSI		0x08	/* On SCRIPTS sstep */
+#define	OOSIOP_DIEN_SIR		0x04	/* On SCRIPTS intr instruction */
+#define	OOSIOP_DIEN_WTD		0x02	/* On watchdog timeout */
+#define	OOSIOP_DIEN_IID		0x01	/* On illegal instruction detected */
+
+/* DMA control register (dcntl) */
+
+#define	OOSIOP_DCNTL_CF_MASK	0xc0	/* Clock frequency dividers: */
+#define	OOSIOP_DCNTL_CF_2	0x00	/*  0 --> 37.51..50.00 MHz, div=2 */
+#define	OOSIOP_DCNTL_CF_1_5	0x40	/*  1 --> 25.01..37.50 MHz, div=1.5 */
+#define	OOSIOP_DCNTL_CF_1	0x80	/*  2 --> 16.67..25.00 MHz, div=1 */
+#define	OOSIOP_DCNTL_CF_3	0xc0	/*  3 --> 50.01..66.67 MHz, div=3 */
+#define	OOSIOP_DCNTL_S16	0x20	/* SCRIPTS fetches 16bits at a time */
+#define	OOSIOP_DCNTL_SSM	0x10	/* Single step mode */
+#define	OOSIOP_DCNTL_LLM	0x08	/* Enable SCSI Low-level mode */
+#define	OOSIOP_DCNTL_STD	0x04	/* Start DMA operation */
+#define	OOSIOP_DCNTL_RST	0x01	/* Software reset */
--- /dev/null	2003-04-02 23:49:50.000000000 +0900
+++ dev/ic/oosiopvar.h	2003-03-21 13:17:32.000000000 +0900
@@ -0,0 +1,157 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 2001 Shuichiro URATA.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define	OOSIOP_NTGT	8		/* Max targets */
+#define	OOSIOP_NCB	32		/* Initial command buffers */
+#define	OOSIOP_NSG	(MIN(btoc(MAXPHYS) + 1, 32)) /* Max S/G operation */
+#define	OOSIOP_MAX_XFER	ctob(OOSIOP_NSG - 1)
+
+struct oosiop_xfer {
+	/* script for scatter/gather DMA (move*nsg+jump) */
+	u_int32_t datain_scr[(OOSIOP_NSG + 1) * 2];
+	u_int32_t dataout_scr[(OOSIOP_NSG + 1) * 2];
+
+	u_int8_t msgin[8];
+	u_int8_t msgout[8];
+	u_int8_t status;
+	u_int8_t pad[7];
+} __attribute__((__packed__));
+
+#define SCSI_OOSIOP_NOSTATUS	0xff	/* device didn't report status */
+
+#define OOSIOP_XFEROFF(x)	offsetof(struct oosiop_xfer, x)
+#define OOSIOP_DINSCROFF	OOSIOP_XFEROFF(datain_scr[0])
+#define OOSIOP_DOUTSCROFF	OOSIOP_XFEROFF(dataout_scr[0])
+#define OOSIOP_MSGINOFF		OOSIOP_XFEROFF(msgin[0])
+#define OOSIOP_MSGOUTOFF	OOSIOP_XFEROFF(msgout[0])
+
+#define OOSIOP_XFERSCR_SYNC(sc, cb, ops)				\
+	bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_DINSCROFF,	\
+	    OOSIOP_MSGINOFF - OOSIOP_DINSCROFF, (ops))
+#define OOSIOP_DINSCR_SYNC(sc, cb, ops)					\
+	bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_DINSCROFF,	\
+	    OOSIOP_DOUTSCROFF - OOSIOP_DINSCROFF, (ops))
+#define OOSIOP_DOUTSCR_SYNC(sc, cb, ops)				\
+	bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_DOUTSCROFF,\
+	    OOSIOP_MSGINOFF - OOSIOP_DOUTSCROFF, (ops))
+#define OOSIOP_XFERMSG_SYNC(sc, cb, ops)				\
+	bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_MSGINOFF,	\
+	    sizeof(struct oosiop_xfer) - OOSIOP_MSGINOFF, (ops))
+
+#define OOSIOP_SCRIPT_SYNC(sc, ops)					\
+	bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_scrdma,			\
+	    0, sizeof(oosiop_script), (ops))
+
+struct oosiop_cb {
+	TAILQ_ENTRY(oosiop_cb) chain;
+
+	struct scsipi_xfer *xs;		/* SCSI xfer ctrl block from above */
+	int flags;
+	int id;				/* target scsi id */
+	int lun;			/* target lun */
+
+	bus_dmamap_t cmddma;		/* DMA map for command out */
+	bus_dmamap_t datadma;		/* DMA map for data I/O */
+	bus_dmamap_t xferdma;		/* DMA map for xfer block */
+
+	int curdp;			/* current data pointer */
+	int savedp;			/* saved data pointer */
+	int msgoutlen;
+
+	struct oosiop_xfer *xfer;	/* DMA xfer block */
+};
+
+/* oosiop_cb flags */
+#define	CBF_SELTOUT	0x01	/* Selection timeout */
+#define	CBF_TIMEOUT	0x02	/* Command timeout */
+
+TAILQ_HEAD(oosiop_cb_queue, oosiop_cb);
+
+struct oosiop_target {
+	struct oosiop_cb *nexus;
+	int flags;
+	u_int8_t scf;		/* synchronous clock divisor */
+	u_int8_t sxfer;		/* synchronous period and offset */
+};
+
+/* target flags */
+#define	TGTF_SYNCNEG	0x01	/* Trigger synchronous negotiation */
+#define	TGTF_WAITSDTR	0x02	/* Waiting SDTR from target */
+
+struct oosiop_softc {
+	struct device sc_dev;
+
+	bus_space_tag_t	sc_bst;		/* bus space tag */
+	bus_space_handle_t sc_bsh;	/* bus space handle */
+
+	bus_dma_tag_t sc_dmat;		/* bus dma tag */
+	bus_dmamap_t sc_scrdma;		/* script dma map */
+
+	bus_addr_t sc_scrbase;		/* script dma base address */
+	u_int32_t *sc_scr;		/* ptr to script memory */
+
+	int sc_chip;			/* 700 or 700-66 */
+#define	OOSIOP_700	0
+#define	OOSIOP_700_66	1
+
+	int		sc_id;		/* SCSI ID of this interface */
+	int		sc_freq;	/* SCLK frequency */
+	int		sc_ccf;		/* asynchronous divisor (*10) */
+	u_int8_t	sc_dcntl;
+	u_int8_t	sc_minperiod;
+
+	struct oosiop_target sc_tgt[OOSIOP_NTGT];
+
+	struct scsipi_adapter sc_adapter;
+	struct scsipi_channel sc_channel;
+
+	/* Lists of command blocks */
+	struct oosiop_cb_queue sc_free_cb;
+	struct oosiop_cb_queue sc_cbq;	/* command issue queue */
+	struct oosiop_cb *sc_curcb;	/* current command */
+	struct oosiop_cb *sc_lastcb;	/* last activated command */
+
+	bus_addr_t sc_reselbuf;		/* msgin buffer for reselection */
+	int sc_resid;			/* reselected target id */
+
+	int sc_active;
+	int sc_nextdsp;
+};
+
+#define	oosiop_read_1(sc, addr)						\
+    bus_space_read_1((sc)->sc_bst, (sc)->sc_bsh, (addr))
+#define	oosiop_write_1(sc, addr, data)					\
+    bus_space_write_1((sc)->sc_bst, (sc)->sc_bsh, (addr), (data))
+/* XXX byte swapping should be handled by MD bus_space(9)? */
+#define	oosiop_read_4(sc, addr)						\
+    le32toh(bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (addr)))
+#define	oosiop_write_4(sc, addr, data)					\
+    bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (addr), htole32(data))
+
+void oosiop_attach(struct oosiop_softc *);
+int oosiop_intr(struct oosiop_softc *);