12432Sse/**************************************************************************
22432Sse**
32432Sse**
439247Sgibbs**  Device driver for the   NCR 53C8XX   PCI-SCSI-Controller Family.
52432Sse**
62432Sse**-------------------------------------------------------------------------
72432Sse**
82432Sse**  Written for 386bsd and FreeBSD by
97228Sse**	Wolfgang Stanglmeier	<wolf@cologne.de>
103533Sse**	Stefan Esser		<se@mi.Uni-Koeln.de>
112432Sse**
122432Sse**-------------------------------------------------------------------------
13139834Sscottl*/
14139825Simp/*-
152432Sse** Copyright (c) 1994 Wolfgang Stanglmeier.  All rights reserved.
162432Sse**
172432Sse** Redistribution and use in source and binary forms, with or without
182432Sse** modification, are permitted provided that the following conditions
192432Sse** are met:
202432Sse** 1. Redistributions of source code must retain the above copyright
212432Sse**    notice, this list of conditions and the following disclaimer.
222432Sse** 2. Redistributions in binary form must reproduce the above copyright
232432Sse**    notice, this list of conditions and the following disclaimer in the
242432Sse**    documentation and/or other materials provided with the distribution.
252432Sse** 3. The name of the author may not be used to endorse or promote products
262432Sse**    derived from this software without specific prior written permission.
272432Sse**
282432Sse** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
292432Sse** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
302432Sse** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
312432Sse** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
322432Sse** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
332432Sse** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
342432Sse** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
352432Sse** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
362432Sse** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
372432Sse** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
382432Sse**
393533Sse***************************************************************************
402432Sse*/
412432Sse
42116192Sobrien#include <sys/cdefs.h>
43116192Sobrien__FBSDID("$FreeBSD$");
44116192Sobrien
45116192Sobrien
4639247Sgibbs#define NCR_DATE "pl30 98/1/1"
476132Sdg
482432Sse#define NCR_VERSION	(2)
493533Sse#define	MAX_UNITS	(16)
502432Sse
519429Sse#define NCR_GETCC_WITHMSG
527228Sse
5355206Speter#if defined (__FreeBSD__) && defined(_KERNEL)
5420535Sse#include "opt_ncr.h"
5555206Speter#endif
5620517Sse
572432Sse/*==========================================================
582432Sse**
592432Sse**	Configuration and Debugging
602432Sse**
616460Sse**	May be overwritten in <arch/conf/xxxx>
622432Sse**
632432Sse**==========================================================
642432Sse*/
652432Sse
662432Sse/*
672432Sse**    SCSI address of this device.
682432Sse**    The boot routines should have set it.
692432Sse**    If not, use this.
702432Sse*/
712432Sse
722432Sse#ifndef SCSI_NCR_MYADDR
732432Sse#define SCSI_NCR_MYADDR      (7)
742432Sse#endif /* SCSI_NCR_MYADDR */
752432Sse
762432Sse/*
7727684Sse**    The default synchronous period factor
782432Sse**    (0=asynchronous)
7927684Sse**    If maximum synchronous frequency is defined, use it instead.
802432Sse*/
812432Sse
8227684Sse#ifndef	SCSI_NCR_MAX_SYNC
832432Sse
8427684Sse#ifndef SCSI_NCR_DFLT_SYNC
8527684Sse#define SCSI_NCR_DFLT_SYNC   (12)
8627684Sse#endif /* SCSI_NCR_DFLT_SYNC */
8727684Sse
8827684Sse#else
8927684Sse
9027684Sse#if	SCSI_NCR_MAX_SYNC == 0
9127684Sse#define	SCSI_NCR_DFLT_SYNC 0
9227684Sse#else
9327684Sse#define	SCSI_NCR_DFLT_SYNC (250000 / SCSI_NCR_MAX_SYNC)
9427684Sse#endif
9527684Sse
9627684Sse#endif
9727684Sse
982432Sse/*
9927684Sse**    The minimal asynchronous pre-scaler period (ns)
10027684Sse**    Shall be 40.
10127684Sse*/
10227684Sse
10327684Sse#ifndef SCSI_NCR_MIN_ASYNC
10427684Sse#define SCSI_NCR_MIN_ASYNC   (40)
10527684Sse#endif /* SCSI_NCR_MIN_ASYNC */
10627684Sse
10727684Sse/*
1082814Sse**    The maximal bus with (in log2 byte)
1092814Sse**    (0=8 bit, 1=16 bit)
1102814Sse*/
1112814Sse
1122814Sse#ifndef SCSI_NCR_MAX_WIDE
1133939Sse#define SCSI_NCR_MAX_WIDE   (1)
1142814Sse#endif /* SCSI_NCR_MAX_WIDE */
1152814Sse
1162432Sse/*==========================================================
1172432Sse**
1182432Sse**      Configuration and Debugging
1192432Sse**
1202432Sse**==========================================================
1212432Sse*/
1222432Sse
1232432Sse/*
1242432Sse**    Number of targets supported by the driver.
1252432Sse**    n permits target numbers 0..n-1.
1262432Sse**    Default is 7, meaning targets #0..#6.
1272432Sse**    #7 .. is myself.
1282432Sse*/
1292432Sse
13010605Sse#define MAX_TARGET  (16)
1312432Sse
1322432Sse/*
1332432Sse**    Number of logic units supported by the driver.
1342432Sse**    n enables logic unit numbers 0..n-1.
1352432Sse**    The common SCSI devices require only
1362432Sse**    one lun, so take 1 as the default.
1372432Sse*/
1382432Sse
13914556Sse#ifndef	MAX_LUN
14013481Sse#define MAX_LUN     (8)
14114556Sse#endif	/* MAX_LUN */
1422432Sse
1432432Sse/*
1442432Sse**    The maximum number of jobs scheduled for starting.
1452432Sse**    There should be one slot per target, and one slot
14610605Sse**    for each tag of each target in use.
1472432Sse*/
1482432Sse
14939247Sgibbs#define MAX_START   (256)
1502432Sse
1512432Sse/*
1522432Sse**    The maximum number of segments a transfer is split into.
1532432Sse*/
1542432Sse
1552432Sse#define MAX_SCATTER (33)
1562432Sse
1572432Sse/*
1582432Sse**    The maximum transfer length (should be >= 64k).
15915543Sphk**    MUST NOT be greater than (MAX_SCATTER-1) * PAGE_SIZE.
1602432Sse*/
1612432Sse
16215543Sphk#define MAX_SIZE  ((MAX_SCATTER-1) * (long) PAGE_SIZE)
1636526Sse
1646526Sse/*
1656526Sse**	other
1666526Sse*/
1676526Sse
1686526Sse#define NCR_SNOOP_TIMEOUT (1000000)
1697228Sse
1702432Sse/*==========================================================
1712432Sse**
1722432Sse**      Include files
1732432Sse**
1742432Sse**==========================================================
1752432Sse*/
1762432Sse
1772432Sse#include <sys/param.h>
1782432Sse#include <sys/time.h>
1792432Sse
18055206Speter#ifdef _KERNEL
1812432Sse#include <sys/systm.h>
1822432Sse#include <sys/malloc.h>
1832432Sse#include <sys/kernel.h>
184129878Sphk#include <sys/module.h>
18512820Sphk#include <sys/sysctl.h>
186168752Sscottl#include <sys/lock.h>
187168752Sscottl#include <sys/mutex.h>
18860974Sdfr#include <sys/bus.h>
18948424Speter#include <machine/md_var.h>
19060974Sdfr#include <machine/bus.h>
19160974Sdfr#include <machine/resource.h>
19260974Sdfr#include <sys/rman.h>
1932432Sse#include <vm/vm.h>
19412662Sdg#include <vm/pmap.h>
19510605Sse#include <vm/vm_extern.h>
19655206Speter#endif
1972432Sse
198119288Simp#include <dev/pci/pcivar.h>
199119288Simp#include <dev/pci/pcireg.h>
200119343Smarcel#include <pci/ncrreg.h>
2012432Sse
20239247Sgibbs#include <cam/cam.h>
20339247Sgibbs#include <cam/cam_ccb.h>
20439247Sgibbs#include <cam/cam_sim.h>
20539247Sgibbs#include <cam/cam_xpt_sim.h>
20639247Sgibbs#include <cam/cam_debug.h>
2072432Sse
20839247Sgibbs#include <cam/scsi/scsi_all.h>
20939247Sgibbs#include <cam/scsi/scsi_message.h>
2107228Sse
2112432Sse/*==========================================================
2122432Sse**
2132432Sse**	Debugging tags
2142432Sse**
2152432Sse**==========================================================
2162432Sse*/
2172432Sse
2182432Sse#define DEBUG_ALLOC    (0x0001)
2192432Sse#define DEBUG_PHASE    (0x0002)
2202432Sse#define DEBUG_POLL     (0x0004)
2212432Sse#define DEBUG_QUEUE    (0x0008)
2222432Sse#define DEBUG_RESULT   (0x0010)
2232432Sse#define DEBUG_SCATTER  (0x0020)
2242432Sse#define DEBUG_SCRIPT   (0x0040)
2252432Sse#define DEBUG_TINY     (0x0080)
2262432Sse#define DEBUG_TIMING   (0x0100)
2272814Sse#define DEBUG_NEGO     (0x0200)
2282432Sse#define DEBUG_TAGS     (0x0400)
2292432Sse#define DEBUG_FREEZE   (0x0800)
2302814Sse#define DEBUG_RESTART  (0x1000)
2312432Sse
2323552Sse/*
2333552Sse**    Enable/Disable debug messages.
2343552Sse**    Can be changed at runtime too.
2353552Sse*/
23620549Sse#ifdef SCSI_NCR_DEBUG
2376766Sse	#define DEBUG_FLAGS ncr_debug
23820549Sse#else /* SCSI_NCR_DEBUG */
23920549Sse	#define SCSI_NCR_DEBUG	0
2403552Sse	#define DEBUG_FLAGS	0
24120549Sse#endif /* SCSI_NCR_DEBUG */
2422432Sse
2432432Sse
2443552Sse
2452432Sse/*==========================================================
2462432Sse**
2472432Sse**	assert ()
2482432Sse**
2492432Sse**==========================================================
2502432Sse**
2512432Sse**	modified copy from 386bsd:/usr/include/sys/assert.h
2522432Sse**
2532432Sse**----------------------------------------------------------
2542432Sse*/
2552432Sse
25639247Sgibbs#ifdef DIAGNOSTIC
25739247Sgibbs#define	assert(expression) {					\
258170027Srwatson	KASSERT(expression, ("%s", #expression));		\
2592432Sse}
26039247Sgibbs#else
26139247Sgibbs#define	assert(expression) {					\
26239247Sgibbs	if (!(expression)) {					\
26339247Sgibbs		(void)printf("assertion \"%s\" failed: "	\
26439247Sgibbs			     "file \"%s\", line %d\n",		\
26539247Sgibbs			     #expression, __FILE__, __LINE__);	\
26639247Sgibbs	}							\
26739247Sgibbs}
26839247Sgibbs#endif
2697228Sse
2702432Sse/*==========================================================
2712432Sse**
2722432Sse**	Access to the controller chip.
2732432Sse**
2742432Sse**==========================================================
2752432Sse*/
2762432Sse
27760974Sdfr#define	INB(r) bus_space_read_1(np->bst, np->bsh, offsetof(struct ncr_reg, r))
27860974Sdfr#define	INW(r) bus_space_read_2(np->bst, np->bsh, offsetof(struct ncr_reg, r))
27960974Sdfr#define	INL(r) bus_space_read_4(np->bst, np->bsh, offsetof(struct ncr_reg, r))
2806401Sse
28160974Sdfr#define	OUTB(r, val) bus_space_write_1(np->bst, np->bsh, \
28260974Sdfr				       offsetof(struct ncr_reg, r), val)
28360974Sdfr#define	OUTW(r, val) bus_space_write_2(np->bst, np->bsh, \
28460974Sdfr				       offsetof(struct ncr_reg, r), val)
28560974Sdfr#define	OUTL(r, val) bus_space_write_4(np->bst, np->bsh, \
28660974Sdfr				       offsetof(struct ncr_reg, r), val)
28760974Sdfr#define	OUTL_OFF(o, val) bus_space_write_4(np->bst, np->bsh, o, val)
2886401Sse
28960974Sdfr#define	INB_OFF(o) bus_space_read_1(np->bst, np->bsh, o)
29060974Sdfr#define	INW_OFF(o) bus_space_read_2(np->bst, np->bsh, o)
29160974Sdfr#define	INL_OFF(o) bus_space_read_4(np->bst, np->bsh, o)
2926401Sse
29360974Sdfr#define	READSCRIPT_OFF(base, off)					\
29460974Sdfr    (base ? *((volatile u_int32_t *)((volatile char *)base + (off))) :	\
29560974Sdfr    bus_space_read_4(np->bst2, np->bsh2, off))
29627744Sse
29760974Sdfr#define	WRITESCRIPT_OFF(base, off, val)					\
29860974Sdfr    do {								\
29960974Sdfr    	if (base)							\
30060974Sdfr    		*((volatile u_int32_t *)				\
30160974Sdfr			((volatile char *)base + (off))) = (val);	\
30260974Sdfr    	else								\
30360974Sdfr		bus_space_write_4(np->bst2, np->bsh2, off, val);	\
30439532Sken    } while (0)
30539532Sken
30639532Sken#define	READSCRIPT(r) \
30739532Sken    READSCRIPT_OFF(np->script, offsetof(struct script, r))
30839532Sken
30939532Sken#define	WRITESCRIPT(r, val) \
31039532Sken    WRITESCRIPT_OFF(np->script, offsetof(struct script, r), val)
31139532Sken
31227684Sse/*
31327684Sse**	Set bit field ON, OFF
31427684Sse*/
31527684Sse
31627684Sse#define OUTONB(r, m)	OUTB(r, INB(r) | (m))
31727684Sse#define OUTOFFB(r, m)	OUTB(r, INB(r) & ~(m))
31827684Sse#define OUTONW(r, m)	OUTW(r, INW(r) | (m))
31927684Sse#define OUTOFFW(r, m)	OUTW(r, INW(r) & ~(m))
32027684Sse#define OUTONL(r, m)	OUTL(r, INL(r) | (m))
32127684Sse#define OUTOFFL(r, m)	OUTL(r, INL(r) & ~(m))
32227684Sse
3232432Sse/*==========================================================
3242432Sse**
3252432Sse**	Command control block states.
3262432Sse**
3272432Sse**==========================================================
3282432Sse*/
3292432Sse
33010567Sse#define HS_IDLE		(0)
33110567Sse#define HS_BUSY		(1)
33210567Sse#define HS_NEGOTIATE	(2)	/* sync/wide data transfer*/
33310567Sse#define HS_DISCONNECT	(3)	/* Disconnected by target */
3342432Sse
33510567Sse#define HS_COMPLETE	(4)
33610567Sse#define HS_SEL_TIMEOUT	(5)	/* Selection timeout      */
3377228Sse#define HS_RESET	(6)	/* SCSI reset	     */
33810567Sse#define HS_ABORTED	(7)	/* Transfer aborted       */
33910567Sse#define HS_TIMEOUT	(8)	/* Software timeout       */
34010567Sse#define HS_FAIL		(9)	/* SCSI or PCI bus errors */
34110567Sse#define HS_UNEXPECTED	(10)	/* Unexpected disconnect  */
34239247Sgibbs#define HS_STALL	(11)	/* QUEUE FULL or BUSY	  */
3432432Sse
3442814Sse#define HS_DONEMASK	(0xfc)
3452814Sse
3462432Sse/*==========================================================
3472432Sse**
3486705Sse**	Software Interrupt Codes
3492432Sse**
3502432Sse**==========================================================
3512432Sse*/
3522432Sse
3532814Sse#define	SIR_SENSE_RESTART	(1)
3542814Sse#define	SIR_SENSE_FAILED	(2)
3552814Sse#define	SIR_STALL_RESTART	(3)
3562814Sse#define	SIR_STALL_QUEUE		(4)
3572814Sse#define	SIR_NEGO_SYNC		(5)
3582814Sse#define	SIR_NEGO_WIDE		(6)
3592814Sse#define	SIR_NEGO_FAILED		(7)
3602814Sse#define	SIR_NEGO_PROTO		(8)
3612814Sse#define	SIR_REJECT_RECEIVED	(9)
3622814Sse#define	SIR_REJECT_SENT		(10)
3632814Sse#define	SIR_IGN_RESIDUE		(11)
3642814Sse#define	SIR_MISSING_SAVE	(12)
3652814Sse#define	SIR_MAX			(12)
3667228Sse
3672814Sse/*==========================================================
3682814Sse**
3692814Sse**	Extended error codes.
37039247Sgibbs**	xerr_status field of struct nccb.
3712814Sse**
3722814Sse**==========================================================
3732814Sse*/
3742432Sse
3752814Sse#define	XE_OK		(0)
3762814Sse#define	XE_EXTRA_DATA	(1)	/* unexpected data phase */
3772814Sse#define	XE_BAD_PHASE	(2)	/* illegal phase (4/5)   */
3782814Sse
3792432Sse/*==========================================================
3802432Sse**
3812814Sse**	Negotiation status.
38239247Sgibbs**	nego_status field	of struct nccb.
3832432Sse**
3842432Sse**==========================================================
3852432Sse*/
3862432Sse
3872814Sse#define NS_SYNC		(1)
3882814Sse#define NS_WIDE		(2)
3892814Sse
3902814Sse/*==========================================================
3912814Sse**
39239247Sgibbs**	XXX These are no longer used.  Remove once the
39339247Sgibbs**	    script is updated.
3942814Sse**	"Special features" of targets.
39539247Sgibbs**	quirks field of struct tcb.
39639247Sgibbs**	actualquirks field of struct nccb.
3972814Sse**
3982814Sse**==========================================================
3992814Sse*/
4002814Sse
4012814Sse#define	QUIRK_AUTOSAVE	(0x01)
4022814Sse#define	QUIRK_NOMSG	(0x02)
40339247Sgibbs#define	QUIRK_NOSYNC	(0x10)
40439247Sgibbs#define	QUIRK_NOWIDE16	(0x20)
40539247Sgibbs#define	QUIRK_NOTAGS	(0x40)
4062814Sse#define	QUIRK_UPDATE	(0x80)
4072814Sse
4082814Sse/*==========================================================
4092814Sse**
4102814Sse**	Misc.
4112814Sse**
4122814Sse**==========================================================
4132814Sse*/
4142814Sse
4152814Sse#define CCB_MAGIC	(0xf2691ad2)
41639247Sgibbs#define	MAX_TAGS	(32)		/* hard limit */
4177228Sse
4182432Sse/*==========================================================
4192432Sse**
4202432Sse**	OS dependencies.
4212432Sse**
4222432Sse**==========================================================
4232432Sse*/
4242432Sse
42539247Sgibbs#define PRINT_ADDR(ccb) xpt_print_path((ccb)->ccb_h.path)
4267228Sse
4272432Sse/*==========================================================
4282432Sse**
4292432Sse**	Declaration of structs.
4302432Sse**
4312432Sse**==========================================================
4322432Sse*/
4332432Sse
4342432Ssestruct tcb;
4352432Ssestruct lcb;
43639247Sgibbsstruct nccb;
4372432Ssestruct ncb;
4382432Ssestruct script;
4392432Sse
4402432Ssetypedef struct ncb * ncb_p;
4412432Ssetypedef struct tcb * tcb_p;
4422432Ssetypedef struct lcb * lcb_p;
44339247Sgibbstypedef struct nccb * nccb_p;
4442432Sse
4452432Ssestruct link {
44628960Sse	ncrcmd	l_cmd;
44728960Sse	ncrcmd	l_paddr;
4482432Sse};
4492432Sse
4502432Ssestruct	usrcmd {
4512432Sse	u_long	target;
4522432Sse	u_long	lun;
4532432Sse	u_long	data;
4542432Sse	u_long	cmd;
4552432Sse};
4562432Sse
4572432Sse#define UC_SETSYNC      10
4582432Sse#define UC_SETTAGS	11
4592432Sse#define UC_SETDEBUG	12
4602432Sse#define UC_SETORDER	13
4612435Sse#define UC_SETWIDE	14
4622435Sse#define UC_SETFLAG	15
4632432Sse
4642814Sse#define	UF_TRACE	(0x01)
4652814Sse
4662432Sse/*---------------------------------------
4672432Sse**
4682432Sse**	Timestamps for profiling
4692432Sse**
4702432Sse**---------------------------------------
4712432Sse*/
4722432Sse
47339554Sgibbs/* Type of the kernel variable `ticks'.  XXX should be declared with the var. */
47439554Sgibbstypedef int ticks_t;
47539554Sgibbs
4762432Ssestruct tstamp {
47739554Sgibbs	ticks_t	start;
47839554Sgibbs	ticks_t	end;
47939554Sgibbs	ticks_t	select;
48039554Sgibbs	ticks_t	command;
48139554Sgibbs	ticks_t	data;
48239554Sgibbs	ticks_t	status;
48339554Sgibbs	ticks_t	disconnect;
4842432Sse};
4852432Sse
4862432Sse/*
4872432Sse**	profiling data (per device)
4882432Sse*/
4892432Sse
4902432Ssestruct profile {
4912432Sse	u_long	num_trans;
4922432Sse	u_long	num_bytes;
4932432Sse	u_long	num_disc;
4942432Sse	u_long	num_break;
4952432Sse	u_long	num_int;
4962432Sse	u_long	num_fly;
4972432Sse	u_long	ms_setup;
4982432Sse	u_long	ms_data;
4992432Sse	u_long	ms_disc;
5002432Sse	u_long	ms_post;
5012432Sse};
5027228Sse
5032432Sse/*==========================================================
5042432Sse**
5057228Sse**	Declaration of structs:		target control block
5062432Sse**
5072432Sse**==========================================================
5082432Sse*/
5092432Sse
51039247Sgibbs#define NCR_TRANS_CUR		0x01	/* Modify current neogtiation status */
51139247Sgibbs#define NCR_TRANS_ACTIVE	0x03	/* Assume this is the active target */
51239247Sgibbs#define NCR_TRANS_GOAL		0x04	/* Modify negotiation goal */
51339247Sgibbs#define NCR_TRANS_USER		0x08	/* Modify user negotiation settings */
51439247Sgibbs
51539247Sgibbsstruct ncr_transinfo {
51639247Sgibbs	u_int8_t width;
51739247Sgibbs	u_int8_t period;
51839247Sgibbs	u_int8_t offset;
51939247Sgibbs};
52039247Sgibbs
52139247Sgibbsstruct ncr_target_tinfo {
52239247Sgibbs	/* Hardware version of our sync settings */
52339247Sgibbs	u_int8_t disc_tag;
52439247Sgibbs#define		NCR_CUR_DISCENB	0x01
52539247Sgibbs#define		NCR_CUR_TAGENB	0x02
52639247Sgibbs#define		NCR_USR_DISCENB	0x04
52739247Sgibbs#define		NCR_USR_TAGENB	0x08
52839247Sgibbs	u_int8_t sval;
52939247Sgibbs        struct	 ncr_transinfo current;
53039247Sgibbs        struct	 ncr_transinfo goal;
53139247Sgibbs        struct	 ncr_transinfo user;
53239247Sgibbs	/* Hardware version of our wide settings */
53339247Sgibbs	u_int8_t wval;
53439247Sgibbs};
53539247Sgibbs
5362432Ssestruct tcb {
5372432Sse	/*
5382432Sse	**	during reselection the ncr jumps to this point
5397228Sse	**	with SFBR set to the encoded target number
5402432Sse	**	with bit 7 set.
5412432Sse	**	if it's not this target, jump to the next.
5422432Sse	**
5437228Sse	**	JUMP  IF (SFBR != #target#)
5442432Sse	**	@(next tcb)
5452432Sse	*/
5462432Sse
5472432Sse	struct link   jump_tcb;
5482432Sse
5492432Sse	/*
5502814Sse	**	load the actual values for the sxfer and the scntl3
5512814Sse	**	register (sync/wide mode).
5522432Sse	**
5532432Sse	**	SCR_COPY (1);
5542432Sse	**	@(sval field of this tcb)
5552432Sse	**	@(sxfer register)
5562814Sse	**	SCR_COPY (1);
5572814Sse	**	@(wval field of this tcb)
5582814Sse	**	@(scntl3 register)
5592432Sse	*/
5602432Sse
5612814Sse	ncrcmd	getscr[6];
5622432Sse
5632432Sse	/*
5642432Sse	**	if next message is "identify"
5652432Sse	**	then load the message to SFBR,
5662432Sse	**	else load 0 to SFBR.
5672432Sse	**
5682432Sse	**	CALL
5692432Sse	**	<RESEL_LUN>
5702432Sse	*/
5712432Sse
5722432Sse	struct link   call_lun;
5732432Sse
5742432Sse	/*
5752432Sse	**	now look for the right lun.
5762432Sse	**
5772432Sse	**	JUMP
57839247Sgibbs	**	@(first nccb of this lun)
5792432Sse	*/
5802432Sse
5812432Sse	struct link   jump_lcb;
5827228Sse
5832432Sse	/*
58439247Sgibbs	**	pointer to interrupted getcc nccb
5852432Sse	*/
5862432Sse
58739247Sgibbs	nccb_p   hold_cp;
5882432Sse
5892432Sse	/*
59039247Sgibbs	**	pointer to nccb used for negotiating.
59127684Sse	**	Avoid to start a nego for all queued commands
59227684Sse	**	when tagged command queuing is enabled.
59327684Sse	*/
59427684Sse
59539247Sgibbs	nccb_p   nego_cp;
59627684Sse
59727684Sse	/*
5982432Sse	**	statistical data
5992432Sse	*/
6002432Sse
6012432Sse	u_long	transfers;
6022432Sse	u_long	bytes;
6032432Sse
6042432Sse	/*
6052432Sse	**	user settable limits for sync transfer
6062432Sse	**	and tagged commands.
6072432Sse	*/
6082432Sse
60939247Sgibbs	struct	 ncr_target_tinfo tinfo;
6102432Sse
6112432Sse	/*
6122432Sse	**	the lcb's of this tcb
6132432Sse	*/
6142432Sse
6152432Sse	lcb_p   lp[MAX_LUN];
6162432Sse};
6177228Sse
6182432Sse/*==========================================================
6192432Sse**
6207228Sse**	Declaration of structs:		lun control block
6212432Sse**
6222432Sse**==========================================================
6232432Sse*/
6242432Sse
6252432Ssestruct lcb {
6262432Sse	/*
6272432Sse	**	during reselection the ncr jumps to this point
6282432Sse	**	with SFBR set to the "Identify" message.
6292432Sse	**	if it's not this lun, jump to the next.
6302432Sse	**
63110567Sse	**	JUMP  IF (SFBR != #lun#)
6322432Sse	**	@(next lcb of this target)
6332432Sse	*/
6342432Sse
6352432Sse	struct link	jump_lcb;
6362432Sse
6372432Sse	/*
6382432Sse	**	if next message is "simple tag",
6392432Sse	**	then load the tag to SFBR,
6402432Sse	**	else load 0 to SFBR.
6412432Sse	**
6422432Sse	**	CALL
6432432Sse	**	<RESEL_TAG>
6442432Sse	*/
6452432Sse
6462432Sse	struct link	call_tag;
6472432Sse
6482432Sse	/*
64939247Sgibbs	**	now look for the right nccb.
6502432Sse	**
6512432Sse	**	JUMP
65239247Sgibbs	**	@(first nccb of this lun)
6532432Sse	*/
6542432Sse
65539247Sgibbs	struct link	jump_nccb;
6562432Sse
6572432Sse	/*
65839247Sgibbs	**	start of the nccb chain
6592432Sse	*/
6602432Sse
66139247Sgibbs	nccb_p	next_nccb;
6622432Sse
6632432Sse	/*
6642432Sse	**	Control of tagged queueing
6652432Sse	*/
6662432Sse
66739247Sgibbs	u_char		reqnccbs;
6682432Sse	u_char		reqlink;
6692432Sse	u_char		actlink;
6702432Sse	u_char		usetags;
6712432Sse	u_char		lasttag;
6722432Sse};
6737228Sse
6742432Sse/*==========================================================
6752432Sse**
6762432Sse**      Declaration of structs:     COMMAND control block
6772432Sse**
6782432Sse**==========================================================
6792432Sse**
68039247Sgibbs**	This substructure is copied from the nccb to a
6812432Sse**	global address after selection (or reselection)
6822432Sse**	and copied back before disconnect.
6832432Sse**
6842432Sse**	These fields are accessible to the script processor.
6852432Sse**
6862432Sse**----------------------------------------------------------
6872432Sse*/
6882432Sse
6892432Ssestruct head {
6902432Sse	/*
69139247Sgibbs	**	Execution of a nccb starts at this point.
6922432Sse	**	It's a jump to the "SELECT" label
6932432Sse	**	of the script.
6942432Sse	**
6952432Sse	**	After successful selection the script
6962432Sse	**	processor overwrites it with a jump to
6972432Sse	**	the IDLE label of the script.
6982432Sse	*/
6992432Sse
7002432Sse	struct link	launch;
7012432Sse
7022432Sse	/*
7032432Sse	**	Saved data pointer.
7042432Sse	**	Points to the position in the script
7052432Sse	**	responsible for the actual transfer
7062432Sse	**	of data.
7072432Sse	**	It's written after reception of a
7082432Sse	**	"SAVE_DATA_POINTER" message.
7092814Sse	**	The goalpointer points after
7102814Sse	**	the last transfer command.
7112432Sse	*/
7122432Sse
71328960Sse	u_int32_t	savep;
71428960Sse	u_int32_t	lastp;
71528960Sse	u_int32_t	goalp;
7162432Sse
7172432Sse	/*
71839247Sgibbs	**	The virtual address of the nccb
7192432Sse	**	containing this header.
7202432Sse	*/
7212432Sse
72239247Sgibbs	nccb_p	cp;
7232432Sse
7242432Sse	/*
7252432Sse	**	space for some timestamps to gather
7262432Sse	**	profiling data about devices and this driver.
7272432Sse	*/
7282432Sse
7292432Sse	struct tstamp	stamp;
7307228Sse
7312432Sse	/*
7322432Sse	**	status fields.
7332432Sse	*/
7342432Sse
7352432Sse	u_char		status[8];
7362432Sse};
7372435Sse
7382814Sse/*
7392814Sse**	The status bytes are used by the host and the script processor.
7402814Sse**
7412814Sse**	The first four byte are copied to the scratchb register
7422814Sse**	(declared as scr0..scr3 in ncr_reg.h) just after the select/reselect,
7432814Sse**	and copied back just after disconnecting.
7442814Sse**	Inside the script the XX_REG are used.
7452814Sse**
7462814Sse**	The last four bytes are used inside the script by "COPY" commands.
7472814Sse**	Because source and destination must have the same alignment
74810567Sse**	in a longword, the fields HAVE to be at the choosen offsets.
7492814Sse**		xerr_st	(4)	0	(0x34)	scratcha
7502814Sse**		sync_st	(5)	1	(0x05)	sxfer
7512814Sse**		wide_st	(7)	3	(0x03)	scntl3
7522814Sse*/
7532814Sse
7542814Sse/*
7552814Sse**	First four bytes (script)
7562814Sse*/
7572814Sse#define  QU_REG	scr0
7582814Sse#define  HS_REG	scr1
7592814Sse#define  HS_PRT	nc_scr1
7602814Sse#define  SS_REG	scr2
7612814Sse#define  PS_REG	scr3
7622814Sse
7632814Sse/*
7642814Sse**	First four bytes (host)
7652814Sse*/
7662814Sse#define  actualquirks  phys.header.status[0]
7672814Sse#define  host_status   phys.header.status[1]
76839247Sgibbs#define  s_status      phys.header.status[2]
7692814Sse#define  parity_status phys.header.status[3]
7702814Sse
7712814Sse/*
7722814Sse**	Last four bytes (script)
7732814Sse*/
7742814Sse#define  xerr_st       header.status[4]	/* MUST be ==0 mod 4 */
7752814Sse#define  sync_st       header.status[5]	/* MUST be ==1 mod 4 */
7762814Sse#define  nego_st       header.status[6]
7772814Sse#define  wide_st       header.status[7]	/* MUST be ==3 mod 4 */
7782814Sse
7792814Sse/*
7802814Sse**	Last four bytes (host)
7812814Sse*/
7822814Sse#define  xerr_status   phys.xerr_st
7832814Sse#define  sync_status   phys.sync_st
7842814Sse#define  nego_status   phys.nego_st
7852814Sse#define  wide_status   phys.wide_st
7867228Sse
7872432Sse/*==========================================================
7882432Sse**
7892432Sse**      Declaration of structs:     Data structure block
7902432Sse**
7912432Sse**==========================================================
7922432Sse**
79339247Sgibbs**	During execution of a nccb by the script processor,
7942432Sse**	the DSA (data structure address) register points
79539247Sgibbs**	to this substructure of the nccb.
7962432Sse**	This substructure contains the header with
7972432Sse**	the script-processor-changable data and
7982432Sse**	data blocks for the indirect move commands.
7992432Sse**
8002432Sse**----------------------------------------------------------
8012432Sse*/
8022432Sse
8032432Ssestruct dsb {
8042432Sse
8052432Sse	/*
8062432Sse	**	Header.
8072432Sse	**	Has to be the first entry,
8082432Sse	**	because it's jumped to by the
8092432Sse	**	script processor
8102432Sse	*/
8112432Sse
8127228Sse	struct head	header;
8132432Sse
8142432Sse	/*
8152432Sse	**	Table data for Script
8162432Sse	*/
8172432Sse
8182432Sse	struct scr_tblsel  select;
8192432Sse	struct scr_tblmove smsg  ;
8202432Sse	struct scr_tblmove smsg2 ;
8212432Sse	struct scr_tblmove cmd   ;
8227250Sse	struct scr_tblmove scmd  ;
8232432Sse	struct scr_tblmove sense ;
8242432Sse	struct scr_tblmove data [MAX_SCATTER];
8252432Sse};
8267228Sse
8272432Sse/*==========================================================
8282432Sse**
8292432Sse**      Declaration of structs:     Command control block.
8302432Sse**
8312432Sse**==========================================================
8322432Sse**
83339247Sgibbs**	During execution of a nccb by the script processor,
8342432Sse**	the DSA (data structure address) register points
83539247Sgibbs**	to this substructure of the nccb.
8362432Sse**	This substructure contains the header with
8372432Sse**	the script-processor-changable data and then
8382432Sse**	data blocks for the indirect move commands.
8392432Sse**
8402432Sse**----------------------------------------------------------
8412432Sse*/
8422432Sse
8432432Sse
84439247Sgibbsstruct nccb {
8452432Sse	/*
84628636Sse	**	This filler ensures that the global header is
84727684Sse	**	cache line size aligned.
84827684Sse	*/
84928634Sse	ncrcmd	filler[4];
85027684Sse
85127684Sse	/*
8522432Sse	**	during reselection the ncr jumps to this point.
8532432Sse	**	If a "SIMPLE_TAG" message was received,
8542432Sse	**	then SFBR is set to the tag.
8552432Sse	**	else SFBR is set to 0
85639247Sgibbs	**	If looking for another tag, jump to the next nccb.
8572432Sse	**
8582432Sse	**	JUMP  IF (SFBR != #TAG#)
85939247Sgibbs	**	@(next nccb of this lun)
8602432Sse	*/
8612432Sse
86239247Sgibbs	struct link		jump_nccb;
8632432Sse
8642432Sse	/*
8652432Sse	**	After execution of this call, the return address
8662432Sse	**	(in  the TEMP register) points to the following
8672432Sse	**	data structure block.
8682432Sse	**	So copy it to the DSA register, and start
8692432Sse	**	processing of this data structure.
8702432Sse	**
8712432Sse	**	CALL
8722432Sse	**	<RESEL_TMP>
8732432Sse	*/
8742432Sse
8752432Sse	struct link		call_tmp;
8762432Sse
8772432Sse	/*
8782432Sse	**	This is the data structure which is
8792432Sse	**	to be executed by the script processor.
8802432Sse	*/
8812432Sse
8822432Sse	struct dsb		phys;
8837228Sse
8842432Sse	/*
8852432Sse	**	If a data transfer phase is terminated too early
8862432Sse	**	(after reception of a message (i.e. DISCONNECT)),
8872432Sse	**	we have to prepare a mini script to transfer
8882432Sse	**	the rest of the data.
8892432Sse	*/
8902432Sse
89128960Sse	ncrcmd			patch[8];
8922432Sse
8932432Sse	/*
8942432Sse	**	The general SCSI driver provides a
8952432Sse	**	pointer to a control block.
8962432Sse	*/
8972432Sse
89839247Sgibbs	union	ccb *ccb;
8992432Sse
9002432Sse	/*
9012432Sse	**	We prepare a message to be sent after selection,
9022432Sse	**	and a second one to be sent after getcc selection.
9032432Sse	**      Contents are IDENTIFY and SIMPLE_TAG.
9042814Sse	**	While negotiating sync or wide transfer,
9052814Sse	**	a SDTM or WDTM message is appended.
9062432Sse	*/
9072432Sse
9082432Sse	u_char			scsi_smsg [8];
9092432Sse	u_char			scsi_smsg2[8];
9102432Sse
9112432Sse	/*
91239247Sgibbs	**	Lock this nccb.
91339247Sgibbs	**	Flag is used while looking for a free nccb.
91410639Sse	*/
91510639Sse
91610677Sse	u_long		magic;
91710639Sse
91810639Sse	/*
91939247Sgibbs	**	Physical address of this instance of nccb
9202432Sse	*/
9212432Sse
92239247Sgibbs	u_long		p_nccb;
9232814Sse
9242814Sse	/*
9252814Sse	**	Completion time out for this job.
9262814Sse	**	It's set to time of start + allowed number of seconds.
9272814Sse	*/
9282814Sse
92939554Sgibbs	time_t		tlimit;
9307228Sse
9312432Sse	/*
93239247Sgibbs	**	All nccbs of one hostadapter are chained.
9332432Sse	*/
9342432Sse
93539247Sgibbs	nccb_p		link_nccb;
9362432Sse
9372432Sse	/*
93839247Sgibbs	**	All nccbs of one target/lun are chained.
9392432Sse	*/
9402432Sse
94139247Sgibbs	nccb_p		next_nccb;
9422432Sse
9432432Sse	/*
9447250Sse	**	Sense command
9457250Sse	*/
9467250Sse
9477250Sse	u_char		sensecmd[6];
9487250Sse
9497250Sse	/*
9502432Sse	**	Tag for this transfer.
95139247Sgibbs	**	It's patched into jump_nccb.
9522432Sse	**	If it's not zero, a SIMPLE_TAG
9532432Sse	**	message is included in smsg.
9542432Sse	*/
9552432Sse
9562432Sse	u_char			tag;
9572432Sse};
9587228Sse
95939247Sgibbs#define CCB_PHYS(cp,lbl)	(cp->p_nccb + offsetof(struct nccb, lbl))
96010677Sse
9612432Sse/*==========================================================
9622432Sse**
9632432Sse**      Declaration of structs:     NCR device descriptor
9642432Sse**
9652432Sse**==========================================================
9662432Sse*/
9672432Sse
9682432Ssestruct ncb {
96927684Sse	/*
97027684Sse	**	The global header.
97127684Sse	**	Accessible to both the host and the
97227684Sse	**	script-processor.
97327684Sse	**	We assume it is cache line size aligned.
97427684Sse	*/
97527684Sse	struct head     header;
97627684Sse
9773533Sse	int	unit;
9782432Sse
9792432Sse	/*-----------------------------------------------
9802432Sse	**	Scripts ..
9812432Sse	**-----------------------------------------------
9822432Sse	**
9832432Sse	**	During reselection the ncr jumps to this point.
9842432Sse	**	The SFBR register is loaded with the encoded target id.
9852432Sse	**
9862432Sse	**	Jump to the first target.
9872432Sse	**
9882432Sse	**	JUMP
9892432Sse	**	@(next tcb)
9902432Sse	*/
9912432Sse	struct link     jump_tcb;
9922432Sse
9932432Sse	/*-----------------------------------------------
9942432Sse	**	Configuration ..
9952432Sse	**-----------------------------------------------
9962432Sse	**
9972432Sse	**	virtual and physical addresses
9982432Sse	**	of the 53c810 chip.
9992432Sse	*/
100060974Sdfr	int		reg_rid;
100160974Sdfr	struct resource *reg_res;
100260974Sdfr	bus_space_tag_t	bst;
100360974Sdfr	bus_space_handle_t bsh;
10042432Sse
100560974Sdfr	int		sram_rid;
100660974Sdfr	struct resource *sram_res;
100760974Sdfr	bus_space_tag_t	bst2;
100860974Sdfr	bus_space_handle_t bsh2;
100927744Sse
101060974Sdfr	struct resource *irq_res;
101160974Sdfr	void		*irq_handle;
10122432Sse
10132432Sse	/*
101427744Sse	**	Scripts instance virtual address.
101527744Sse	*/
10162432Sse	struct script	*script;
101727744Sse	struct scripth	*scripth;
101810677Sse
101910677Sse	/*
102027744Sse	**	Scripts instance physical address.
102110677Sse	*/
102210673Sse	u_long		p_script;
102327744Sse	u_long		p_scripth;
10247228Sse
10252432Sse	/*
10262432Sse	**	The SCSI address of the host adapter.
10272432Sse	*/
102820435Sse	u_char		myaddr;
10292432Sse
10302432Sse	/*
10312432Sse	**	timing parameters
10322432Sse	*/
103327684Sse	u_char		minsync;	/* Minimum sync period factor	*/
103427684Sse	u_char		maxsync;	/* Maximum sync period factor	*/
103527684Sse	u_char		maxoffs;	/* Max scsi offset		*/
103627684Sse	u_char		clock_divn;	/* Number of clock divisors	*/
103727684Sse	u_long		clock_khz;	/* SCSI clock frequency in KHz	*/
103827684Sse	u_long		features;	/* Chip features map		*/
103927684Sse	u_char		multiplier;	/* Clock multiplier (1,2,4)	*/
104020435Sse
104127684Sse	u_char		maxburst;	/* log base 2 of dwords burst	*/
104227684Sse
104320435Sse	/*
104420435Sse	**	BIOS supplied PCI bus options
104520435Sse	*/
10462432Sse	u_char		rv_scntl3;
104720435Sse	u_char		rv_dcntl;
104820435Sse	u_char		rv_dmode;
104920435Sse	u_char		rv_ctest3;
105027684Sse	u_char		rv_ctest4;
105120435Sse	u_char		rv_ctest5;
105227684Sse	u_char		rv_gpcntl;
105327684Sse	u_char		rv_stest2;
10542814Sse
10552432Sse	/*-----------------------------------------------
105639247Sgibbs	**	CAM SIM information for this instance
10572432Sse	**-----------------------------------------------
10582432Sse	*/
10592432Sse
106039247Sgibbs	struct		cam_sim  *sim;
106139247Sgibbs	struct		cam_path *path;
10622432Sse
10632432Sse	/*-----------------------------------------------
10642432Sse	**	Job control
10652432Sse	**-----------------------------------------------
10662432Sse	**
10672432Sse	**	Commands from user
10682432Sse	*/
10692432Sse	struct usrcmd	user;
10702432Sse
10712432Sse	/*
10722432Sse	**	Target data
10732432Sse	*/
10742432Sse	struct tcb	target[MAX_TARGET];
10752432Sse
10762432Sse	/*
10772432Sse	**	Start queue.
10782432Sse	*/
107928960Sse	u_int32_t	squeue [MAX_START];
10802432Sse	u_short		squeueput;
10812432Sse
10822432Sse	/*
10832432Sse	**	Timeout handler
10842432Sse	*/
108539554Sgibbs	time_t		heartbeat;
10862432Sse	u_short		ticks;
10872432Sse	u_short		latetime;
108839554Sgibbs	time_t		lasttime;
108929681Sgibbs	struct		callout_handle timeout_ch;
10907228Sse
10912432Sse	/*-----------------------------------------------
10922432Sse	**	Debug and profiling
10932432Sse	**-----------------------------------------------
10942432Sse	**
10952432Sse	**	register dump
10962432Sse	*/
10972432Sse	struct ncr_reg	regdump;
109839554Sgibbs	time_t		regtime;
10992432Sse
11002432Sse	/*
11012432Sse	**	Profiling data
11022432Sse	*/
11032432Sse	struct profile	profile;
11042432Sse	u_long		disc_phys;
11052432Sse	u_long		disc_ref;
11062814Sse
11072814Sse	/*
110839247Sgibbs	**	Head of list of all nccbs for this controller.
11092432Sse	*/
111039247Sgibbs	nccb_p		link_nccb;
111139247Sgibbs
11122432Sse	/*
11132432Sse	**	message buffers.
11142432Sse	**	Should be longword aligned,
11152432Sse	**	because they're written with a
11162432Sse	**	COPY script command.
11172432Sse	*/
11189364Sse	u_char		msgout[8];
11199364Sse	u_char		msgin [8];
112028960Sse	u_int32_t	lastmsg;
11212432Sse
11222432Sse	/*
11232432Sse	**	Buffer for STATUS_IN phase.
11242432Sse	*/
11252814Sse	u_char		scratch;
11262432Sse
11272814Sse	/*
11282814Sse	**	controller chip dependent maximal transfer width.
11292814Sse	*/
11302814Sse	u_char		maxwide;
11312814Sse
11326460Sse#ifdef NCR_IOMAPPED
11336136Sse	/*
11346460Sse	**	address of the ncr control registers in io space
11352814Sse	*/
113639532Sken	pci_port_t	port;
11376460Sse#endif
11382432Sse};
11397228Sse
114010677Sse#define NCB_SCRIPT_PHYS(np,lbl)	(np->p_script + offsetof (struct script, lbl))
114127744Sse#define NCB_SCRIPTH_PHYS(np,lbl) (np->p_scripth + offsetof (struct scripth,lbl))
114210677Sse
11432432Sse/*==========================================================
11442432Sse**
11452432Sse**
11462432Sse**      Script for NCR-Processor.
11472432Sse**
11482432Sse**	Use ncr_script_fill() to create the variable parts.
11492432Sse**	Use ncr_script_copy_and_bind() to make a copy and
11502432Sse**	bind to physical addresses.
11512432Sse**
11522432Sse**
11532432Sse**==========================================================
11542432Sse**
11552432Sse**	We have to know the offsets of all labels before
11562432Sse**	we reach them (for forward jumps).
11572432Sse**	Therefore we declare a struct here.
11582432Sse**	If you make changes inside the script,
11592432Sse**	DONT FORGET TO CHANGE THE LENGTHS HERE!
11602432Sse**
11612432Sse**----------------------------------------------------------
11622432Sse*/
11637228Sse
116427744Sse/*
116527744Sse**	Script fragments which are loaded into the on-board RAM
116627744Sse**	of 825A, 875 and 895 chips.
116727744Sse*/
11682432Ssestruct script {
11692432Sse	ncrcmd	start		[  7];
11702432Sse	ncrcmd	start0		[  2];
11712432Sse	ncrcmd	start1		[  3];
11722432Sse	ncrcmd  startpos	[  1];
11732432Sse	ncrcmd  trysel		[  8];
11742432Sse	ncrcmd	skip		[  8];
11752432Sse	ncrcmd	skip2		[  3];
11762432Sse	ncrcmd  idle		[  2];
117746843Sse	ncrcmd	select		[ 18];
11782432Sse	ncrcmd	prepare		[  4];
11792814Sse	ncrcmd	loadpos		[ 14];
11802814Sse	ncrcmd	prepare2	[ 24];
11812432Sse	ncrcmd	setmsg		[  5];
11822814Sse	ncrcmd  clrack		[  2];
11836179Sse	ncrcmd  dispatch	[ 33];
11842814Sse	ncrcmd	no_data		[ 17];
11857228Sse	ncrcmd  checkatn	[ 10];
11862432Sse	ncrcmd  command		[ 15];
11872814Sse	ncrcmd  status		[ 27];
11882814Sse	ncrcmd  msg_in		[ 26];
11892432Sse	ncrcmd  msg_bad		[  6];
11902814Sse	ncrcmd  complete	[ 13];
11912432Sse	ncrcmd	cleanup		[ 12];
119239247Sgibbs	ncrcmd	cleanup0	[  9];
119339247Sgibbs	ncrcmd	signal		[ 12];
11949364Sse	ncrcmd  save_dp		[  5];
11952432Sse	ncrcmd  restore_dp	[  5];
11962814Sse	ncrcmd  disconnect	[ 12];
11972814Sse	ncrcmd  disconnect0	[  5];
11982814Sse	ncrcmd  disconnect1	[ 23];
11992432Sse	ncrcmd	msg_out		[  9];
12002432Sse	ncrcmd	msg_out_done	[  7];
120127744Sse	ncrcmd  badgetcc	[  6];
120227744Sse	ncrcmd	reselect	[  8];
120327744Sse	ncrcmd	reselect1	[  8];
120427744Sse	ncrcmd	reselect2	[  8];
120527744Sse	ncrcmd	resel_tmp	[  5];
120627744Sse	ncrcmd  resel_lun	[ 18];
120727744Sse	ncrcmd	resel_tag	[ 24];
120827744Sse	ncrcmd  data_in		[MAX_SCATTER * 4 + 7];
120927744Sse	ncrcmd  data_out	[MAX_SCATTER * 4 + 7];
121027744Sse};
121127744Sse
121227744Sse/*
121327744Sse**	Script fragments which stay in main memory for all chips.
121427744Sse*/
121527744Ssestruct scripth {
121627744Sse	ncrcmd  tryloop		[MAX_START*5+2];
121727744Sse	ncrcmd  msg_parity	[  6];
121827744Sse	ncrcmd	msg_reject	[  8];
121927744Sse	ncrcmd	msg_ign_residue	[ 32];
122027744Sse	ncrcmd  msg_extended	[ 18];
122127744Sse	ncrcmd  msg_ext_2	[ 18];
122227744Sse	ncrcmd	msg_wdtr	[ 27];
122327744Sse	ncrcmd  msg_ext_3	[ 18];
122427744Sse	ncrcmd	msg_sdtr	[ 27];
12252432Sse	ncrcmd	msg_out_abort	[ 10];
12262432Sse	ncrcmd  getcc		[  4];
12272432Sse	ncrcmd  getcc1		[  5];
12289364Sse#ifdef NCR_GETCC_WITHMSG
122946843Sse	ncrcmd	getcc2		[ 29];
12309364Sse#else
12319364Sse	ncrcmd	getcc2		[ 14];
12329364Sse#endif
123346843Sse	ncrcmd	getcc3		[  6];
12342432Sse	ncrcmd	aborttag	[  4];
12356132Sdg	ncrcmd	abort		[ 22];
12366526Sse	ncrcmd	snooptest	[  9];
12376526Sse	ncrcmd	snoopend	[  2];
12382432Sse};
12397228Sse
12402432Sse/*==========================================================
12412432Sse**
12422432Sse**
12432814Sse**      Function headers.
12442432Sse**
12452432Sse**
12462432Sse**==========================================================
12472432Sse*/
12482432Sse
124955206Speter#ifdef _KERNEL
1250142407Simpstatic	nccb_p	ncr_alloc_nccb(ncb_p np, u_long target, u_long lun);
1251142407Simpstatic	void	ncr_complete(ncb_p np, nccb_p cp);
1252142407Simpstatic	int	ncr_delta(int * from, int * to);
1253142407Simpstatic	void	ncr_exception(ncb_p np);
1254142407Simpstatic	void	ncr_free_nccb(ncb_p np, nccb_p cp);
1255142407Simpstatic	void	ncr_freeze_devq(ncb_p np, struct cam_path *path);
1256142407Simpstatic	void	ncr_selectclock(ncb_p np, u_char scntl3);
1257142407Simpstatic	void	ncr_getclock(ncb_p np, u_char multiplier);
1258142407Simpstatic	nccb_p	ncr_get_nccb(ncb_p np, u_long t,u_long l);
125943309Sdillon#if 0
1260142407Simpstatic  u_int32_t ncr_info(int unit);
126143309Sdillon#endif
1262142407Simpstatic	void	ncr_init(ncb_p np, char * msg, u_long code);
1263142407Simpstatic	void	ncr_intr(void *vnp);
1264142407Simpstatic	void	ncr_int_ma(ncb_p np, u_char dstat);
1265142407Simpstatic	void	ncr_int_sir(ncb_p np);
1266142407Simpstatic  void    ncr_int_sto(ncb_p np);
126743309Sdillon#if 0
1268142407Simpstatic	void	ncr_min_phys(struct buf *bp);
126943309Sdillon#endif
1270142407Simpstatic	void	ncr_poll(struct cam_sim *sim);
1271142407Simpstatic	void	ncb_profile(ncb_p np, nccb_p cp);
1272142418Simpstatic	void	ncr_script_copy_and_bind(ncb_p np, ncrcmd *src, ncrcmd *dst,
1273142407Simp		    int len);
1274142407Simpstatic  void    ncr_script_fill(struct script * scr, struct scripth *scrh);
1275142407Simpstatic	int	ncr_scatter(struct dsb* phys, vm_offset_t vaddr,
1276142407Simp		    vm_size_t datalen);
1277142407Simpstatic	void	ncr_getsync(ncb_p np, u_char sfac, u_char *fakp,
1278142407Simp		    u_char *scntl3p);
1279142407Simpstatic	void	ncr_setsync(ncb_p np, nccb_p cp,u_char scntl3,u_char sxfer,
1280142407Simp		    u_char period);
1281142407Simpstatic	void	ncr_setwide(ncb_p np, nccb_p cp, u_char wide, u_char ack);
1282142407Simpstatic	int	ncr_show_msg(u_char * msg);
1283142407Simpstatic	int	ncr_snooptest(ncb_p np);
1284142407Simpstatic	void	ncr_action(struct cam_sim *sim, union ccb *ccb);
1285142407Simpstatic	void	ncr_timeout(void *arg);
1286142407Simpstatic  void    ncr_wakeup(ncb_p np, u_long code);
12872432Sse
1288142407Simpstatic  int	ncr_probe(device_t dev);
1289142407Simpstatic	int	ncr_attach(device_t dev);
12902432Sse
129155206Speter#endif /* _KERNEL */
12927228Sse
12932432Sse/*==========================================================
12942432Sse**
12952432Sse**
12962432Sse**      Global static data.
12972432Sse**
12982432Sse**
12992432Sse**==========================================================
13002432Sse*/
13012432Sse
130216322Sgpalmerstatic const u_long	ncr_version = NCR_VERSION	* 11
130310605Sse	+ (u_long) sizeof (struct ncb)	*  7
130439247Sgibbs	+ (u_long) sizeof (struct nccb)	*  5
130510605Sse	+ (u_long) sizeof (struct lcb)	*  3
130610605Sse	+ (u_long) sizeof (struct tcb)	*  2;
13072432Sse
130855206Speter#ifdef _KERNEL
13092432Sse
131020549Ssestatic int ncr_debug = SCSI_NCR_DEBUG;
131112820SphkSYSCTL_INT(_debug, OID_AUTO, ncr_debug, CTLFLAG_RW, &ncr_debug, 0, "");
13123166Sse
131312820Sphkstatic int ncr_cache; /* to be aligned _NOT_ static */
13143552Sse
13152432Sse/*==========================================================
13162432Sse**
13172432Sse**
13182432Sse**      Global static data:	auto configure
13192432Sse**
13202432Sse**
13212432Sse**==========================================================
13222432Sse*/
13232432Sse
13243166Sse#define	NCR_810_ID	(0x00011000ul)
13256401Sse#define	NCR_815_ID	(0x00041000ul)
132626568Sse#define	NCR_820_ID	(0x00021000ul)
13273166Sse#define	NCR_825_ID	(0x00031000ul)
132810936Sse#define	NCR_860_ID	(0x00061000ul)
132910936Sse#define	NCR_875_ID	(0x000f1000ul)
133026568Sse#define	NCR_875_ID2	(0x008f1000ul)
133126568Sse#define	NCR_885_ID	(0x000d1000ul)
133226568Sse#define	NCR_895_ID	(0x000c1000ul)
133326568Sse#define	NCR_896_ID	(0x000b1000ul)
133456446Sgroudier#define	NCR_895A_ID	(0x00121000ul)
133556446Sgroudier#define	NCR_1510D_ID	(0x000a1000ul)
13363166Sse
13372432Sse
13382814Ssestatic char *ncr_name (ncb_p np)
13392814Sse{
13402814Sse	static char name[10];
134141514Sarchie	snprintf(name, sizeof(name), "ncr%d", np->unit);
13423533Sse	return (name);
13432814Sse}
13447228Sse
13452432Sse/*==========================================================
13462432Sse**
13472432Sse**
13482432Sse**      Scripts for NCR-Processor.
13492432Sse**
13502432Sse**      Use ncr_script_bind for binding to physical addresses.
13512432Sse**
13522432Sse**
13532432Sse**==========================================================
13542432Sse**
13552435Sse**	NADDR generates a reference to a field of the controller data.
13562432Sse**	PADDR generates a reference to another part of the script.
13572435Sse**	RADDR generates a reference to a script processor register.
13582435Sse**	FADDR generates a reference to a script processor register
13592435Sse**		with offset.
13602432Sse**
13612432Sse**----------------------------------------------------------
13622432Sse*/
13632432Sse
13642432Sse#define	RELOC_SOFTC	0x40000000
13652432Sse#define	RELOC_LABEL	0x50000000
13662432Sse#define	RELOC_REGISTER	0x60000000
136727744Sse#define	RELOC_KVAR	0x70000000
136827744Sse#define	RELOC_LABELH	0x80000000
13692432Sse#define	RELOC_MASK	0xf0000000
13702432Sse
13712432Sse#define	NADDR(label)	(RELOC_SOFTC | offsetof(struct ncb, label))
13722432Sse#define PADDR(label)    (RELOC_LABEL | offsetof(struct script, label))
137327744Sse#define PADDRH(label)   (RELOC_LABELH | offsetof(struct scripth, label))
13742432Sse#define	RADDR(label)	(RELOC_REGISTER | REG(label))
13752435Sse#define	FADDR(label,ofs)(RELOC_REGISTER | ((REG(label))+(ofs)))
137627744Sse#define	KVAR(which)	(RELOC_KVAR | (which))
13772432Sse
137834961Sphk#define KVAR_SECOND			(0)
137934961Sphk#define KVAR_TICKS			(1)
138027744Sse#define KVAR_NCR_CACHE			(2)
138127744Sse
138227744Sse#define	SCRIPT_KVAR_FIRST		(0)
138327744Sse#define	SCRIPT_KVAR_LAST		(3)
138427744Sse
138527744Sse/*
138627744Sse * Kernel variables referenced in the scripts.
138727744Sse * THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY.
138827744Sse */
1389246037Sjhbstatic volatile void *script_kvars[] =
139034961Sphk	{ &time_second, &ticks, &ncr_cache };
139127744Sse
13922432Ssestatic	struct script script0 = {
13932432Sse/*--------------------------< START >-----------------------*/ {
13942432Sse	/*
13952432Sse	**	Claim to be still alive ...
13962432Sse	*/
13972432Sse	SCR_COPY (sizeof (((struct ncb *)0)->heartbeat)),
139834961Sphk		KVAR (KVAR_SECOND),
13992432Sse		NADDR (heartbeat),
14002432Sse	/*
14012432Sse	**      Make data structure address invalid.
14022432Sse	**      clear SIGP.
14032432Sse	*/
14042432Sse	SCR_LOAD_REG (dsa, 0xff),
14052432Sse		0,
14062432Sse	SCR_FROM_REG (ctest2),
14072432Sse		0,
14082432Sse}/*-------------------------< START0 >----------------------*/,{
14092432Sse	/*
14106705Sse	**	Hook for interrupted GetConditionCode.
14112432Sse	**	Will be patched to ... IFTRUE by
14126705Sse	**	the interrupt handler.
14132432Sse	*/
14142432Sse	SCR_INT ^ IFFALSE (0),
14152814Sse		SIR_SENSE_RESTART,
14167228Sse
14172432Sse}/*-------------------------< START1 >----------------------*/,{
14182432Sse	/*
14192432Sse	**	Hook for stalled start queue.
14206705Sse	**	Will be patched to IFTRUE by the interrupt handler.
14212432Sse	*/
14222432Sse	SCR_INT ^ IFFALSE (0),
14232814Sse		SIR_STALL_RESTART,
14242432Sse	/*
14252432Sse	**	Then jump to a certain point in tryloop.
14262432Sse	**	Due to the lack of indirect addressing the code
14272432Sse	**	is self modifying here.
14282432Sse	*/
14292432Sse	SCR_JUMP,
14302432Sse}/*-------------------------< STARTPOS >--------------------*/,{
143127744Sse		PADDRH(tryloop),
14327228Sse
14332432Sse}/*-------------------------< TRYSEL >----------------------*/,{
14342432Sse	/*
14352432Sse	**	Now:
14362432Sse	**	DSA: Address of a Data Structure
14372432Sse	**	or   Address of the IDLE-Label.
14382432Sse	**
14392432Sse	**	TEMP:	Address of a script, which tries to
14402432Sse	**		start the NEXT entry.
14412432Sse	**
14422432Sse	**	Save the TEMP register into the SCRATCHA register.
14432432Sse	**	Then copy the DSA to TEMP and RETURN.
14442432Sse	**	This is kind of an indirect jump.
14452432Sse	**	(The script processor has NO stack, so the
14462432Sse	**	CALL is actually a jump and link, and the
14472432Sse	**	RETURN is an indirect jump.)
14482432Sse	**
14492432Sse	**	If the slot was empty, DSA contains the address
14502432Sse	**	of the IDLE part of this script. The processor
14512432Sse	**	jumps to IDLE and waits for a reselect.
14522432Sse	**	It will wake up and try the same slot again
14532432Sse	**	after the SIGP bit becomes set by the host.
14542432Sse	**
14552432Sse	**	If the slot was not empty, DSA contains
145639247Sgibbs	**	the address of the phys-part of a nccb.
14572432Sse	**	The processor jumps to this address.
14582432Sse	**	phys starts with head,
14592432Sse	**	head starts with launch,
14602432Sse	**	so actually the processor jumps to
14612432Sse	**	the lauch part.
146210567Sse	**	If the entry is scheduled for execution,
14632432Sse	**	then launch contains a jump to SELECT.
14642432Sse	**	If it's not scheduled, it contains a jump to IDLE.
14652432Sse	*/
14662432Sse	SCR_COPY (4),
14672432Sse		RADDR (temp),
14682432Sse		RADDR (scratcha),
14692432Sse	SCR_COPY (4),
14702432Sse		RADDR (dsa),
14712432Sse		RADDR (temp),
14722432Sse	SCR_RETURN,
14732432Sse		0
14747228Sse
14752432Sse}/*-------------------------< SKIP >------------------------*/,{
14762432Sse	/*
14772432Sse	**	This entry has been canceled.
14782432Sse	**	Next time use the next slot.
14792432Sse	*/
14802432Sse	SCR_COPY (4),
14812432Sse		RADDR (scratcha),
14822432Sse		PADDR (startpos),
14832432Sse	/*
14842432Sse	**	patch the launch field.
14852432Sse	**	should look like an idle process.
14862432Sse	*/
148727684Sse	SCR_COPY_F (4),
14882432Sse		RADDR (dsa),
14892432Sse		PADDR (skip2),
14902432Sse	SCR_COPY (8),
14912432Sse		PADDR (idle),
14922432Sse}/*-------------------------< SKIP2 >-----------------------*/,{
14932432Sse		0,
14942432Sse	SCR_JUMP,
14952432Sse		PADDR(start),
14962432Sse}/*-------------------------< IDLE >------------------------*/,{
14972432Sse	/*
14982432Sse	**	Nothing to do?
14992432Sse	**	Wait for reselect.
15002432Sse	*/
15012432Sse	SCR_JUMP,
15022432Sse		PADDR(reselect),
15037228Sse
15042432Sse}/*-------------------------< SELECT >----------------------*/,{
15052432Sse	/*
15062432Sse	**	DSA	contains the address of a scheduled
15072432Sse	**		data structure.
15082432Sse	**
15092432Sse	**	SCRATCHA contains the address of the script,
15102432Sse	**		which starts the next entry.
15112432Sse	**
15122432Sse	**	Set Initiator mode.
15132432Sse	**
151410567Sse	**	(Target mode is left as an exercise for the reader)
15152432Sse	*/
15162432Sse
15172432Sse	SCR_CLR (SCR_TRG),
15182432Sse		0,
15192814Sse	SCR_LOAD_REG (HS_REG, 0xff),
15202432Sse		0,
15212432Sse
15222432Sse	/*
15232432Sse	**      And try to select this target.
15242432Sse	*/
15252432Sse	SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select),
15262432Sse		PADDR (reselect),
15272432Sse
15282432Sse	/*
15292432Sse	**	Now there are 4 possibilities:
15302432Sse	**
1531160964Syar	**	(1) The ncr loses arbitration.
15322432Sse	**	This is ok, because it will try again,
15332432Sse	**	when the bus becomes idle.
15342432Sse	**	(But beware of the timeout function!)
15352432Sse	**
15362432Sse	**	(2) The ncr is reselected.
15372432Sse	**	Then the script processor takes the jump
15382432Sse	**	to the RESELECT label.
15392432Sse	**
15402432Sse	**	(3) The ncr completes the selection.
15412432Sse	**	Then it will execute the next statement.
15422432Sse	**
15432432Sse	**	(4) There is a selection timeout.
15446705Sse	**	Then the ncr should interrupt the host and stop.
15452432Sse	**	Unfortunately, it seems to continue execution
15462432Sse	**	of the script. But it will fail with an
15476705Sse	**	IID-interrupt on the next WHEN.
15482432Sse	*/
15492432Sse
15502432Sse	SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)),
15512432Sse		0,
15527228Sse
15532432Sse	/*
15542432Sse	**	Send the IDENTIFY and SIMPLE_TAG messages
155539247Sgibbs	**	(and the MSG_EXT_SDTR message)
15562432Sse	*/
15572432Sse	SCR_MOVE_TBL ^ SCR_MSG_OUT,
15582432Sse		offsetof (struct dsb, smsg),
155913364Sse#ifdef undef /* XXX better fail than try to deal with this ... */
15602432Sse	SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_OUT)),
15612432Sse		-16,
156213364Sse#endif
15632432Sse	SCR_CLR (SCR_ATN),
15642432Sse		0,
15652432Sse	SCR_COPY (1),
15662432Sse		RADDR (sfbr),
15672432Sse		NADDR (lastmsg),
15682432Sse	/*
15692432Sse	**	Selection complete.
15702432Sse	**	Next time use the next slot.
15712432Sse	*/
15722432Sse	SCR_COPY (4),
15732432Sse		RADDR (scratcha),
15742432Sse		PADDR (startpos),
15752432Sse}/*-------------------------< PREPARE >----------------------*/,{
15762432Sse	/*
15772432Sse	**      The ncr doesn't have an indirect load
15782432Sse	**	or store command. So we have to
15792432Sse	**	copy part of the control block to a
15802432Sse	**	fixed place, where we can access it.
15812432Sse	**
15822432Sse	**	We patch the address part of a
15832432Sse	**	COPY command with the DSA-register.
15842432Sse	*/
158527684Sse	SCR_COPY_F (4),
15862432Sse		RADDR (dsa),
15872432Sse		PADDR (loadpos),
15882432Sse	/*
15892432Sse	**	then we do the actual copy.
15902432Sse	*/
15912432Sse	SCR_COPY (sizeof (struct head)),
15922432Sse	/*
15932432Sse	**	continued after the next label ...
15942432Sse	*/
15957228Sse
15962432Sse}/*-------------------------< LOADPOS >---------------------*/,{
15972432Sse		0,
15982432Sse		NADDR (header),
15992432Sse	/*
160039247Sgibbs	**      Mark this nccb as not scheduled.
16012432Sse	*/
16022432Sse	SCR_COPY (8),
16032432Sse		PADDR (idle),
16042432Sse		NADDR (header.launch),
16052432Sse	/*
16062432Sse	**      Set a time stamp for this selection
16072432Sse	*/
160839386Sgibbs	SCR_COPY (sizeof (ticks)),
160934961Sphk		KVAR (KVAR_TICKS),
16102432Sse		NADDR (header.stamp.select),
16112432Sse	/*
16122432Sse	**      load the savep (saved pointer) into
16132432Sse	**      the TEMP register (actual pointer)
16142432Sse	*/
16152432Sse	SCR_COPY (4),
16162432Sse		NADDR (header.savep),
16172432Sse		RADDR (temp),
16182432Sse	/*
16192432Sse	**      Initialize the status registers
16202432Sse	*/
16212432Sse	SCR_COPY (4),
16222432Sse		NADDR (header.status),
16232432Sse		RADDR (scr0),
16247228Sse
16252432Sse}/*-------------------------< PREPARE2 >---------------------*/,{
16262432Sse	/*
16272432Sse	**      Load the synchronous mode register
16282432Sse	*/
16292814Sse	SCR_COPY (1),
16302814Sse		NADDR (sync_st),
16312814Sse		RADDR (sxfer),
16322432Sse	/*
16332814Sse	**      Load the wide mode and timing register
16342814Sse	*/
16352814Sse	SCR_COPY (1),
16362814Sse		NADDR (wide_st),
16372814Sse		RADDR (scntl3),
16382814Sse	/*
16392432Sse	**	Initialize the msgout buffer with a NOOP message.
16402432Sse	*/
164139247Sgibbs	SCR_LOAD_REG (scratcha, MSG_NOOP),
16422432Sse		0,
16432432Sse	SCR_COPY (1),
16442432Sse		RADDR (scratcha),
16452432Sse		NADDR (msgout),
16462432Sse	SCR_COPY (1),
16472432Sse		RADDR (scratcha),
16482432Sse		NADDR (msgin),
16492432Sse	/*
16502814Sse	**	Message in phase ?
16512432Sse	*/
16522814Sse	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
16532432Sse		PADDR (dispatch),
16542432Sse	/*
16552814Sse	**	Extended or reject message ?
16562432Sse	*/
16572814Sse	SCR_FROM_REG (sbdl),
16582814Sse		0,
165939247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_EXTENDED)),
16602814Sse		PADDR (msg_in),
166139247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_MESSAGE_REJECT)),
166227744Sse		PADDRH (msg_reject),
16632814Sse	/*
16642814Sse	**	normal processing
16652814Sse	*/
16662432Sse	SCR_JUMP,
16672432Sse		PADDR (dispatch),
16682432Sse}/*-------------------------< SETMSG >----------------------*/,{
16692432Sse	SCR_COPY (1),
16702432Sse		RADDR (scratcha),
16712432Sse		NADDR (msgout),
16722432Sse	SCR_SET (SCR_ATN),
16732432Sse		0,
16742432Sse}/*-------------------------< CLRACK >----------------------*/,{
16752432Sse	/*
16762432Sse	**	Terminate possible pending message phase.
16772432Sse	*/
16782814Sse	SCR_CLR (SCR_ACK),
16792432Sse		0,
16807228Sse
16812432Sse}/*-----------------------< DISPATCH >----------------------*/,{
16822814Sse	SCR_FROM_REG (HS_REG),
16832814Sse		0,
16842814Sse	SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
16852814Sse		SIR_NEGO_FAILED,
16866179Sse	/*
16876179Sse	**	remove bogus output signals
16886179Sse	*/
16896179Sse	SCR_REG_REG (socl, SCR_AND, CACK|CATN),
16906179Sse		0,
16912432Sse	SCR_RETURN ^ IFTRUE (WHEN (SCR_DATA_OUT)),
16922432Sse		0,
16932432Sse	SCR_RETURN ^ IFTRUE (IF (SCR_DATA_IN)),
16942432Sse		0,
16952432Sse	SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)),
16962432Sse		PADDR (msg_out),
16972432Sse	SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN)),
16982432Sse		PADDR (msg_in),
16992432Sse	SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)),
17002432Sse		PADDR (command),
17012432Sse	SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)),
17022432Sse		PADDR (status),
17032432Sse	/*
17042432Sse	**      Discard one illegal phase byte, if required.
17052432Sse	*/
17062814Sse	SCR_LOAD_REG (scratcha, XE_BAD_PHASE),
17072814Sse		0,
17082814Sse	SCR_COPY (1),
17092814Sse		RADDR (scratcha),
17102814Sse		NADDR (xerr_st),
17112432Sse	SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_OUT)),
17122432Sse		8,
17132432Sse	SCR_MOVE_ABS (1) ^ SCR_ILG_OUT,
17142432Sse		NADDR (scratch),
17152432Sse	SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_IN)),
17162432Sse		8,
17172432Sse	SCR_MOVE_ABS (1) ^ SCR_ILG_IN,
17182432Sse		NADDR (scratch),
17192432Sse	SCR_JUMP,
17202432Sse		PADDR (dispatch),
17217228Sse
17222432Sse}/*-------------------------< NO_DATA >--------------------*/,{
17232432Sse	/*
17242432Sse	**	The target wants to tranfer too much data
17252432Sse	**	or in the wrong direction.
17262814Sse	**      Remember that in extended error.
17272432Sse	*/
17282814Sse	SCR_LOAD_REG (scratcha, XE_EXTRA_DATA),
17292432Sse		0,
17302432Sse	SCR_COPY (1),
17312432Sse		RADDR (scratcha),
17322814Sse		NADDR (xerr_st),
17332432Sse	/*
17342432Sse	**      Discard one data byte, if required.
17352432Sse	*/
17362432Sse	SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)),
17372432Sse		8,
17382432Sse	SCR_MOVE_ABS (1) ^ SCR_DATA_OUT,
17392432Sse		NADDR (scratch),
17402432Sse	SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)),
17412432Sse		8,
17422432Sse	SCR_MOVE_ABS (1) ^ SCR_DATA_IN,
17432432Sse		NADDR (scratch),
17442432Sse	/*
17452432Sse	**      .. and repeat as required.
17462432Sse	*/
17472432Sse	SCR_CALL,
17482432Sse		PADDR (dispatch),
17492432Sse	SCR_JUMP,
17502432Sse		PADDR (no_data),
17512432Sse}/*-------------------------< CHECKATN >--------------------*/,{
17522432Sse	/*
17532432Sse	**	If AAP (bit 1 of scntl0 register) is set
17542432Sse	**	and a parity error is detected,
17552432Sse	**	the script processor asserts ATN.
17562432Sse	**
17572432Sse	**	The target should switch to a MSG_OUT phase
17582432Sse	**	to get the message.
17592432Sse	*/
17602432Sse	SCR_FROM_REG (socl),
17612432Sse		0,
17622432Sse	SCR_JUMP ^ IFFALSE (MASK (CATN, CATN)),
17632432Sse		PADDR (dispatch),
17642432Sse	/*
17652432Sse	**	count it
17662432Sse	*/
17672814Sse	SCR_REG_REG (PS_REG, SCR_ADD, 1),
17682432Sse		0,
17692432Sse	/*
177039247Sgibbs	**	Prepare a MSG_INITIATOR_DET_ERR message
17712432Sse	**	(initiator detected error).
17722432Sse	**	The target should retry the transfer.
17732432Sse	*/
177439247Sgibbs	SCR_LOAD_REG (scratcha, MSG_INITIATOR_DET_ERR),
17752432Sse		0,
17762432Sse	SCR_JUMP,
17772432Sse		PADDR (setmsg),
17787228Sse
17792432Sse}/*-------------------------< COMMAND >--------------------*/,{
17802432Sse	/*
17812432Sse	**	If this is not a GETCC transfer ...
17822432Sse	*/
17832814Sse	SCR_FROM_REG (SS_REG),
17842432Sse		0,
178539247Sgibbs/*<<<*/	SCR_JUMPR ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)),
17862432Sse		28,
17872432Sse	/*
17882432Sse	**	... set a timestamp ...
17892432Sse	*/
179039386Sgibbs	SCR_COPY (sizeof (ticks)),
179134961Sphk		KVAR (KVAR_TICKS),
17922432Sse		NADDR (header.stamp.command),
17932432Sse	/*
17942432Sse	**	... and send the command
17952432Sse	*/
17962432Sse	SCR_MOVE_TBL ^ SCR_COMMAND,
17972432Sse		offsetof (struct dsb, cmd),
17982432Sse	SCR_JUMP,
17992432Sse		PADDR (dispatch),
18002432Sse	/*
18012432Sse	**	Send the GETCC command
18022432Sse	*/
18037250Sse/*>>>*/	SCR_MOVE_TBL ^ SCR_COMMAND,
18047250Sse		offsetof (struct dsb, scmd),
18052432Sse	SCR_JUMP,
18062432Sse		PADDR (dispatch),
18077228Sse
18082432Sse}/*-------------------------< STATUS >--------------------*/,{
18092432Sse	/*
18102432Sse	**	set the timestamp.
18112432Sse	*/
181239386Sgibbs	SCR_COPY (sizeof (ticks)),
181334961Sphk		KVAR (KVAR_TICKS),
18142432Sse		NADDR (header.stamp.status),
18152432Sse	/*
18162432Sse	**	If this is a GETCC transfer,
18172432Sse	*/
18182814Sse	SCR_FROM_REG (SS_REG),
18192432Sse		0,
182039247Sgibbs/*<<<*/	SCR_JUMPR ^ IFFALSE (DATA (SCSI_STATUS_CHECK_COND)),
18212814Sse		40,
18222432Sse	/*
18232432Sse	**	get the status
18242432Sse	*/
18252432Sse	SCR_MOVE_ABS (1) ^ SCR_STATUS,
18262432Sse		NADDR (scratch),
18272432Sse	/*
18282814Sse	**	Save status to scsi_status.
18292432Sse	**	Mark as complete.
18302432Sse	**	And wait for disconnect.
18312432Sse	*/
18322814Sse	SCR_TO_REG (SS_REG),
18332432Sse		0,
183439247Sgibbs	SCR_REG_REG (SS_REG, SCR_OR, SCSI_STATUS_SENSE),
18352432Sse		0,
18362814Sse	SCR_LOAD_REG (HS_REG, HS_COMPLETE),
18372814Sse		0,
18382432Sse	SCR_JUMP,
18392432Sse		PADDR (checkatn),
18402432Sse	/*
18412432Sse	**	If it was no GETCC transfer,
18422432Sse	**	save the status to scsi_status.
18432432Sse	*/
18442432Sse/*>>>*/	SCR_MOVE_ABS (1) ^ SCR_STATUS,
18452432Sse		NADDR (scratch),
18462814Sse	SCR_TO_REG (SS_REG),
18472432Sse		0,
18482432Sse	/*
18492432Sse	**	if it was no check condition ...
18502432Sse	*/
185139247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)),
18522432Sse		PADDR (checkatn),
18532432Sse	/*
18542432Sse	**	... mark as complete.
18552432Sse	*/
18562814Sse	SCR_LOAD_REG (HS_REG, HS_COMPLETE),
18572432Sse		0,
18582432Sse	SCR_JUMP,
18592432Sse		PADDR (checkatn),
18607228Sse
18612432Sse}/*-------------------------< MSG_IN >--------------------*/,{
18622432Sse	/*
18632432Sse	**	Get the first byte of the message
18642432Sse	**	and save it to SCRATCHA.
18652432Sse	**
18662432Sse	**	The script processor doesn't negate the
18672432Sse	**	ACK signal after this transfer.
18682432Sse	*/
18692432Sse	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
18702432Sse		NADDR (msgin[0]),
18712432Sse	/*
18722432Sse	**	Check for message parity error.
18732432Sse	*/
18742432Sse	SCR_TO_REG (scratcha),
18752432Sse		0,
18762432Sse	SCR_FROM_REG (socl),
18772432Sse		0,
18782432Sse	SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)),
187927744Sse		PADDRH (msg_parity),
18802432Sse	SCR_FROM_REG (scratcha),
18812432Sse		0,
18822432Sse	/*
18832432Sse	**	Parity was ok, handle this message.
18842432Sse	*/
188539247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_CMDCOMPLETE)),
18862432Sse		PADDR (complete),
188739247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_SAVEDATAPOINTER)),
18882432Sse		PADDR (save_dp),
188939247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_RESTOREPOINTERS)),
18902432Sse		PADDR (restore_dp),
189139247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_DISCONNECT)),
18922432Sse		PADDR (disconnect),
189339247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_EXTENDED)),
189427744Sse		PADDRH (msg_extended),
189539247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_NOOP)),
18962814Sse		PADDR (clrack),
189739247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_MESSAGE_REJECT)),
189827744Sse		PADDRH (msg_reject),
189939247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_IGN_WIDE_RESIDUE)),
190027744Sse		PADDRH (msg_ign_residue),
19012432Sse	/*
19022432Sse	**	Rest of the messages left as
19032432Sse	**	an exercise ...
19042432Sse	**
19052432Sse	**	Unimplemented messages:
19062432Sse	**	fall through to MSG_BAD.
19072432Sse	*/
19082432Sse}/*-------------------------< MSG_BAD >------------------*/,{
19092432Sse	/*
19102432Sse	**	unimplemented message - reject it.
19112432Sse	*/
19122432Sse	SCR_INT,
19132814Sse		SIR_REJECT_SENT,
191439247Sgibbs	SCR_LOAD_REG (scratcha, MSG_MESSAGE_REJECT),
19152432Sse		0,
19162432Sse	SCR_JUMP,
19172432Sse		PADDR (setmsg),
19187228Sse
19192432Sse}/*-------------------------< COMPLETE >-----------------*/,{
19202432Sse	/*
19212432Sse	**	Complete message.
19222432Sse	**
19232814Sse	**	If it's not the get condition code,
19242814Sse	**	copy TEMP register to LASTP in header.
19252814Sse	*/
19262814Sse	SCR_FROM_REG (SS_REG),
19272814Sse		0,
192839247Sgibbs/*<<<*/	SCR_JUMPR ^ IFTRUE (MASK (SCSI_STATUS_SENSE, SCSI_STATUS_SENSE)),
19292814Sse		12,
19302814Sse	SCR_COPY (4),
19312814Sse		RADDR (temp),
19322814Sse		NADDR (header.lastp),
19332814Sse/*>>>*/	/*
19342432Sse	**	When we terminate the cycle by clearing ACK,
19352432Sse	**	the target may disconnect immediately.
19362432Sse	**
19372432Sse	**	We don't want to be told of an
19382432Sse	**	"unexpected disconnect",
19392432Sse	**	so we disable this feature.
19402432Sse	*/
19412432Sse	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
19422432Sse		0,
19432432Sse	/*
19442432Sse	**	Terminate cycle ...
19452432Sse	*/
19466215Sse	SCR_CLR (SCR_ACK|SCR_ATN),
19472432Sse		0,
19482432Sse	/*
19492432Sse	**	... and wait for the disconnect.
19502432Sse	*/
19512432Sse	SCR_WAIT_DISC,
19522432Sse		0,
19532432Sse}/*-------------------------< CLEANUP >-------------------*/,{
19542432Sse	/*
195539247Sgibbs	**      dsa:    Pointer to nccb
195639247Sgibbs	**	      or xxxxxxFF (no nccb)
19572432Sse	**
19582814Sse	**      HS_REG:   Host-Status (<>0!)
19592432Sse	*/
19602432Sse	SCR_FROM_REG (dsa),
19612432Sse		0,
19622432Sse	SCR_JUMP ^ IFTRUE (DATA (0xff)),
19632432Sse		PADDR (signal),
19642432Sse	/*
19652432Sse	**      dsa is valid.
19662432Sse	**	save the status registers
19672432Sse	*/
19682432Sse	SCR_COPY (4),
19692432Sse		RADDR (scr0),
19702432Sse		NADDR (header.status),
19712432Sse	/*
197239247Sgibbs	**	and copy back the header to the nccb.
19732432Sse	*/
197427684Sse	SCR_COPY_F (4),
19752432Sse		RADDR (dsa),
19762814Sse		PADDR (cleanup0),
19772432Sse	SCR_COPY (sizeof (struct head)),
19782432Sse		NADDR (header),
19792814Sse}/*-------------------------< CLEANUP0 >--------------------*/,{
19802432Sse		0,
19817228Sse
19822432Sse	/*
19832432Sse	**	If command resulted in "check condition"
19842432Sse	**	status and is not yet completed,
19852432Sse	**	try to get the condition code.
19862432Sse	*/
19872814Sse	SCR_FROM_REG (HS_REG),
19882432Sse		0,
19892814Sse/*<<<*/	SCR_JUMPR ^ IFFALSE (MASK (0, HS_DONEMASK)),
19902432Sse		16,
19912814Sse	SCR_FROM_REG (SS_REG),
19922432Sse		0,
199339247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)),
199427744Sse		PADDRH(getcc2),
19952432Sse}/*-------------------------< SIGNAL >----------------------*/,{
19962432Sse	/*
19972432Sse	**	if status = queue full,
19982432Sse	**	reinsert in startqueue and stall queue.
19992432Sse	*/
200039247Sgibbs/*>>>*/	SCR_FROM_REG (SS_REG),
20012432Sse		0,
200239247Sgibbs	SCR_INT ^ IFTRUE (DATA (SCSI_STATUS_QUEUE_FULL)),
20032814Sse		SIR_STALL_QUEUE,
200439247Sgibbs  	/*
200539247Sgibbs	**	And make the DSA register invalid.
200639247Sgibbs	*/
200739247Sgibbs	SCR_LOAD_REG (dsa, 0xff), /* invalid */
200839247Sgibbs		0,
20092432Sse	/*
20102432Sse	**	if job completed ...
20112432Sse	*/
20122814Sse	SCR_FROM_REG (HS_REG),
20132432Sse		0,
20142432Sse	/*
20152432Sse	**	... signal completion to the host
20162432Sse	*/
20172814Sse	SCR_INT_FLY ^ IFFALSE (MASK (0, HS_DONEMASK)),
20182432Sse		0,
20192432Sse	/*
20202432Sse	**	Auf zu neuen Schandtaten!
20212432Sse	*/
20222432Sse	SCR_JUMP,
20232432Sse		PADDR(start),
20247228Sse
20252432Sse}/*-------------------------< SAVE_DP >------------------*/,{
20262432Sse	/*
20272432Sse	**	SAVE_DP message:
20282432Sse	**	Copy TEMP register to SAVEP in header.
20292432Sse	*/
20302432Sse	SCR_COPY (4),
20312432Sse		RADDR (temp),
20322432Sse		NADDR (header.savep),
20332432Sse	SCR_JUMP,
20342432Sse		PADDR (clrack),
20352432Sse}/*-------------------------< RESTORE_DP >---------------*/,{
20362432Sse	/*
20372432Sse	**	RESTORE_DP message:
20382432Sse	**	Copy SAVEP in header to TEMP register.
20392432Sse	*/
20402432Sse	SCR_COPY (4),
20412432Sse		NADDR (header.savep),
20422432Sse		RADDR (temp),
20432432Sse	SCR_JUMP,
20442432Sse		PADDR (clrack),
20457228Sse
20462432Sse}/*-------------------------< DISCONNECT >---------------*/,{
20472432Sse	/*
20482814Sse	**	If QUIRK_AUTOSAVE is set,
2049108470Sschweikh	**	do a "save pointer" operation.
20502814Sse	*/
20512814Sse	SCR_FROM_REG (QU_REG),
20522814Sse		0,
20532814Sse/*<<<*/	SCR_JUMPR ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)),
20542814Sse		12,
20552814Sse	/*
20562814Sse	**	like SAVE_DP message:
20572814Sse	**	Copy TEMP register to SAVEP in header.
20582814Sse	*/
20592814Sse	SCR_COPY (4),
20602814Sse		RADDR (temp),
20612814Sse		NADDR (header.savep),
20622814Sse/*>>>*/	/*
20632814Sse	**	Check if temp==savep or temp==goalp:
20642814Sse	**	if not, log a missing save pointer message.
206510567Sse	**	In fact, it's a comparison mod 256.
20662814Sse	**
20672814Sse	**	Hmmm, I hadn't thought that I would be urged to
20682814Sse	**	write this kind of ugly self modifying code.
20692814Sse	**
20702814Sse	**	It's unbelievable, but the ncr53c8xx isn't able
20712814Sse	**	to subtract one register from another.
20722814Sse	*/
20732814Sse	SCR_FROM_REG (temp),
20742814Sse		0,
20752814Sse	/*
20762814Sse	**	You are not expected to understand this ..
207710567Sse	**
207810567Sse	**	CAUTION: only little endian architectures supported! XXX
20792814Sse	*/
208027684Sse	SCR_COPY_F (1),
20812814Sse		NADDR (header.savep),
20822814Sse		PADDR (disconnect0),
20832814Sse}/*-------------------------< DISCONNECT0 >--------------*/,{
20842814Sse/*<<<*/	SCR_JUMPR ^ IFTRUE (DATA (1)),
20852814Sse		20,
20862814Sse	/*
20872814Sse	**	neither this
20882814Sse	*/
208927684Sse	SCR_COPY_F (1),
20902814Sse		NADDR (header.goalp),
20912814Sse		PADDR (disconnect1),
20922814Sse}/*-------------------------< DISCONNECT1 >--------------*/,{
20932814Sse	SCR_INT ^ IFFALSE (DATA (1)),
20942814Sse		SIR_MISSING_SAVE,
20952814Sse/*>>>*/
20967228Sse
20972814Sse	/*
20982814Sse	**	DISCONNECTing  ...
20992814Sse	**
21006132Sdg	**	disable the "unexpected disconnect" feature,
21016132Sdg	**	and remove the ACK signal.
21022432Sse	*/
21032432Sse	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
21042432Sse		0,
21056215Sse	SCR_CLR (SCR_ACK|SCR_ATN),
21062432Sse		0,
21072432Sse	/*
21082432Sse	**	Wait for the disconnect.
21092432Sse	*/
21102432Sse	SCR_WAIT_DISC,
21112432Sse		0,
21122432Sse	/*
21132432Sse	**	Profiling:
21142432Sse	**	Set a time stamp,
21152432Sse	**	and count the disconnects.
21162432Sse	*/
211739386Sgibbs	SCR_COPY (sizeof (ticks)),
211834961Sphk		KVAR (KVAR_TICKS),
21192432Sse		NADDR (header.stamp.disconnect),
21202432Sse	SCR_COPY (4),
21212432Sse		NADDR (disc_phys),
21222432Sse		RADDR (temp),
21232432Sse	SCR_REG_REG (temp, SCR_ADD, 0x01),
21242432Sse		0,
21252432Sse	SCR_COPY (4),
21262432Sse		RADDR (temp),
21272432Sse		NADDR (disc_phys),
21282432Sse	/*
21292432Sse	**	Status is: DISCONNECTED.
21302432Sse	*/
21312814Sse	SCR_LOAD_REG (HS_REG, HS_DISCONNECT),
21322432Sse		0,
21332432Sse	SCR_JUMP,
21342432Sse		PADDR (cleanup),
21357228Sse
21362432Sse}/*-------------------------< MSG_OUT >-------------------*/,{
21372432Sse	/*
21382432Sse	**	The target requests a message.
21392432Sse	*/
21402432Sse	SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
21412432Sse		NADDR (msgout),
21422432Sse	SCR_COPY (1),
21432432Sse		RADDR (sfbr),
21442432Sse		NADDR (lastmsg),
21452432Sse	/*
21462432Sse	**	If it was no ABORT message ...
21472432Sse	*/
214839247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_ABORT)),
214927744Sse		PADDRH (msg_out_abort),
21502432Sse	/*
21512432Sse	**	... wait for the next phase
21522432Sse	**	if it's a message out, send it again, ...
21532432Sse	*/
21542432Sse	SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
21552432Sse		PADDR (msg_out),
21562432Sse}/*-------------------------< MSG_OUT_DONE >--------------*/,{
21572432Sse	/*
21582432Sse	**	... else clear the message ...
21592432Sse	*/
216039247Sgibbs	SCR_LOAD_REG (scratcha, MSG_NOOP),
21612432Sse		0,
21622432Sse	SCR_COPY (4),
21632432Sse		RADDR (scratcha),
21642432Sse		NADDR (msgout),
21652432Sse	/*
21662432Sse	**	... and process the next phase
21672432Sse	*/
21682432Sse	SCR_JUMP,
21692432Sse		PADDR (dispatch),
21707228Sse
21712432Sse}/*------------------------< BADGETCC >---------------------*/,{
21722432Sse	/*
21732432Sse	**	If SIGP was set, clear it and try again.
21742432Sse	*/
21752432Sse	SCR_FROM_REG (ctest2),
21762432Sse		0,
21772432Sse	SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)),
217827744Sse		PADDRH (getcc2),
21792432Sse	SCR_INT,
21802814Sse		SIR_SENSE_FAILED,
21812432Sse}/*-------------------------< RESELECT >--------------------*/,{
21822432Sse	/*
218327684Sse	**	This NOP will be patched with LED OFF
218427684Sse	**	SCR_REG_REG (gpreg, SCR_OR, 0x01)
218527684Sse	*/
218627684Sse	SCR_NO_OP,
218727684Sse		0,
218827684Sse
218927684Sse	/*
21902432Sse	**	make the DSA invalid.
21912432Sse	*/
21922432Sse	SCR_LOAD_REG (dsa, 0xff),
21932432Sse		0,
21942432Sse	SCR_CLR (SCR_TRG),
21952432Sse		0,
21962432Sse	/*
21972432Sse	**	Sleep waiting for a reselection.
21982432Sse	**	If SIGP is set, special treatment.
21992432Sse	**
22002432Sse	**	Zu allem bereit ..
22012432Sse	*/
22022432Sse	SCR_WAIT_RESEL,
22032432Sse		PADDR(reselect2),
220427684Sse}/*-------------------------< RESELECT1 >--------------------*/,{
22052432Sse	/*
220627684Sse	**	This NOP will be patched with LED ON
220727684Sse	**	SCR_REG_REG (gpreg, SCR_AND, 0xfe)
220827684Sse	*/
220927684Sse	SCR_NO_OP,
221027684Sse		0,
221127684Sse	/*
22122432Sse	**	... zu nichts zu gebrauchen ?
22132432Sse	**
22142432Sse	**      load the target id into the SFBR
22152432Sse	**	and jump to the control block.
22162432Sse	**
22172432Sse	**	Look at the declarations of
22182432Sse	**	- struct ncb
22192432Sse	**	- struct tcb
22202432Sse	**	- struct lcb
222139247Sgibbs	**	- struct nccb
22222432Sse	**	to understand what's going on.
22232432Sse	*/
222418875Sse	SCR_REG_SFBR (ssid, SCR_AND, 0x8F),
22252432Sse		0,
222646843Sse	SCR_TO_REG (sdid),
22272432Sse		0,
22282432Sse	SCR_JUMP,
22292432Sse		NADDR (jump_tcb),
22302432Sse}/*-------------------------< RESELECT2 >-------------------*/,{
22312432Sse	/*
223227684Sse	**	This NOP will be patched with LED ON
223327684Sse	**	SCR_REG_REG (gpreg, SCR_AND, 0xfe)
223427684Sse	*/
223527684Sse	SCR_NO_OP,
223627684Sse		0,
223727684Sse	/*
22382432Sse	**	If it's not connected :(
22396705Sse	**	-> interrupted by SIGP bit.
22402432Sse	**	Jump to start.
22412432Sse	*/
22422432Sse	SCR_FROM_REG (ctest2),
22432432Sse		0,
22442432Sse	SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)),
22452432Sse		PADDR (start),
22462432Sse	SCR_JUMP,
22472432Sse		PADDR (reselect),
22487228Sse
22492432Sse}/*-------------------------< RESEL_TMP >-------------------*/,{
22502432Sse	/*
22512432Sse	**	The return address in TEMP
22522432Sse	**	is in fact the data structure address,
22532432Sse	**	so copy it to the DSA register.
22542432Sse	*/
22552432Sse	SCR_COPY (4),
22562432Sse		RADDR (temp),
22572432Sse		RADDR (dsa),
22582432Sse	SCR_JUMP,
22592432Sse		PADDR (prepare),
22602432Sse
22612432Sse}/*-------------------------< RESEL_LUN >-------------------*/,{
22622432Sse	/*
22632432Sse	**	come back to this point
22642432Sse	**	to get an IDENTIFY message
22652432Sse	**	Wait for a msg_in phase.
22662432Sse	*/
22672432Sse/*<<<*/	SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)),
22682432Sse		48,
22692432Sse	/*
22702432Sse	**	message phase
22712432Sse	**	It's not a sony, it's a trick:
22722432Sse	**	read the data without acknowledging it.
22732432Sse	*/
22742432Sse	SCR_FROM_REG (sbdl),
22752432Sse		0,
227639247Sgibbs/*<<<*/	SCR_JUMPR ^ IFFALSE (MASK (MSG_IDENTIFYFLAG, 0x98)),
22772432Sse		32,
22782432Sse	/*
22792432Sse	**	It WAS an Identify message.
22802432Sse	**	get it and ack it!
22812432Sse	*/
22822432Sse	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
22832432Sse		NADDR (msgin),
22842432Sse	SCR_CLR (SCR_ACK),
22852432Sse		0,
22862432Sse	/*
22877228Sse	**	Mask out the lun.
22882432Sse	*/
22892432Sse	SCR_REG_REG (sfbr, SCR_AND, 0x07),
22902432Sse		0,
22912432Sse	SCR_RETURN,
22922432Sse		0,
22932432Sse	/*
22942432Sse	**	No message phase or no IDENTIFY message:
22952432Sse	**	return 0.
22962432Sse	*/
22972432Sse/*>>>*/	SCR_LOAD_SFBR (0),
22982432Sse		0,
22992432Sse	SCR_RETURN,
23002432Sse		0,
23017228Sse
23022432Sse}/*-------------------------< RESEL_TAG >-------------------*/,{
23032432Sse	/*
23042432Sse	**	come back to this point
23052432Sse	**	to get a SIMPLE_TAG message
23062432Sse	**	Wait for a MSG_IN phase.
23072432Sse	*/
23082432Sse/*<<<*/	SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)),
23092432Sse		64,
23102432Sse	/*
23112432Sse	**	message phase
23122432Sse	**	It's a trick - read the data
23132432Sse	**	without acknowledging it.
23142432Sse	*/
23152432Sse	SCR_FROM_REG (sbdl),
23162432Sse		0,
231739247Sgibbs/*<<<*/	SCR_JUMPR ^ IFFALSE (DATA (MSG_SIMPLE_Q_TAG)),
23182432Sse		48,
23192432Sse	/*
23202432Sse	**	It WAS a SIMPLE_TAG message.
23212432Sse	**	get it and ack it!
23222432Sse	*/
23232432Sse	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
23242432Sse		NADDR (msgin),
23252432Sse	SCR_CLR (SCR_ACK),
23262432Sse		0,
23272432Sse	/*
23282432Sse	**	Wait for the second byte (the tag)
23292432Sse	*/
23302432Sse/*<<<*/	SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)),
23312432Sse		24,
23322432Sse	/*
23332432Sse	**	Get it and ack it!
23342432Sse	*/
23352432Sse	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
23362432Sse		NADDR (msgin),
23372432Sse	SCR_CLR (SCR_ACK|SCR_CARRY),
23382432Sse		0,
23392432Sse	SCR_RETURN,
23402432Sse		0,
23412432Sse	/*
23422432Sse	**	No message phase or no SIMPLE_TAG message
23432432Sse	**	or no second byte: return 0.
23442432Sse	*/
23452432Sse/*>>>*/	SCR_LOAD_SFBR (0),
23462432Sse		0,
23472432Sse	SCR_SET (SCR_CARRY),
23482432Sse		0,
23492432Sse	SCR_RETURN,
23502432Sse		0,
23517228Sse
23522432Sse}/*-------------------------< DATA_IN >--------------------*/,{
23532432Sse/*
23542432Sse**	Because the size depends on the
23552432Sse**	#define MAX_SCATTER parameter,
23562432Sse**	it is filled in at runtime.
23572432Sse**
23582432Sse**	SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)),
23592432Sse**		PADDR (no_data),
236039386Sgibbs**	SCR_COPY (sizeof (ticks)),
236134961Sphk**		KVAR (KVAR_TICKS),
23622432Sse**		NADDR (header.stamp.data),
23632432Sse**	SCR_MOVE_TBL ^ SCR_DATA_IN,
23642432Sse**		offsetof (struct dsb, data[ 0]),
23652432Sse**
23662432Sse**  ##===========< i=1; i<MAX_SCATTER >=========
23672432Sse**  ||	SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)),
23682432Sse**  ||		PADDR (checkatn),
23692432Sse**  ||	SCR_MOVE_TBL ^ SCR_DATA_IN,
23702432Sse**  ||		offsetof (struct dsb, data[ i]),
23712432Sse**  ##==========================================
23722432Sse**
23732432Sse**	SCR_CALL,
23742432Sse**		PADDR (checkatn),
23752432Sse**	SCR_JUMP,
23762432Sse**		PADDR (no_data),
23772432Sse*/
23782432Sse0
23792432Sse}/*-------------------------< DATA_OUT >-------------------*/,{
23802432Sse/*
23812432Sse**	Because the size depends on the
23822432Sse**	#define MAX_SCATTER parameter,
23832432Sse**	it is filled in at runtime.
23842432Sse**
238527744Sse**	SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_OUT)),
23862432Sse**		PADDR (no_data),
238739386Sgibbs**	SCR_COPY (sizeof (ticks)),
238834961Sphk**		KVAR (KVAR_TICKS),
23892432Sse**		NADDR (header.stamp.data),
23902432Sse**	SCR_MOVE_TBL ^ SCR_DATA_OUT,
23912432Sse**		offsetof (struct dsb, data[ 0]),
23922432Sse**
23932432Sse**  ##===========< i=1; i<MAX_SCATTER >=========
23942432Sse**  ||	SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)),
23952432Sse**  ||		PADDR (dispatch),
23962432Sse**  ||	SCR_MOVE_TBL ^ SCR_DATA_OUT,
23972432Sse**  ||		offsetof (struct dsb, data[ i]),
23982432Sse**  ##==========================================
23992432Sse**
24002432Sse**	SCR_CALL,
24012432Sse**		PADDR (dispatch),
24022432Sse**	SCR_JUMP,
24032432Sse**		PADDR (no_data),
24042432Sse**
24052432Sse**---------------------------------------------------------
24062432Sse*/
240736735Sdfr(u_long)0
24087228Sse
240927744Sse}/*--------------------------------------------------------*/
241027744Sse};
241127744Sse
241227744Sse
241327744Ssestatic	struct scripth scripth0 = {
241427744Sse/*-------------------------< TRYLOOP >---------------------*/{
241527744Sse/*
241627744Sse**	Load an entry of the start queue into dsa
241727744Sse**	and try to start it by jumping to TRYSEL.
241827744Sse**
241927744Sse**	Because the size depends on the
242027744Sse**	#define MAX_START parameter, it is filled
242127744Sse**	in at runtime.
242227744Sse**
242327744Sse**-----------------------------------------------------------
242427744Sse**
242527744Sse**  ##===========< I=0; i<MAX_START >===========
242627744Sse**  ||	SCR_COPY (4),
242727744Sse**  ||		NADDR (squeue[i]),
242827744Sse**  ||		RADDR (dsa),
242927744Sse**  ||	SCR_CALL,
243027744Sse**  ||		PADDR (trysel),
243127744Sse**  ##==========================================
243227744Sse**
243327744Sse**	SCR_JUMP,
243427744Sse**		PADDRH(tryloop),
243527744Sse**
243627744Sse**-----------------------------------------------------------
243727744Sse*/
243827744Sse0
243927744Sse}/*-------------------------< MSG_PARITY >---------------*/,{
244027744Sse	/*
244127744Sse	**	count it
244227744Sse	*/
244327744Sse	SCR_REG_REG (PS_REG, SCR_ADD, 0x01),
244427744Sse		0,
244527744Sse	/*
244627744Sse	**	send a "message parity error" message.
244727744Sse	*/
244839247Sgibbs	SCR_LOAD_REG (scratcha, MSG_PARITY_ERROR),
244927744Sse		0,
245027744Sse	SCR_JUMP,
245127744Sse		PADDR (setmsg),
245239247Sgibbs}/*-------------------------< MSG_MESSAGE_REJECT >---------------*/,{
245327744Sse	/*
245427744Sse	**	If a negotiation was in progress,
245527744Sse	**	negotiation failed.
245627744Sse	*/
245727744Sse	SCR_FROM_REG (HS_REG),
245827744Sse		0,
245927744Sse	SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
246027744Sse		SIR_NEGO_FAILED,
246127744Sse	/*
246227744Sse	**	else make host log this message
246327744Sse	*/
246427744Sse	SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)),
246527744Sse		SIR_REJECT_RECEIVED,
246627744Sse	SCR_JUMP,
246727744Sse		PADDR (clrack),
246827744Sse
246927744Sse}/*-------------------------< MSG_IGN_RESIDUE >----------*/,{
247027744Sse	/*
247127744Sse	**	Terminate cycle
247227744Sse	*/
247327744Sse	SCR_CLR (SCR_ACK),
247427744Sse		0,
247527744Sse	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
247627744Sse		PADDR (dispatch),
247727744Sse	/*
247827744Sse	**	get residue size.
247927744Sse	*/
248027744Sse	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
248127744Sse		NADDR (msgin[1]),
248227744Sse	/*
248327744Sse	**	Check for message parity error.
248427744Sse	*/
248527744Sse	SCR_TO_REG (scratcha),
248627744Sse		0,
248727744Sse	SCR_FROM_REG (socl),
248827744Sse		0,
248927744Sse	SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)),
249027744Sse		PADDRH (msg_parity),
249127744Sse	SCR_FROM_REG (scratcha),
249227744Sse		0,
249327744Sse	/*
249427744Sse	**	Size is 0 .. ignore message.
249527744Sse	*/
249627744Sse	SCR_JUMP ^ IFTRUE (DATA (0)),
249727744Sse		PADDR (clrack),
249827744Sse	/*
249927744Sse	**	Size is not 1 .. have to interrupt.
250027744Sse	*/
250127744Sse/*<<<*/	SCR_JUMPR ^ IFFALSE (DATA (1)),
250227744Sse		40,
250327744Sse	/*
250427744Sse	**	Check for residue byte in swide register
250527744Sse	*/
250627744Sse	SCR_FROM_REG (scntl2),
250727744Sse		0,
250827744Sse/*<<<*/	SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)),
250927744Sse		16,
251027744Sse	/*
251127744Sse	**	There IS data in the swide register.
251227744Sse	**	Discard it.
251327744Sse	*/
251427744Sse	SCR_REG_REG (scntl2, SCR_OR, WSR),
251527744Sse		0,
251627744Sse	SCR_JUMP,
251727744Sse		PADDR (clrack),
251827744Sse	/*
251927744Sse	**	Load again the size to the sfbr register.
252027744Sse	*/
252127744Sse/*>>>*/	SCR_FROM_REG (scratcha),
252227744Sse		0,
252327744Sse/*>>>*/	SCR_INT,
252427744Sse		SIR_IGN_RESIDUE,
252527744Sse	SCR_JUMP,
252627744Sse		PADDR (clrack),
252727744Sse
252827744Sse}/*-------------------------< MSG_EXTENDED >-------------*/,{
252927744Sse	/*
253027744Sse	**	Terminate cycle
253127744Sse	*/
253227744Sse	SCR_CLR (SCR_ACK),
253327744Sse		0,
253427744Sse	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
253527744Sse		PADDR (dispatch),
253627744Sse	/*
253727744Sse	**	get length.
253827744Sse	*/
253927744Sse	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
254027744Sse		NADDR (msgin[1]),
254127744Sse	/*
254227744Sse	**	Check for message parity error.
254327744Sse	*/
254427744Sse	SCR_TO_REG (scratcha),
254527744Sse		0,
254627744Sse	SCR_FROM_REG (socl),
254727744Sse		0,
254827744Sse	SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)),
254927744Sse		PADDRH (msg_parity),
255027744Sse	SCR_FROM_REG (scratcha),
255127744Sse		0,
255227744Sse	/*
255327744Sse	*/
255427744Sse	SCR_JUMP ^ IFTRUE (DATA (3)),
255527744Sse		PADDRH (msg_ext_3),
255627744Sse	SCR_JUMP ^ IFFALSE (DATA (2)),
255727744Sse		PADDR (msg_bad),
255827744Sse}/*-------------------------< MSG_EXT_2 >----------------*/,{
255927744Sse	SCR_CLR (SCR_ACK),
256027744Sse		0,
256127744Sse	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
256227744Sse		PADDR (dispatch),
256327744Sse	/*
256427744Sse	**	get extended message code.
256527744Sse	*/
256627744Sse	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
256727744Sse		NADDR (msgin[2]),
256827744Sse	/*
256927744Sse	**	Check for message parity error.
257027744Sse	*/
257127744Sse	SCR_TO_REG (scratcha),
257227744Sse		0,
257327744Sse	SCR_FROM_REG (socl),
257427744Sse		0,
257527744Sse	SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)),
257627744Sse		PADDRH (msg_parity),
257727744Sse	SCR_FROM_REG (scratcha),
257827744Sse		0,
257939247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_EXT_WDTR)),
258027744Sse		PADDRH (msg_wdtr),
258127744Sse	/*
258227744Sse	**	unknown extended message
258327744Sse	*/
258427744Sse	SCR_JUMP,
258527744Sse		PADDR (msg_bad)
258627744Sse}/*-------------------------< MSG_WDTR >-----------------*/,{
258727744Sse	SCR_CLR (SCR_ACK),
258827744Sse		0,
258927744Sse	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
259027744Sse		PADDR (dispatch),
259127744Sse	/*
259227744Sse	**	get data bus width
259327744Sse	*/
259427744Sse	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
259527744Sse		NADDR (msgin[3]),
259627744Sse	SCR_FROM_REG (socl),
259727744Sse		0,
259827744Sse	SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)),
259927744Sse		PADDRH (msg_parity),
260027744Sse	/*
260127744Sse	**	let the host do the real work.
260227744Sse	*/
260327744Sse	SCR_INT,
260427744Sse		SIR_NEGO_WIDE,
260527744Sse	/*
260627744Sse	**	let the target fetch our answer.
260727744Sse	*/
260827744Sse	SCR_SET (SCR_ATN),
260927744Sse		0,
261027744Sse	SCR_CLR (SCR_ACK),
261127744Sse		0,
261227744Sse
261327744Sse	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
261427744Sse		SIR_NEGO_PROTO,
261527744Sse	/*
261639247Sgibbs	**	Send the MSG_EXT_WDTR
261727744Sse	*/
261827744Sse	SCR_MOVE_ABS (4) ^ SCR_MSG_OUT,
261927744Sse		NADDR (msgout),
262027744Sse	SCR_CLR (SCR_ATN),
262127744Sse		0,
262227744Sse	SCR_COPY (1),
262327744Sse		RADDR (sfbr),
262427744Sse		NADDR (lastmsg),
262527744Sse	SCR_JUMP,
262627744Sse		PADDR (msg_out_done),
262727744Sse
262827744Sse}/*-------------------------< MSG_EXT_3 >----------------*/,{
262927744Sse	SCR_CLR (SCR_ACK),
263027744Sse		0,
263127744Sse	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
263227744Sse		PADDR (dispatch),
263327744Sse	/*
263427744Sse	**	get extended message code.
263527744Sse	*/
263627744Sse	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
263727744Sse		NADDR (msgin[2]),
263827744Sse	/*
263927744Sse	**	Check for message parity error.
264027744Sse	*/
264127744Sse	SCR_TO_REG (scratcha),
264227744Sse		0,
264327744Sse	SCR_FROM_REG (socl),
264427744Sse		0,
264527744Sse	SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)),
264627744Sse		PADDRH (msg_parity),
264727744Sse	SCR_FROM_REG (scratcha),
264827744Sse		0,
264939247Sgibbs	SCR_JUMP ^ IFTRUE (DATA (MSG_EXT_SDTR)),
265027744Sse		PADDRH (msg_sdtr),
265127744Sse	/*
265227744Sse	**	unknown extended message
265327744Sse	*/
265427744Sse	SCR_JUMP,
265527744Sse		PADDR (msg_bad)
265627744Sse
265727744Sse}/*-------------------------< MSG_SDTR >-----------------*/,{
265827744Sse	SCR_CLR (SCR_ACK),
265927744Sse		0,
266027744Sse	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
266127744Sse		PADDR (dispatch),
266227744Sse	/*
266327744Sse	**	get period and offset
266427744Sse	*/
266527744Sse	SCR_MOVE_ABS (2) ^ SCR_MSG_IN,
266627744Sse		NADDR (msgin[3]),
266727744Sse	SCR_FROM_REG (socl),
266827744Sse		0,
266927744Sse	SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)),
267027744Sse		PADDRH (msg_parity),
267127744Sse	/*
267227744Sse	**	let the host do the real work.
267327744Sse	*/
267427744Sse	SCR_INT,
267527744Sse		SIR_NEGO_SYNC,
267627744Sse	/*
267727744Sse	**	let the target fetch our answer.
267827744Sse	*/
267927744Sse	SCR_SET (SCR_ATN),
268027744Sse		0,
268127744Sse	SCR_CLR (SCR_ACK),
268227744Sse		0,
268327744Sse
268427744Sse	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
268527744Sse		SIR_NEGO_PROTO,
268627744Sse	/*
268739247Sgibbs	**	Send the MSG_EXT_SDTR
268827744Sse	*/
268927744Sse	SCR_MOVE_ABS (5) ^ SCR_MSG_OUT,
269027744Sse		NADDR (msgout),
269127744Sse	SCR_CLR (SCR_ATN),
269227744Sse		0,
269327744Sse	SCR_COPY (1),
269427744Sse		RADDR (sfbr),
269527744Sse		NADDR (lastmsg),
269627744Sse	SCR_JUMP,
269727744Sse		PADDR (msg_out_done),
269827744Sse
269927744Sse}/*-------------------------< MSG_OUT_ABORT >-------------*/,{
270027744Sse	/*
270127744Sse	**	After ABORT message,
270227744Sse	**
270327744Sse	**	expect an immediate disconnect, ...
270427744Sse	*/
270527744Sse	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
270627744Sse		0,
270727744Sse	SCR_CLR (SCR_ACK|SCR_ATN),
270827744Sse		0,
270927744Sse	SCR_WAIT_DISC,
271027744Sse		0,
271127744Sse	/*
271227744Sse	**	... and set the status to "ABORTED"
271327744Sse	*/
271427744Sse	SCR_LOAD_REG (HS_REG, HS_ABORTED),
271527744Sse		0,
271627744Sse	SCR_JUMP,
271727744Sse		PADDR (cleanup),
271827744Sse
271927744Sse}/*-------------------------< GETCC >-----------------------*/,{
272027744Sse	/*
272127744Sse	**	The ncr doesn't have an indirect load
272227744Sse	**	or store command. So we have to
272327744Sse	**	copy part of the control block to a
272427744Sse	**	fixed place, where we can modify it.
272527744Sse	**
272627744Sse	**	We patch the address part of a COPY command
272727744Sse	**	with the address of the dsa register ...
272827744Sse	*/
272927744Sse	SCR_COPY_F (4),
273027744Sse		RADDR (dsa),
273127744Sse		PADDRH (getcc1),
273227744Sse	/*
273327744Sse	**	... then we do the actual copy.
273427744Sse	*/
273527744Sse	SCR_COPY (sizeof (struct head)),
273627744Sse}/*-------------------------< GETCC1 >----------------------*/,{
273727744Sse		0,
273827744Sse		NADDR (header),
273927744Sse	/*
274027744Sse	**	Initialize the status registers
274127744Sse	*/
274227744Sse	SCR_COPY (4),
274327744Sse		NADDR (header.status),
274427744Sse		RADDR (scr0),
274527744Sse}/*-------------------------< GETCC2 >----------------------*/,{
274627744Sse	/*
274727744Sse	**	Get the condition code from a target.
274827744Sse	**
274927744Sse	**	DSA points to a data structure.
275027744Sse	**	Set TEMP to the script location
275127744Sse	**	that receives the condition code.
275227744Sse	**
275327744Sse	**	Because there is no script command
275427744Sse	**	to load a longword into a register,
275527744Sse	**	we use a CALL command.
275627744Sse	*/
275727744Sse/*<<<*/	SCR_CALLR,
275827744Sse		24,
275927744Sse	/*
276027744Sse	**	Get the condition code.
276127744Sse	*/
276227744Sse	SCR_MOVE_TBL ^ SCR_DATA_IN,
276327744Sse		offsetof (struct dsb, sense),
276427744Sse	/*
276527744Sse	**	No data phase may follow!
276627744Sse	*/
276727744Sse	SCR_CALL,
276827744Sse		PADDR (checkatn),
276927744Sse	SCR_JUMP,
277027744Sse		PADDR (no_data),
277127744Sse/*>>>*/
277227744Sse
277327744Sse	/*
277427744Sse	**	The CALL jumps to this point.
277527744Sse	**	Prepare for a RESTORE_POINTER message.
277627744Sse	**	Save the TEMP register into the saved pointer.
277727744Sse	*/
277827744Sse	SCR_COPY (4),
277927744Sse		RADDR (temp),
278027744Sse		NADDR (header.savep),
278127744Sse	/*
278227744Sse	**	Load scratcha, because in case of a selection timeout,
278327744Sse	**	the host will expect a new value for startpos in
278427744Sse	**	the scratcha register.
278527744Sse	*/
278627744Sse	SCR_COPY (4),
278727744Sse		PADDR (startpos),
278827744Sse		RADDR (scratcha),
278927744Sse#ifdef NCR_GETCC_WITHMSG
279027744Sse	/*
279127744Sse	**	If QUIRK_NOMSG is set, select without ATN.
279227744Sse	**	and don't send a message.
279327744Sse	*/
279427744Sse	SCR_FROM_REG (QU_REG),
279527744Sse		0,
279627744Sse	SCR_JUMP ^ IFTRUE (MASK (QUIRK_NOMSG, QUIRK_NOMSG)),
279727744Sse		PADDRH(getcc3),
279827744Sse	/*
279927744Sse	**	Then try to connect to the target.
280027744Sse	**	If we are reselected, special treatment
280127744Sse	**	of the current job is required before
280227744Sse	**	accepting the reselection.
280327744Sse	*/
280427744Sse	SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select),
280527744Sse		PADDR(badgetcc),
280627744Sse	/*
280727744Sse	**	Send the IDENTIFY message.
280827744Sse	**	In case of short transfer, remove ATN.
280927744Sse	*/
281027744Sse	SCR_MOVE_TBL ^ SCR_MSG_OUT,
281127744Sse		offsetof (struct dsb, smsg2),
281227744Sse	SCR_CLR (SCR_ATN),
281327744Sse		0,
281427744Sse	/*
281527744Sse	**	save the first byte of the message.
281627744Sse	*/
281727744Sse	SCR_COPY (1),
281827744Sse		RADDR (sfbr),
281927744Sse		NADDR (lastmsg),
282027744Sse	SCR_JUMP,
282127744Sse		PADDR (prepare2),
282227744Sse
282327744Sse#endif
282427744Sse}/*-------------------------< GETCC3 >----------------------*/,{
282527744Sse	/*
282627744Sse	**	Try to connect to the target.
282727744Sse	**	If we are reselected, special treatment
282827744Sse	**	of the current job is required before
282927744Sse	**	accepting the reselection.
283027744Sse	**
283127744Sse	**	Silly target won't accept a message.
283227744Sse	**	Select without ATN.
283327744Sse	*/
283427744Sse	SCR_SEL_TBL ^ offsetof (struct dsb, select),
283527744Sse		PADDR(badgetcc),
283627744Sse	/*
283727744Sse	**	Force error if selection timeout
283827744Sse	*/
283927744Sse	SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)),
284027744Sse		0,
284127744Sse	/*
284227744Sse	**	don't negotiate.
284327744Sse	*/
284427744Sse	SCR_JUMP,
284527744Sse		PADDR (prepare2),
28462432Sse}/*-------------------------< ABORTTAG >-------------------*/,{
28472432Sse	/*
28482432Sse	**      Abort a bad reselection.
28492432Sse	**	Set the message to ABORT vs. ABORT_TAG
28502432Sse	*/
285139247Sgibbs	SCR_LOAD_REG (scratcha, MSG_ABORT_TAG),
28522432Sse		0,
28532432Sse	SCR_JUMPR ^ IFFALSE (CARRYSET),
28542432Sse		8,
28552432Sse}/*-------------------------< ABORT >----------------------*/,{
285639247Sgibbs	SCR_LOAD_REG (scratcha, MSG_ABORT),
28572432Sse		0,
28582432Sse	SCR_COPY (1),
28592432Sse		RADDR (scratcha),
28602432Sse		NADDR (msgout),
28612432Sse	SCR_SET (SCR_ATN),
28622432Sse		0,
28632432Sse	SCR_CLR (SCR_ACK),
28642432Sse		0,
28652432Sse	/*
28662432Sse	**	and send it.
28672432Sse	**	we expect an immediate disconnect
28682432Sse	*/
28692432Sse	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
28702432Sse		0,
28712432Sse	SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
28722432Sse		NADDR (msgout),
28732432Sse	SCR_COPY (1),
28742432Sse		RADDR (sfbr),
28752432Sse		NADDR (lastmsg),
28766215Sse	SCR_CLR (SCR_ACK|SCR_ATN),
28776132Sdg		0,
28782432Sse	SCR_WAIT_DISC,
28792432Sse		0,
28802432Sse	SCR_JUMP,
28812432Sse		PADDR (start),
28823166Sse}/*-------------------------< SNOOPTEST >-------------------*/,{
28833166Sse	/*
28843166Sse	**	Read the variable.
28853166Sse	*/
28863166Sse	SCR_COPY (4),
288727744Sse		KVAR (KVAR_NCR_CACHE),
28883166Sse		RADDR (scratcha),
28893166Sse	/*
28903166Sse	**	Write the variable.
28913166Sse	*/
28923166Sse	SCR_COPY (4),
28933166Sse		RADDR (temp),
289427744Sse		KVAR (KVAR_NCR_CACHE),
28953166Sse	/*
28963166Sse	**	Read back the variable.
28973166Sse	*/
28983166Sse	SCR_COPY (4),
289927744Sse		KVAR (KVAR_NCR_CACHE),
29003166Sse		RADDR (temp),
29016526Sse}/*-------------------------< SNOOPEND >-------------------*/,{
29023166Sse	/*
29033166Sse	**	And stop.
29043166Sse	*/
29053166Sse	SCR_INT,
29063166Sse		99,
29072432Sse}/*--------------------------------------------------------*/
29082432Sse};
29097228Sse
291027744Sse
29112432Sse/*==========================================================
29122432Sse**
29132432Sse**
29142432Sse**	Fill in #define dependent parts of the script
29152432Sse**
29162432Sse**
29172432Sse**==========================================================
29182432Sse*/
29192432Sse
2920105219Sphkstatic void ncr_script_fill (struct script * scr, struct scripth * scrh)
29212432Sse{
29222432Sse	int	i;
29232432Sse	ncrcmd	*p;
29242432Sse
292527744Sse	p = scrh->tryloop;
29262432Sse	for (i=0; i<MAX_START; i++) {
29272432Sse		*p++ =SCR_COPY (4);
29282432Sse		*p++ =NADDR (squeue[i]);
29292432Sse		*p++ =RADDR (dsa);
29302432Sse		*p++ =SCR_CALL;
29312432Sse		*p++ =PADDR (trysel);
29322432Sse	};
29332432Sse	*p++ =SCR_JUMP;
293427744Sse	*p++ =PADDRH(tryloop);
29352432Sse
293639554Sgibbs	assert ((char *)p == (char *)&scrh->tryloop + sizeof (scrh->tryloop));
29372432Sse
29382432Sse	p = scr->data_in;
29392432Sse
29402432Sse	*p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN));
29412432Sse	*p++ =PADDR (no_data);
294239386Sgibbs	*p++ =SCR_COPY (sizeof (ticks));
294334961Sphk	*p++ =(ncrcmd) KVAR (KVAR_TICKS);
29442432Sse	*p++ =NADDR (header.stamp.data);
29452432Sse	*p++ =SCR_MOVE_TBL ^ SCR_DATA_IN;
29462432Sse	*p++ =offsetof (struct dsb, data[ 0]);
29472432Sse
29482432Sse	for (i=1; i<MAX_SCATTER; i++) {
29492432Sse		*p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN));
29502432Sse		*p++ =PADDR (checkatn);
29512432Sse		*p++ =SCR_MOVE_TBL ^ SCR_DATA_IN;
29522432Sse		*p++ =offsetof (struct dsb, data[i]);
29532432Sse	};
29542432Sse
29552432Sse	*p++ =SCR_CALL;
29562432Sse	*p++ =PADDR (checkatn);
29572432Sse	*p++ =SCR_JUMP;
29582432Sse	*p++ =PADDR (no_data);
29592432Sse
296039554Sgibbs	assert ((char *)p == (char *)&scr->data_in + sizeof (scr->data_in));
29617228Sse
29622432Sse	p = scr->data_out;
29632432Sse
29642432Sse	*p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_OUT));
29652432Sse	*p++ =PADDR (no_data);
296639386Sgibbs	*p++ =SCR_COPY (sizeof (ticks));
296734961Sphk	*p++ =(ncrcmd) KVAR (KVAR_TICKS);
29682432Sse	*p++ =NADDR (header.stamp.data);
29692432Sse	*p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT;
29702432Sse	*p++ =offsetof (struct dsb, data[ 0]);
29712432Sse
29722432Sse	for (i=1; i<MAX_SCATTER; i++) {
29732432Sse		*p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT));
29742432Sse		*p++ =PADDR (dispatch);
29752432Sse		*p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT;
29762432Sse		*p++ =offsetof (struct dsb, data[i]);
29772432Sse	};
29782432Sse
29792432Sse	*p++ =SCR_CALL;
29802432Sse	*p++ =PADDR (dispatch);
29812432Sse	*p++ =SCR_JUMP;
29822432Sse	*p++ =PADDR (no_data);
29832432Sse
298439554Sgibbs	assert ((char *)p == (char *)&scr->data_out + sizeof (scr->data_out));
29852432Sse}
29867228Sse
29872432Sse/*==========================================================
29882432Sse**
29892432Sse**
29902432Sse**	Copy and rebind a script.
29912432Sse**
29922432Sse**
29932432Sse**==========================================================
29942432Sse*/
29952432Sse
299628636Ssestatic void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len)
29972432Sse{
299827744Sse	ncrcmd  opcode, new, old, tmp1, tmp2;
299927744Sse	ncrcmd	*start, *end;
300039532Sken	int relocs, offset;
30012432Sse
30022432Sse	start = src;
300327744Sse	end = src + len/4;
300439532Sken	offset = 0;
30058876Srgrimes
30062432Sse	while (src < end) {
30072432Sse
300839532Sken		opcode = *src++;
300939532Sken		WRITESCRIPT_OFF(dst, offset, opcode);
301039532Sken		offset += 4;
30112432Sse
30122432Sse		/*
30132432Sse		**	If we forget to change the length
30142432Sse		**	in struct script, a field will be
30152432Sse		**	padded with 0. This is an illegal
30162432Sse		**	command.
30172432Sse		*/
30182432Sse
30192814Sse		if (opcode == 0) {
30202432Sse			printf ("%s: ERROR0 IN SCRIPT at %d.\n",
302127744Sse				ncr_name(np), (int) (src-start-1));
30222814Sse			DELAY (1000000);
30232814Sse		};
30242432Sse
30253552Sse		if (DEBUG_FLAGS & DEBUG_SCRIPT)
302627744Sse			printf ("%p:  <%x>\n",
302727744Sse				(src-1), (unsigned)opcode);
30282432Sse
30292432Sse		/*
30302432Sse		**	We don't have to decode ALL commands
30312432Sse		*/
30322432Sse		switch (opcode >> 28) {
30337228Sse
30342432Sse		case 0xc:
30352432Sse			/*
30362432Sse			**	COPY has TWO arguments.
30372432Sse			*/
30382432Sse			relocs = 2;
303927744Sse			tmp1 = src[0];
304027744Sse			if ((tmp1 & RELOC_MASK) == RELOC_KVAR)
304127744Sse				tmp1 = 0;
304227744Sse			tmp2 = src[1];
304327744Sse			if ((tmp2 & RELOC_MASK) == RELOC_KVAR)
304427744Sse				tmp2 = 0;
304527744Sse			if ((tmp1 ^ tmp2) & 3) {
30462814Sse				printf ("%s: ERROR1 IN SCRIPT at %d.\n",
304727744Sse					ncr_name(np), (int) (src-start-1));
30482814Sse				DELAY (1000000);
304927744Sse			}
305027684Sse			/*
305127744Sse			**	If PREFETCH feature not enabled, remove
305227744Sse			**	the NO FLUSH bit if present.
305327684Sse			*/
305427744Sse			if ((opcode & SCR_NO_FLUSH) && !(np->features&FE_PFEN))
305539532Sken				WRITESCRIPT_OFF(dst, offset - 4,
305639532Sken				    (opcode & ~SCR_NO_FLUSH));
30572432Sse			break;
30582432Sse
30592432Sse		case 0x0:
30602432Sse			/*
30612432Sse			**	MOVE (absolute address)
30622432Sse			*/
30632432Sse			relocs = 1;
30642432Sse			break;
30652432Sse
30662432Sse		case 0x8:
30672432Sse			/*
30682432Sse			**	JUMP / CALL
30692432Sse			**	dont't relocate if relative :-)
30702432Sse			*/
30712432Sse			if (opcode & 0x00800000)
30722432Sse				relocs = 0;
30732432Sse			else
30742432Sse				relocs = 1;
30752432Sse			break;
30762432Sse
30772432Sse		case 0x4:
30782432Sse		case 0x5:
30792432Sse		case 0x6:
30802432Sse		case 0x7:
30812432Sse			relocs = 1;
30822432Sse			break;
30832432Sse
30842432Sse		default:
30852432Sse			relocs = 0;
30862432Sse			break;
30872432Sse		};
30887228Sse
30892432Sse		if (relocs) {
30902432Sse			while (relocs--) {
309110605Sse				old = *src++;
30922432Sse
30932432Sse				switch (old & RELOC_MASK) {
30942432Sse				case RELOC_REGISTER:
309560974Sdfr					new = (old & ~RELOC_MASK) + rman_get_start(np->reg_res);
30962432Sse					break;
30972432Sse				case RELOC_LABEL:
309810677Sse					new = (old & ~RELOC_MASK) + np->p_script;
30992432Sse					break;
310027744Sse				case RELOC_LABELH:
310127744Sse					new = (old & ~RELOC_MASK) + np->p_scripth;
310227744Sse					break;
31032432Sse				case RELOC_SOFTC:
31042432Sse					new = (old & ~RELOC_MASK) + vtophys(np);
31052432Sse					break;
310627744Sse				case RELOC_KVAR:
310727744Sse					if (((old & ~RELOC_MASK) <
310827744Sse					     SCRIPT_KVAR_FIRST) ||
310927744Sse					    ((old & ~RELOC_MASK) >
311027744Sse					     SCRIPT_KVAR_LAST))
311127744Sse						panic("ncr KVAR out of range");
311227744Sse					new = vtophys(script_kvars[old &
311327744Sse					    ~RELOC_MASK]);
311427744Sse					break;
31152432Sse				case 0:
31162432Sse					/* Don't relocate a 0 address. */
31172432Sse					if (old == 0) {
31182432Sse						new = old;
31192432Sse						break;
31202432Sse					}
3121102412Scharnier					/* FALLTHROUGH */
31222432Sse				default:
312339532Sken					panic("ncr_script_copy_and_bind: weird relocation %x @ %d\n", old, (int)(src - start));
31242432Sse					break;
31252432Sse				}
31262432Sse
312739532Sken				WRITESCRIPT_OFF(dst, offset, new);
312839532Sken				offset += 4;
31292432Sse			}
313039532Sken		} else {
313139532Sken			WRITESCRIPT_OFF(dst, offset, *src++);
313239532Sken			offset += 4;
313339532Sken		}
31342432Sse
31352432Sse	};
31362432Sse}
31377228Sse
31382432Sse/*==========================================================
31392432Sse**
31402432Sse**
31412432Sse**      Auto configuration.
31422432Sse**
31432432Sse**
31442432Sse**==========================================================
31452432Sse*/
31462432Sse
314743309Sdillon#if 0
31482432Sse/*----------------------------------------------------------
31492432Sse**
31502432Sse**	Reduce the transfer length to the max value
31512432Sse**	we can transfer safely.
31522432Sse**
31532432Sse**      Reading a block greater then MAX_SIZE from the
31542432Sse**	raw (character) device exercises a memory leak
31552432Sse**	in the vm subsystem. This is common to ALL devices.
31562432Sse**	We have submitted a description of this bug to
31572432Sse**	<FreeBSD-bugs@freefall.cdrom.com>.
31582432Sse**	It should be fixed in the current release.
31592432Sse**
31602432Sse**----------------------------------------------------------
31612432Sse*/
31622432Sse
31632432Ssevoid ncr_min_phys (struct  buf *bp)
31642432Sse{
31659364Sse	if ((unsigned long)bp->b_bcount > MAX_SIZE) bp->b_bcount = MAX_SIZE;
31662432Sse}
31672432Sse
316843309Sdillon#endif
316943309Sdillon
317043309Sdillon#if 0
31712432Sse/*----------------------------------------------------------
31722432Sse**
31732432Sse**	Maximal number of outstanding requests per target.
31742432Sse**
31752432Sse**----------------------------------------------------------
31762432Sse*/
31772432Sse
317814453Sgibbsu_int32_t ncr_info (int unit)
31792432Sse{
31802432Sse	return (1);   /* may be changed later */
31812432Sse}
31827228Sse
318343309Sdillon#endif
318443309Sdillon
31852432Sse/*----------------------------------------------------------
31862432Sse**
318727684Sse**	NCR chip devices table and chip look up function.
318827684Sse**	Features bit are defined in ncrreg.h. Is it the
318927684Sse**	right place?
319027684Sse**
319127684Sse**----------------------------------------------------------
319227684Sse*/
319327684Ssetypedef struct {
319427684Sse	unsigned long	device_id;
319528636Sse	unsigned short	minrevid;
319628636Sse	char	       *name;
319727684Sse	unsigned char	maxburst;
319827684Sse	unsigned char	maxoffs;
319927684Sse	unsigned char	clock_divn;
320027684Sse	unsigned int	features;
320127684Sse} ncr_chip;
320227684Sse
320327684Ssestatic ncr_chip ncr_chip_table[] = {
320428636Sse {NCR_810_ID, 0x00,	"ncr 53c810 fast10 scsi",		4,  8, 4,
320527684Sse FE_ERL}
320627684Sse ,
320728636Sse {NCR_810_ID, 0x10,	"ncr 53c810a fast10 scsi",		4,  8, 4,
320828636Sse FE_ERL|FE_LDSTR|FE_PFEN|FE_BOF}
320927684Sse ,
321028636Sse {NCR_815_ID, 0x00,	"ncr 53c815 fast10 scsi", 		4,  8, 4,
321127684Sse FE_ERL|FE_BOF}
321227684Sse ,
321328636Sse {NCR_820_ID, 0x00,	"ncr 53c820 fast10 wide scsi", 		4,  8, 4,
321427684Sse FE_WIDE|FE_ERL}
321527684Sse ,
321628636Sse {NCR_825_ID, 0x00,	"ncr 53c825 fast10 wide scsi",		4,  8, 4,
321727684Sse FE_WIDE|FE_ERL|FE_BOF}
321827684Sse ,
321928636Sse {NCR_825_ID, 0x10,	"ncr 53c825a fast10 wide scsi",		7,  8, 4,
322028636Sse FE_WIDE|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}
322127684Sse ,
322228636Sse {NCR_860_ID, 0x00,	"ncr 53c860 fast20 scsi",		4,  8, 5,
322328636Sse FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_LDSTR|FE_PFEN}
322427684Sse ,
322528636Sse {NCR_875_ID, 0x00,	"ncr 53c875 fast20 wide scsi",		7, 16, 5,
322628636Sse FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}
322727684Sse ,
322828636Sse {NCR_875_ID, 0x02,	"ncr 53c875 fast20 wide scsi",		7, 16, 5,
322928636Sse FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}
323027684Sse ,
323128636Sse {NCR_875_ID2, 0x00,	"ncr 53c875j fast20 wide scsi",		7, 16, 5,
323228636Sse FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}
323327684Sse ,
323428636Sse {NCR_885_ID, 0x00,	"ncr 53c885 fast20 wide scsi",		7, 16, 5,
323528636Sse FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}
323627684Sse ,
323728636Sse {NCR_895_ID, 0x00,	"ncr 53c895 fast40 wide scsi",		7, 31, 7,
323828636Sse FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}
323928636Sse ,
324028636Sse {NCR_896_ID, 0x00,	"ncr 53c896 fast40 wide scsi",		7, 31, 7,
324128636Sse FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}
324256446Sgroudier ,
324356446Sgroudier {NCR_895A_ID, 0x00,	"ncr 53c895a fast40 wide scsi",		7, 31, 7,
324456446Sgroudier FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}
324556446Sgroudier ,
324656446Sgroudier {NCR_1510D_ID, 0x00,	"ncr 53c1510d fast40 wide scsi",	7, 31, 7,
324756446Sgroudier FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}
324827684Sse};
324927684Sse
325027684Ssestatic int ncr_chip_lookup(u_long device_id, u_char revision_id)
325127684Sse{
325227684Sse	int i, found;
325328636Sse
325427684Sse	found = -1;
325527684Sse	for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); i++) {
325627684Sse		if (device_id	== ncr_chip_table[i].device_id &&
325728636Sse		    ncr_chip_table[i].minrevid <= revision_id) {
325828636Sse			if (found < 0 ||
325928636Sse			    ncr_chip_table[found].minrevid
326028636Sse			      < ncr_chip_table[i].minrevid) {
326128636Sse				found = i;
326228636Sse			}
326327684Sse		}
326427684Sse	}
326527684Sse	return found;
326627684Sse}
326727684Sse
326827684Sse/*----------------------------------------------------------
326927684Sse**
32702432Sse**	Probe the hostadapter.
32712432Sse**
32722432Sse**----------------------------------------------------------
32732432Sse*/
32742432Sse
32752432Sse
32762432Sse
327760974Sdfrstatic	int ncr_probe (device_t dev)
32782432Sse{
327927684Sse	int i;
32803533Sse
328160974Sdfr	i = ncr_chip_lookup(pci_get_devid(dev), pci_get_revid(dev));
328260974Sdfr	if (i >= 0) {
328360974Sdfr		device_set_desc(dev, ncr_chip_table[i].name);
3284142398Simp		return (BUS_PROBE_DEFAULT);
328560974Sdfr	}
32863533Sse
328760974Sdfr	return (ENXIO);
32882432Sse}
32892432Sse
32903533Sse
32917228Sse
32922432Sse/*==========================================================
32932432Sse**
329427684Sse**	NCR chip clock divisor table.
329527684Sse**	Divisors are multiplied by 10,000,000 in order to make
329627684Sse**	calculations more simple.
32972432Sse**
329827684Sse**==========================================================
329927684Sse*/
330027684Sse
330127684Sse#define _5M 5000000
330227684Ssestatic u_long div_10M[] =
330327684Sse	{2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};
330427684Sse
330527684Sse/*===============================================================
330627684Sse**
330727684Sse**	NCR chips allow burst lengths of 2, 4, 8, 16, 32, 64, 128
330827684Sse**	transfers. 32,64,128 are only supported by 875 and 895 chips.
330927684Sse**	We use log base 2 (burst length) as internal code, with
331027684Sse**	value 0 meaning "burst disabled".
331127684Sse**
331227684Sse**===============================================================
331327684Sse*/
331427684Sse
331527684Sse/*
331627684Sse *	Burst length from burst code.
331727684Sse */
331827684Sse#define burst_length(bc) (!(bc))? 0 : 1 << (bc)
331927684Sse
332027684Sse/*
332127684Sse *	Burst code from io register bits.
332227684Sse */
332327684Sse#define burst_code(dmode, ctest4, ctest5) \
332427684Sse	(ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1
332527684Sse
332627684Sse/*
332727684Sse *	Set initial io register bits from burst code.
332827684Sse */
332939247Sgibbsstatic void
333039247Sgibbsncr_init_burst(ncb_p np, u_char bc)
333127684Sse{
333227684Sse	np->rv_ctest4	&= ~0x80;
333327684Sse	np->rv_dmode	&= ~(0x3 << 6);
333427684Sse	np->rv_ctest5	&= ~0x4;
333527684Sse
333627684Sse	if (!bc) {
333727684Sse		np->rv_ctest4	|= 0x80;
333827684Sse	}
333927684Sse	else {
334027684Sse		--bc;
334127684Sse		np->rv_dmode	|= ((bc & 0x3) << 6);
334227684Sse		np->rv_ctest5	|= (bc & 0x4);
334327684Sse	}
334427684Sse}
334527684Sse
334627684Sse/*==========================================================
334727684Sse**
334827684Sse**
33492432Sse**      Auto configuration:  attach and init a host adapter.
33502432Sse**
33512432Sse**
33522432Sse**==========================================================
33532432Sse*/
33542432Sse
33552432Sse
335660974Sdfrstatic int
335760974Sdfrncr_attach (device_t dev)
33582432Sse{
335960974Sdfr	ncb_p np = (struct ncb*) device_get_softc(dev);
336039247Sgibbs	u_char	 rev = 0;
336139247Sgibbs	u_long	 period;
336260974Sdfr	int	 i, rid;
336339247Sgibbs	u_int8_t usrsync;
336439247Sgibbs	u_int8_t usrwide;
336539247Sgibbs	struct cam_devq *devq;
33662432Sse
33672432Sse	/*
336827684Sse	**	allocate and initialize structures.
33692432Sse	*/
33702432Sse
337160974Sdfr	np->unit = device_get_unit(dev);
33722432Sse
33732432Sse	/*
33742432Sse	**	Try to map the controller chip to
33752432Sse	**	virtual and physical memory.
33762432Sse	*/
33772432Sse
337860974Sdfr	np->reg_rid = 0x14;
3379127135Snjl	np->reg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
3380127135Snjl					     &np->reg_rid, RF_ACTIVE);
338160974Sdfr	if (!np->reg_res) {
338260974Sdfr		device_printf(dev, "could not map memory\n");
338360974Sdfr		return ENXIO;
338460974Sdfr	}
33852432Sse
338618886Sse	/*
338718886Sse	**	Make the controller's registers available.
338818886Sse	**	Now the INB INW INL OUTB OUTW OUTL macros
338918886Sse	**	can be used safely.
339018886Sse	*/
339118886Sse
339260974Sdfr	np->bst = rman_get_bustag(np->reg_res);
339360974Sdfr	np->bsh = rman_get_bushandle(np->reg_res);
339418886Sse
339560974Sdfr
33966401Sse#ifdef NCR_IOMAPPED
33976401Sse	/*
33986401Sse	**	Try to map the controller chip into iospace.
33996401Sse	*/
34006401Sse
34016401Sse	if (!pci_map_port (config_id, 0x10, &np->port))
34026401Sse		return;
34036401Sse#endif
34046401Sse
34057228Sse
34062432Sse	/*
340720435Sse	**	Save some controller register default values
34082814Sse	*/
34092814Sse
341027684Sse	np->rv_scntl3	= INB(nc_scntl3) & 0x77;
341127684Sse	np->rv_dmode	= INB(nc_dmode)  & 0xce;
341227684Sse	np->rv_dcntl	= INB(nc_dcntl)  & 0xa9;
341327684Sse	np->rv_ctest3	= INB(nc_ctest3) & 0x01;
341427684Sse	np->rv_ctest4	= INB(nc_ctest4) & 0x88;
341527684Sse	np->rv_ctest5	= INB(nc_ctest5) & 0x24;
341627684Sse	np->rv_gpcntl	= INB(nc_gpcntl);
341727684Sse	np->rv_stest2	= INB(nc_stest2) & 0x20;
341818875Sse
341927744Sse	if (bootverbose >= 2) {
342027684Sse		printf ("\tBIOS values:  SCNTL3:%02x DMODE:%02x  DCNTL:%02x\n",
342127684Sse			np->rv_scntl3, np->rv_dmode, np->rv_dcntl);
342227684Sse		printf ("\t              CTEST3:%02x CTEST4:%02x CTEST5:%02x\n",
342327684Sse			np->rv_ctest3, np->rv_ctest4, np->rv_ctest5);
342427684Sse	}
342527684Sse
342627684Sse	np->rv_dcntl  |= NOCOM;
342727684Sse
342818875Sse	/*
342920435Sse	**	Do chip dependent initialization.
343020435Sse	*/
343120435Sse
343260974Sdfr	rev = pci_get_revid(dev);
343320435Sse
343420435Sse	/*
343527684Sse	**	Get chip features from chips table.
343627684Sse	*/
343760974Sdfr	i = ncr_chip_lookup(pci_get_devid(dev), rev);
343827684Sse
343927684Sse	if (i >= 0) {
344027684Sse		np->maxburst	= ncr_chip_table[i].maxburst;
344127684Sse		np->maxoffs	= ncr_chip_table[i].maxoffs;
344227684Sse		np->clock_divn	= ncr_chip_table[i].clock_divn;
344327684Sse		np->features	= ncr_chip_table[i].features;
344427684Sse	} else {	/* Should'nt happen if probe() is ok */
344527684Sse		np->maxburst	= 4;
344627684Sse		np->maxoffs	= 8;
344727684Sse		np->clock_divn	= 4;
344827684Sse		np->features	= FE_ERL;
344927684Sse	}
345027684Sse
345127684Sse	np->maxwide	= np->features & FE_WIDE ? 1 : 0;
345227684Sse	np->clock_khz	= np->features & FE_CLK80 ? 80000 : 40000;
345327684Sse	if	(np->features & FE_QUAD)	np->multiplier = 4;
345427684Sse	else if	(np->features & FE_DBLR)	np->multiplier = 2;
345527684Sse	else					np->multiplier = 1;
345627684Sse
345727684Sse	/*
345818875Sse	**	Get the frequency of the chip's clock.
345918875Sse	**	Find the right value for scntl3.
346018875Sse	*/
346127684Sse	if (np->features & (FE_ULTRA|FE_ULTRA2))
346227684Sse		ncr_getclock(np, np->multiplier);
346318875Sse
346420435Sse#ifdef NCR_TEKRAM_EEPROM
346527684Sse	if (bootverbose) {
346627684Sse		printf ("%s: Tekram EEPROM read %s\n",
346727684Sse			ncr_name(np),
346827684Sse			read_tekram_eeprom (np, NULL) ?
346927684Sse			"succeeded" : "failed");
347027684Sse	}
347127684Sse#endif /* NCR_TEKRAM_EEPROM */
347227684Sse
347327684Sse	/*
347427684Sse	 *	If scntl3 != 0, we assume BIOS is present.
347527684Sse	 */
347627684Sse	if (np->rv_scntl3)
347727684Sse		np->features |= FE_BIOS;
347827684Sse
347927684Sse	/*
348027684Sse	 * Divisor to be used for async (timer pre-scaler).
348127684Sse	 */
348227684Sse	i = np->clock_divn - 1;
348327684Sse	while (i >= 0) {
348427684Sse		--i;
348527684Sse		if (10ul * SCSI_NCR_MIN_ASYNC * np->clock_khz > div_10M[i]) {
348627684Sse			++i;
348727684Sse			break;
348820435Sse		}
34893166Sse	}
349027684Sse	np->rv_scntl3 = i+1;
34912814Sse
34922814Sse	/*
349327684Sse	 * Minimum synchronous period factor supported by the chip.
349427684Sse	 * Btw, 'period' is in tenths of nanoseconds.
349527684Sse	 */
349627684Sse
349727684Sse	period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz;
349827684Sse	if	(period <= 250)		np->minsync = 10;
349927684Sse	else if	(period <= 303)		np->minsync = 11;
350027684Sse	else if	(period <= 500)		np->minsync = 12;
350127684Sse	else				np->minsync = (period + 40 - 1) / 40;
350227684Sse
350327684Sse	/*
350427684Sse	 * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2).
350527684Sse	 */
350627684Sse
350727684Sse	if	(np->minsync < 25 && !(np->features & (FE_ULTRA|FE_ULTRA2)))
350827684Sse		np->minsync = 25;
350927684Sse	else if	(np->minsync < 12 && !(np->features & FE_ULTRA2))
351027684Sse		np->minsync = 12;
351127684Sse
351227684Sse	/*
351327684Sse	 * Maximum synchronous period factor supported by the chip.
351427684Sse	 */
351527684Sse
351627684Sse	period = (11 * div_10M[np->clock_divn - 1]) / (4 * np->clock_khz);
351727684Sse	np->maxsync = period > 2540 ? 254 : period / 10;
351827684Sse
351927684Sse	/*
352027684Sse	 * Now, some features available with Symbios compatible boards.
352127684Sse	 * LED support through GPIO0 and DIFF support.
352227684Sse	 */
352327684Sse
352427684Sse#ifdef	SCSI_NCR_SYMBIOS_COMPAT
352527684Sse	if (!(np->rv_gpcntl & 0x01))
352627684Sse		np->features |= FE_LED0;
352727684Sse#if 0	/* Not safe enough without NVRAM support or user settable option */
352827684Sse	if (!(INB(nc_gpreg) & 0x08))
352927684Sse		np->features |= FE_DIFF;
353027684Sse#endif
353127684Sse#endif	/* SCSI_NCR_SYMBIOS_COMPAT */
353227684Sse
353327684Sse	/*
353427684Sse	 * Prepare initial IO registers settings.
353527684Sse	 * Trust BIOS only if we believe we have one and if we want to.
353627684Sse	 */
353727684Sse#ifdef	SCSI_NCR_TRUST_BIOS
353827684Sse	if (!(np->features & FE_BIOS)) {
353927684Sse#else
354027684Sse	if (1) {
354127684Sse#endif
354227684Sse		np->rv_dmode = 0;
354327684Sse		np->rv_dcntl = NOCOM;
354427684Sse		np->rv_ctest3 = 0;
354527684Sse		np->rv_ctest4 = MPEE;
354627684Sse		np->rv_ctest5 = 0;
354727684Sse		np->rv_stest2 = 0;
354827684Sse
354927684Sse		if (np->features & FE_ERL)
355027684Sse			np->rv_dmode 	|= ERL;	  /* Enable Read Line */
355127684Sse		if (np->features & FE_BOF)
355227684Sse			np->rv_dmode 	|= BOF;	  /* Burst Opcode Fetch */
355327684Sse		if (np->features & FE_ERMP)
355427684Sse			np->rv_dmode	|= ERMP;  /* Enable Read Multiple */
355527684Sse		if (np->features & FE_CLSE)
355627684Sse			np->rv_dcntl	|= CLSE;  /* Cache Line Size Enable */
355727684Sse		if (np->features & FE_WRIE)
355827684Sse			np->rv_ctest3	|= WRIE;  /* Write and Invalidate */
355927684Sse		if (np->features & FE_PFEN)
356027684Sse			np->rv_dcntl	|= PFEN;  /* Prefetch Enable */
356127684Sse		if (np->features & FE_DFS)
356227684Sse			np->rv_ctest5	|= DFS;	  /* Dma Fifo Size */
356327684Sse		if (np->features & FE_DIFF)
356427684Sse			np->rv_stest2	|= 0x20;  /* Differential mode */
356527684Sse		ncr_init_burst(np, np->maxburst); /* Max dwords burst length */
356627684Sse	} else {
356727684Sse		np->maxburst =
356827684Sse			burst_code(np->rv_dmode, np->rv_ctest4, np->rv_ctest5);
356927684Sse	}
357027684Sse
357127684Sse	/*
357228636Sse	**	Get on-chip SRAM address, if supported
357327744Sse	*/
357460974Sdfr	if ((np->features & FE_RAM) && sizeof(struct script) <= 4096) {
357560974Sdfr		np->sram_rid = 0x18;
3576127135Snjl		np->sram_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
3577127135Snjl						      &np->sram_rid,
3578127135Snjl						      RF_ACTIVE);
357960974Sdfr	}
358027744Sse
358128636Sse	/*
358228636Sse	**	Allocate structure for script relocation.
358328636Sse	*/
358460974Sdfr	if (np->sram_res != NULL) {
358539682Sdfr		np->script = NULL;
358660974Sdfr		np->p_script = rman_get_start(np->sram_res);
358760974Sdfr		np->bst2 = rman_get_bustag(np->sram_res);
358860974Sdfr		np->bsh2 = rman_get_bushandle(np->sram_res);
358928636Sse	} else if (sizeof (struct script) > PAGE_SIZE) {
3590124460Salc		np->script  = (struct script*) contigmalloc
3591124460Salc			(round_page(sizeof (struct script)), M_DEVBUF, M_WAITOK,
3592124460Salc			 0, 0xffffffff, PAGE_SIZE, 0);
359328636Sse	} else {
359428636Sse		np->script  = (struct script *)
3595111119Simp			malloc (sizeof (struct script), M_DEVBUF, M_WAITOK);
359628636Sse	}
359728636Sse
359828636Sse	if (sizeof (struct scripth) > PAGE_SIZE) {
3599124460Salc		np->scripth = (struct scripth*) contigmalloc
3600124460Salc			(round_page(sizeof (struct scripth)), M_DEVBUF, M_WAITOK,
3601124460Salc			 0, 0xffffffff, PAGE_SIZE, 0);
360228636Sse	} else
360328636Sse		{
360428636Sse		np->scripth = (struct scripth *)
3605111119Simp			malloc (sizeof (struct scripth), M_DEVBUF, M_WAITOK);
360628636Sse	}
360728636Sse
360827744Sse#ifdef SCSI_NCR_PCI_CONFIG_FIXUP
360927744Sse	/*
361027744Sse	**	If cache line size is enabled, check PCI config space and
361127744Sse	**	try to fix it up if necessary.
361227744Sse	*/
361327744Sse#ifdef PCIR_CACHELNSZ	/* To be sure that new PCI stuff is present */
361428636Sse	{
361560974Sdfr		u_char cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1);
361660974Sdfr		u_short command  = pci_read_config(dev, PCIR_COMMAND, 2);
361727744Sse
361827744Sse		if (!cachelnsz) {
361927744Sse			cachelnsz = 8;
362027744Sse			printf("%s: setting PCI cache line size register to %d.\n",
362127744Sse				ncr_name(np), (int)cachelnsz);
362260974Sdfr			pci_write_config(dev, PCIR_CACHELNSZ, cachelnsz, 1);
362327744Sse		}
362427744Sse
3625254263Sscottl		if (!(command & PCIM_CMD_MWRICEN)) {
3626254263Sscottl			command |= PCIM_CMD_MWRICEN;
362727744Sse			printf("%s: setting PCI command write and invalidate.\n",
362827744Sse				ncr_name(np));
362960974Sdfr			pci_write_config(dev, PCIR_COMMAND, command, 2);
363027744Sse		}
363128636Sse	}
363227744Sse#endif /* PCIR_CACHELNSZ */
363327744Sse
363427744Sse#endif /* SCSI_NCR_PCI_CONFIG_FIXUP */
363527744Sse
363639247Sgibbs	/* Initialize per-target user settings */
363739247Sgibbs	usrsync = 0;
363839247Sgibbs	if (SCSI_NCR_DFLT_SYNC) {
363939247Sgibbs		usrsync = SCSI_NCR_DFLT_SYNC;
364039247Sgibbs		if (usrsync > np->maxsync)
364139247Sgibbs			usrsync = np->maxsync;
364239247Sgibbs		if (usrsync < np->minsync)
364339247Sgibbs			usrsync = np->minsync;
364439247Sgibbs	};
364539247Sgibbs
364639247Sgibbs	usrwide = (SCSI_NCR_MAX_WIDE);
364739247Sgibbs	if (usrwide > np->maxwide) usrwide=np->maxwide;
364839247Sgibbs
364939247Sgibbs	for (i=0;i<MAX_TARGET;i++) {
365039247Sgibbs		tcb_p tp = &np->target[i];
365139247Sgibbs
365239247Sgibbs		tp->tinfo.user.period = usrsync;
365339247Sgibbs		tp->tinfo.user.offset = usrsync != 0 ? np->maxoffs : 0;
365439247Sgibbs		tp->tinfo.user.width = usrwide;
365539247Sgibbs		tp->tinfo.disc_tag = NCR_CUR_DISCENB
365639247Sgibbs				   | NCR_CUR_TAGENB
365739247Sgibbs				   | NCR_USR_DISCENB
365839247Sgibbs				   | NCR_USR_TAGENB;
365939247Sgibbs	}
366039247Sgibbs
366127744Sse	/*
366227684Sse	**	Bells and whistles   ;-)
366327684Sse	*/
366428636Sse	if (bootverbose)
366528636Sse		printf("%s: minsync=%d, maxsync=%d, maxoffs=%d, %d dwords burst, %s dma fifo\n",
366627684Sse		ncr_name(np), np->minsync, np->maxsync, np->maxoffs,
366727684Sse		burst_length(np->maxburst),
366827684Sse		(np->rv_ctest5 & DFS) ? "large" : "normal");
366927684Sse
367027684Sse	/*
367127744Sse	**	Print some complementary information that can be helpfull.
36722432Sse	*/
367327744Sse	if (bootverbose)
367427744Sse		printf("%s: %s, %s IRQ driver%s\n",
367527744Sse			ncr_name(np),
367627744Sse			np->rv_stest2 & 0x20 ? "differential" : "single-ended",
367727744Sse			np->rv_dcntl & IRQM ? "totem pole" : "open drain",
367860974Sdfr			np->sram_res ? ", using on-chip SRAM" : "");
367927744Sse
368027744Sse	/*
368127744Sse	**	Patch scripts to physical addresses
368227744Sse	*/
368327744Sse	ncr_script_fill (&script0, &scripth0);
36842432Sse
368539532Sken	if (np->script)
368639532Sken		np->p_script	= vtophys(np->script);
368727744Sse	np->p_scripth	= vtophys(np->scripth);
368827744Sse
368927744Sse	ncr_script_copy_and_bind (np, (ncrcmd *) &script0,
369028636Sse			(ncrcmd *) np->script, sizeof(struct script));
369127744Sse
369227744Sse	ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0,
369328636Sse		(ncrcmd *) np->scripth, sizeof(struct scripth));
369427744Sse
36952432Sse	/*
369627684Sse	**    Patch the script for LED support.
369727684Sse	*/
369827684Sse
369927684Sse	if (np->features & FE_LED0) {
370039532Sken		WRITESCRIPT(reselect[0],  SCR_REG_REG(gpreg, SCR_OR,  0x01));
370139532Sken		WRITESCRIPT(reselect1[0], SCR_REG_REG(gpreg, SCR_AND, 0xfe));
370239532Sken		WRITESCRIPT(reselect2[0], SCR_REG_REG(gpreg, SCR_AND, 0xfe));
370327684Sse	}
370427684Sse
370527684Sse	/*
37062432Sse	**	init data structure
37072432Sse	*/
37082432Sse
370910677Sse	np->jump_tcb.l_cmd	= SCR_JUMP;
371027744Sse	np->jump_tcb.l_paddr	= NCB_SCRIPTH_PHYS (np, abort);
37112432Sse
37122432Sse	/*
37132432Sse	**  Get SCSI addr of host adapter (set by bios?).
37142432Sse	*/
37152432Sse
37162432Sse	np->myaddr = INB(nc_scid) & 0x07;
37172432Sse	if (!np->myaddr) np->myaddr = SCSI_NCR_MYADDR;
37182432Sse
37196132Sdg#ifdef NCR_DUMP_REG
37202432Sse	/*
37216132Sdg	**	Log the initial register contents
37226132Sdg	*/
37236132Sdg	{
37246132Sdg		int reg;
37256132Sdg		for (reg=0; reg<256; reg+=4) {
37266132Sdg			if (reg%16==0) printf ("reg[%2x]", reg);
37276132Sdg			printf (" %08x", (int)pci_conf_read (config_id, reg));
37286132Sdg			if (reg%16==12) printf ("\n");
37296132Sdg		}
37306132Sdg	}
373120435Sse#endif /* NCR_DUMP_REG */
37326132Sdg
37336132Sdg	/*
373420435Sse	**	Reset chip.
37356132Sdg	*/
37366132Sdg
37376132Sdg	OUTB (nc_istat,  SRST);
373810605Sse	DELAY (1000);
37396132Sdg	OUTB (nc_istat,  0   );
37406132Sdg
37416132Sdg
37426132Sdg	/*
37433166Sse	**	Now check the cache handling of the pci chipset.
37443166Sse	*/
37453166Sse
37463166Sse	if (ncr_snooptest (np)) {
37473166Sse		printf ("CACHE INCORRECTLY CONFIGURED.\n");
374860974Sdfr		return EINVAL;
37493166Sse	};
37503166Sse
37513166Sse	/*
37526705Sse	**	Install the interrupt handler.
37533533Sse	*/
37543533Sse
375560974Sdfr	rid = 0;
3756127135Snjl	np->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
3757127135Snjl					     RF_SHAREABLE | RF_ACTIVE);
375860974Sdfr	if (np->irq_res == NULL) {
375960974Sdfr		device_printf(dev,
376060974Sdfr			      "interruptless mode: reduced performance.\n");
376160974Sdfr	} else {
376273280Smarkm		bus_setup_intr(dev, np->irq_res, INTR_TYPE_CAM | INTR_ENTROPY,
3763166920Simp			       NULL, ncr_intr, np, &np->irq_handle);
376460974Sdfr	}
37653533Sse
37663533Sse	/*
376739386Sgibbs	** Create the device queue.  We only allow MAX_START-1 concurrent
376839386Sgibbs	** transactions so we can be sure to have one element free in our
376939386Sgibbs	** start queue to reset to the idle loop.
37702432Sse	*/
377139386Sgibbs	devq = cam_simq_alloc(MAX_START - 1);
377239247Sgibbs	if (devq == NULL)
377360974Sdfr		return ENOMEM;
37742432Sse
37752432Sse	/*
377639247Sgibbs	**	Now tell the generic SCSI layer
377739247Sgibbs	**	about our bus.
37782432Sse	*/
377939247Sgibbs	np->sim = cam_sim_alloc(ncr_action, ncr_poll, "ncr", np, np->unit,
3780168752Sscottl				&Giant, 1, MAX_TAGS, devq);
378139247Sgibbs	if (np->sim == NULL) {
378239247Sgibbs		cam_simq_free(devq);
378360974Sdfr		return ENOMEM;
378439247Sgibbs	}
37852432Sse
378639247Sgibbs
3787170872Sscottl	if (xpt_bus_register(np->sim, dev, 0) != CAM_SUCCESS) {
378847374Sken		cam_sim_free(np->sim, /*free_devq*/ TRUE);
378960974Sdfr		return ENOMEM;
379010605Sse	}
379139247Sgibbs
379239247Sgibbs	if (xpt_create_path(&np->path, /*periph*/NULL,
379339247Sgibbs			    cam_sim_path(np->sim), CAM_TARGET_WILDCARD,
379439247Sgibbs			    CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
379539247Sgibbs		xpt_bus_deregister(cam_sim_path(np->sim));
379647374Sken		cam_sim_free(np->sim, /*free_devq*/TRUE);
379760974Sdfr		return ENOMEM;
379839247Sgibbs	}
37992432Sse
38002432Sse	/*
38012432Sse	**	start the timeout daemon
38022432Sse	*/
38032432Sse	ncr_timeout (np);
38042432Sse	np->lasttime=0;
38052432Sse
380660974Sdfr	return 0;
38072432Sse}
38087228Sse
38092432Sse/*==========================================================
38102432Sse**
38112432Sse**
38126705Sse**	Process pending device interrupts.
38132432Sse**
38142432Sse**
38152432Sse**==========================================================
38162432Sse*/
38172432Sse
381813597Ssestatic void
381912879Sbdencr_intr(vnp)
382012879Sbde	void *vnp;
38212432Sse{
382212879Sbde	ncb_p np = vnp;
382339247Sgibbs	int oldspl = splcam();
38242432Sse
38253552Sse	if (DEBUG_FLAGS & DEBUG_TINY) printf ("[");
38262432Sse
38273533Sse	if (INB(nc_istat) & (INTF|SIP|DIP)) {
38283533Sse		/*
38293533Sse		**	Repeat until no outstanding ints
38303533Sse		*/
38313533Sse		do {
38323533Sse			ncr_exception (np);
38333533Sse		} while (INB(nc_istat) & (INTF|SIP|DIP));
38343533Sse
38353533Sse		np->ticks = 100;
38362432Sse	};
38372432Sse
38383552Sse	if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n");
38392432Sse
38406460Sse	splx (oldspl);
38412432Sse}
38427228Sse
38432432Sse/*==========================================================
38442432Sse**
38452432Sse**
38462432Sse**	Start execution of a SCSI command.
38472432Sse**	This is called from the generic SCSI driver.
38482432Sse**
38492432Sse**
38502432Sse**==========================================================
38512432Sse*/
38522432Sse
385339247Sgibbsstatic void
385439247Sgibbsncr_action (struct cam_sim *sim, union ccb *ccb)
38552432Sse{
385639247Sgibbs	ncb_p np;
38572432Sse
385839247Sgibbs	np = (ncb_p) cam_sim_softc(sim);
38592432Sse
386039247Sgibbs	switch (ccb->ccb_h.func_code) {
386139247Sgibbs	/* Common cases first */
386239247Sgibbs	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
386339247Sgibbs	{
386439247Sgibbs		nccb_p cp;
386539247Sgibbs		lcb_p lp;
386639247Sgibbs		tcb_p tp;
386739247Sgibbs		int oldspl;
386839247Sgibbs		struct ccb_scsiio *csio;
386939247Sgibbs		u_int8_t *msgptr;
387039247Sgibbs		u_int msglen;
387139247Sgibbs		u_int msglen2;
387239247Sgibbs		int segments;
387339247Sgibbs		u_int8_t nego;
387439247Sgibbs		u_int8_t idmsg;
3875118073Srobert		int qidx;
387639247Sgibbs
387739247Sgibbs		tp = &np->target[ccb->ccb_h.target_id];
387839247Sgibbs		csio = &ccb->csio;
38792432Sse
388039247Sgibbs		oldspl = splcam();
38812432Sse
388239247Sgibbs		/*
388339247Sgibbs		 * Last time we need to check if this CCB needs to
388439247Sgibbs		 * be aborted.
388539247Sgibbs		 */
388639247Sgibbs		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
388739247Sgibbs			xpt_done(ccb);
388839247Sgibbs			splx(oldspl);
388939247Sgibbs			return;
389039247Sgibbs		}
389139247Sgibbs		ccb->ccb_h.status |= CAM_SIM_QUEUED;
38927228Sse
389339247Sgibbs		/*---------------------------------------------------
389439247Sgibbs		**
389539247Sgibbs		**	Assign an nccb / bind ccb
389639247Sgibbs		**
389739247Sgibbs		**----------------------------------------------------
389839247Sgibbs		*/
389939247Sgibbs		cp = ncr_get_nccb (np, ccb->ccb_h.target_id,
390039247Sgibbs				   ccb->ccb_h.target_lun);
390139247Sgibbs		if (cp == NULL) {
390239247Sgibbs			/* XXX JGibbs - Freeze SIMQ */
390339247Sgibbs			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
390439247Sgibbs			xpt_done(ccb);
390539247Sgibbs			return;
390639247Sgibbs		};
390739247Sgibbs
390839247Sgibbs		cp->ccb = ccb;
390939247Sgibbs
391039247Sgibbs		/*---------------------------------------------------
391139247Sgibbs		**
391239247Sgibbs		**	timestamp
391339247Sgibbs		**
391439247Sgibbs		**----------------------------------------------------
391539247Sgibbs		*/
391639247Sgibbs		/*
391739247Sgibbs		** XXX JGibbs - Isn't this expensive
391839247Sgibbs		**		enough to be conditionalized??
391939247Sgibbs		*/
39202432Sse
392139247Sgibbs		bzero (&cp->phys.header.stamp, sizeof (struct tstamp));
392239247Sgibbs		cp->phys.header.stamp.start = ticks;
39232432Sse
392439247Sgibbs		nego = 0;
392539247Sgibbs		if (tp->nego_cp == NULL) {
392639247Sgibbs
392739247Sgibbs			if (tp->tinfo.current.width
392839247Sgibbs			 != tp->tinfo.goal.width) {
392939247Sgibbs				tp->nego_cp = cp;
393039247Sgibbs				nego = NS_WIDE;
393146581Sken			} else if ((tp->tinfo.current.period
393246581Sken				    != tp->tinfo.goal.period)
393346581Sken				|| (tp->tinfo.current.offset
393446581Sken				    != tp->tinfo.goal.offset)) {
393539247Sgibbs				tp->nego_cp = cp;
393639247Sgibbs				nego = NS_SYNC;
393739247Sgibbs			};
393839247Sgibbs		};
39392814Sse
394039247Sgibbs		/*---------------------------------------------------
394139247Sgibbs		**
394239247Sgibbs		**	choose a new tag ...
394339247Sgibbs		**
394439247Sgibbs		**----------------------------------------------------
394539247Sgibbs		*/
394639247Sgibbs		lp = tp->lp[ccb->ccb_h.target_lun];
394739247Sgibbs
394839247Sgibbs		if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0
394940418Sgibbs		 && (ccb->csio.tag_action != CAM_TAG_ACTION_NONE)
395039247Sgibbs		 && (nego == 0)) {
395139247Sgibbs			/*
395239247Sgibbs			**	assign a tag to this nccb
395339247Sgibbs			*/
395439247Sgibbs			while (!cp->tag) {
395539247Sgibbs				nccb_p cp2 = lp->next_nccb;
395639247Sgibbs				lp->lasttag = lp->lasttag % 255 + 1;
395739247Sgibbs				while (cp2 && cp2->tag != lp->lasttag)
395839247Sgibbs					cp2 = cp2->next_nccb;
395939247Sgibbs				if (cp2) continue;
396039247Sgibbs				cp->tag=lp->lasttag;
396139247Sgibbs				if (DEBUG_FLAGS & DEBUG_TAGS) {
396239247Sgibbs					PRINT_ADDR(ccb);
396339247Sgibbs					printf ("using tag #%d.\n", cp->tag);
396439247Sgibbs				};
396539247Sgibbs			};
396639247Sgibbs		} else {
396739247Sgibbs			cp->tag=0;
39682814Sse		};
39692814Sse
397039247Sgibbs		/*----------------------------------------------------
397139247Sgibbs		**
397239247Sgibbs		**	Build the identify / tag / sdtr message
397339247Sgibbs		**
397439247Sgibbs		**----------------------------------------------------
397539247Sgibbs		*/
397639247Sgibbs		idmsg = MSG_IDENTIFYFLAG | ccb->ccb_h.target_lun;
397739247Sgibbs		if (tp->tinfo.disc_tag & NCR_CUR_DISCENB)
397839247Sgibbs			idmsg |= MSG_IDENTIFY_DISCFLAG;
397918875Sse
398039247Sgibbs		msgptr = cp->scsi_smsg;
398139247Sgibbs		msglen = 0;
398239247Sgibbs		msgptr[msglen++] = idmsg;
39832814Sse
398439247Sgibbs		if (cp->tag) {
398539247Sgibbs	    		msgptr[msglen++] = ccb->csio.tag_action;
398639247Sgibbs			msgptr[msglen++] = cp->tag;
398739247Sgibbs		}
39882432Sse
398939247Sgibbs		switch (nego) {
399039247Sgibbs		case NS_SYNC:
399139247Sgibbs			msgptr[msglen++] = MSG_EXTENDED;
399239247Sgibbs			msgptr[msglen++] = MSG_EXT_SDTR_LEN;
399339247Sgibbs			msgptr[msglen++] = MSG_EXT_SDTR;
399439247Sgibbs			msgptr[msglen++] = tp->tinfo.goal.period;
3995201758Smbr			msgptr[msglen++] = tp->tinfo.goal.offset;
399639247Sgibbs			if (DEBUG_FLAGS & DEBUG_NEGO) {
399739247Sgibbs				PRINT_ADDR(ccb);
399839247Sgibbs				printf ("sync msgout: ");
399939247Sgibbs				ncr_show_msg (&cp->scsi_smsg [msglen-5]);
400039247Sgibbs				printf (".\n");
400139247Sgibbs			};
400239247Sgibbs			break;
400339247Sgibbs		case NS_WIDE:
400439247Sgibbs			msgptr[msglen++] = MSG_EXTENDED;
400539247Sgibbs			msgptr[msglen++] = MSG_EXT_WDTR_LEN;
400639247Sgibbs			msgptr[msglen++] = MSG_EXT_WDTR;
400739247Sgibbs			msgptr[msglen++] = tp->tinfo.goal.width;
400839247Sgibbs			if (DEBUG_FLAGS & DEBUG_NEGO) {
400939247Sgibbs				PRINT_ADDR(ccb);
401039247Sgibbs				printf ("wide msgout: ");
401139247Sgibbs				ncr_show_msg (&cp->scsi_smsg [msglen-4]);
401239247Sgibbs				printf (".\n");
401339247Sgibbs			};
401439247Sgibbs			break;
401539247Sgibbs		};
40162432Sse
401739247Sgibbs		/*----------------------------------------------------
401839247Sgibbs		**
401939247Sgibbs		**	Build the identify message for getcc.
402039247Sgibbs		**
402139247Sgibbs		**----------------------------------------------------
402239247Sgibbs		*/
40232432Sse
402439247Sgibbs		cp->scsi_smsg2 [0] = idmsg;
402539247Sgibbs		msglen2 = 1;
40262432Sse
402739247Sgibbs		/*----------------------------------------------------
402839247Sgibbs		**
402939247Sgibbs		**	Build the data descriptors
403039247Sgibbs		**
403139247Sgibbs		**----------------------------------------------------
403239247Sgibbs		*/
40332432Sse
403439247Sgibbs		/* XXX JGibbs - Handle other types of I/O */
403539247Sgibbs		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
403639247Sgibbs			segments = ncr_scatter(&cp->phys,
403739247Sgibbs					       (vm_offset_t)csio->data_ptr,
403839247Sgibbs					       (vm_size_t)csio->dxfer_len);
40396302Sse
404039247Sgibbs			if (segments < 0) {
404139247Sgibbs				ccb->ccb_h.status = CAM_REQ_TOO_BIG;
404239247Sgibbs				ncr_free_nccb(np, cp);
404339247Sgibbs				splx(oldspl);
404439247Sgibbs				xpt_done(ccb);
404539247Sgibbs				return;
404639247Sgibbs			}
404739247Sgibbs			if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
404839247Sgibbs				cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_in);
404939247Sgibbs				cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16;
405039247Sgibbs			} else { /* CAM_DIR_OUT */
405139247Sgibbs				cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_out);
405239247Sgibbs				cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16;
405339247Sgibbs			}
405439247Sgibbs		} else {
405539247Sgibbs			cp->phys.header.savep = NCB_SCRIPT_PHYS (np, no_data);
405639247Sgibbs			cp->phys.header.goalp = cp->phys.header.savep;
405739247Sgibbs		}
40582432Sse
405939247Sgibbs		cp->phys.header.lastp = cp->phys.header.savep;
40602432Sse
40617228Sse
406239247Sgibbs		/*----------------------------------------------------
406339247Sgibbs		**
406439247Sgibbs		**	fill in nccb
406539247Sgibbs		**
406639247Sgibbs		**----------------------------------------------------
406739247Sgibbs		**
406839247Sgibbs		**
406939247Sgibbs		**	physical -> virtual backlink
407039247Sgibbs		**	Generic SCSI command
407139247Sgibbs		*/
407239247Sgibbs		cp->phys.header.cp		= cp;
407326568Sse		/*
407439247Sgibbs		**	Startqueue
407526568Sse		*/
407639247Sgibbs		cp->phys.header.launch.l_paddr	= NCB_SCRIPT_PHYS (np, select);
407739247Sgibbs		cp->phys.header.launch.l_cmd	= SCR_JUMP;
40782432Sse		/*
407939247Sgibbs		**	select
408014556Sse		*/
408139247Sgibbs		cp->phys.select.sel_id		= ccb->ccb_h.target_id;
408239247Sgibbs		cp->phys.select.sel_scntl3	= tp->tinfo.wval;
408339247Sgibbs		cp->phys.select.sel_sxfer	= tp->tinfo.sval;
408439247Sgibbs		/*
408539247Sgibbs		**	message
408639247Sgibbs		*/
408739247Sgibbs		cp->phys.smsg.addr		= CCB_PHYS (cp, scsi_smsg);
408839247Sgibbs		cp->phys.smsg.size		= msglen;
408939247Sgibbs
409039247Sgibbs		cp->phys.smsg2.addr		= CCB_PHYS (cp, scsi_smsg2);
409139247Sgibbs		cp->phys.smsg2.size		= msglen2;
409239247Sgibbs		/*
409339247Sgibbs		**	command
409439247Sgibbs		*/
409539247Sgibbs		/* XXX JGibbs - Support other command types */
409639247Sgibbs		cp->phys.cmd.addr		= vtophys (csio->cdb_io.cdb_bytes);
409739247Sgibbs		cp->phys.cmd.size		= csio->cdb_len;
409839247Sgibbs		/*
409939247Sgibbs		**	sense command
410039247Sgibbs		*/
410139247Sgibbs		cp->phys.scmd.addr		= CCB_PHYS (cp, sensecmd);
410239247Sgibbs		cp->phys.scmd.size		= 6;
410339247Sgibbs		/*
410439247Sgibbs		**	patch requested size into sense command
410539247Sgibbs		*/
410639247Sgibbs		cp->sensecmd[0]			= 0x03;
410739247Sgibbs		cp->sensecmd[1]			= ccb->ccb_h.target_lun << 5;
410839247Sgibbs		cp->sensecmd[4]			= sizeof(struct scsi_sense_data);
410939247Sgibbs		cp->sensecmd[4]			= csio->sense_len;
411039247Sgibbs		/*
411139247Sgibbs		**	sense data
411239247Sgibbs		*/
411339247Sgibbs		cp->phys.sense.addr		= vtophys (&csio->sense_data);
411439247Sgibbs		cp->phys.sense.size		= csio->sense_len;
411539247Sgibbs		/*
411639247Sgibbs		**	status
411739247Sgibbs		*/
411839467Sgibbs		cp->actualquirks		= QUIRK_NOMSG;
411939247Sgibbs		cp->host_status			= nego ? HS_NEGOTIATE : HS_BUSY;
412039247Sgibbs		cp->s_status			= SCSI_STATUS_ILLEGAL;
412139247Sgibbs		cp->parity_status		= 0;
412239247Sgibbs
412339247Sgibbs		cp->xerr_status			= XE_OK;
412439247Sgibbs		cp->sync_status			= tp->tinfo.sval;
412539247Sgibbs		cp->nego_status			= nego;
412639247Sgibbs		cp->wide_status			= tp->tinfo.wval;
412714556Sse
412839247Sgibbs		/*----------------------------------------------------
412939247Sgibbs		**
413039247Sgibbs		**	Critical region: start this job.
413139247Sgibbs		**
413239247Sgibbs		**----------------------------------------------------
413339247Sgibbs		*/
413414556Sse
413514556Sse		/*
413639247Sgibbs		**	reselect pattern and activate this job.
41372432Sse		*/
41388876Srgrimes
413939247Sgibbs		cp->jump_nccb.l_cmd	= (SCR_JUMP ^ IFFALSE (DATA (cp->tag)));
414039247Sgibbs		cp->tlimit		= time_second
414139247Sgibbs					+ ccb->ccb_h.timeout / 1000 + 2;
414239247Sgibbs		cp->magic		= CCB_MAGIC;
414327684Sse
414427684Sse		/*
414539247Sgibbs		**	insert into start queue.
414627684Sse		*/
414727684Sse
414839247Sgibbs		qidx = np->squeueput + 1;
4149118073Srobert		if (qidx >= MAX_START)
4150118073Srobert			qidx = 0;
415139247Sgibbs		np->squeue [qidx	 ] = NCB_SCRIPT_PHYS (np, idle);
415239247Sgibbs		np->squeue [np->squeueput] = CCB_PHYS (cp, phys);
415339247Sgibbs		np->squeueput = qidx;
41547228Sse
415539247Sgibbs		if(DEBUG_FLAGS & DEBUG_QUEUE)
415639247Sgibbs			printf("%s: queuepos=%d tryoffset=%d.\n",
415739247Sgibbs			       ncr_name (np), np->squeueput,
415839532Sken			       (unsigned)(READSCRIPT(startpos[0]) -
415939247Sgibbs			       (NCB_SCRIPTH_PHYS (np, tryloop))));
41602432Sse
41612432Sse		/*
416239247Sgibbs		**	Script processor may be waiting for reselect.
416339247Sgibbs		**	Wake it up.
41642432Sse		*/
416539247Sgibbs		OUTB (nc_istat, SIGP);
41667228Sse
41672432Sse		/*
416839247Sgibbs		**	and reenable interrupts
41692432Sse		*/
417039247Sgibbs		splx (oldspl);
417139247Sgibbs		break;
41722432Sse	}
417339247Sgibbs	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
417439247Sgibbs	case XPT_EN_LUN:		/* Enable LUN as a target */
417539247Sgibbs	case XPT_TARGET_IO:		/* Execute target I/O request */
417639247Sgibbs	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
417739247Sgibbs	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
417839247Sgibbs	case XPT_ABORT:			/* Abort the specified CCB */
417939247Sgibbs		/* XXX Implement */
418039247Sgibbs		ccb->ccb_h.status = CAM_REQ_INVALID;
418139247Sgibbs		xpt_done(ccb);
41822814Sse		break;
418339247Sgibbs	case XPT_SET_TRAN_SETTINGS:
418439247Sgibbs	{
4185163816Smjacob		struct	ccb_trans_settings *cts = &ccb->cts;
418639247Sgibbs		tcb_p	tp;
418739247Sgibbs		u_int	update_type;
418839247Sgibbs		int	s;
4189163816Smjacob		struct ccb_trans_settings_scsi *scsi =
4190163816Smjacob		    &cts->proto_specific.scsi;
4191163816Smjacob		struct ccb_trans_settings_spi *spi =
4192163816Smjacob		    &cts->xport_specific.spi;
41937228Sse
419439247Sgibbs		update_type = 0;
4195163816Smjacob		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
4196163816Smjacob			update_type |= NCR_TRANS_GOAL;
4197163816Smjacob		if (cts->type == CTS_TYPE_USER_SETTINGS)
4198163816Smjacob			update_type |= NCR_TRANS_USER;
4199163816Smjacob
4200163816Smjacob		s = splcam();
4201163816Smjacob		tp = &np->target[ccb->ccb_h.target_id];
4202163816Smjacob		/* Tag and disc enables */
4203163816Smjacob		if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
4204163816Smjacob			if (update_type & NCR_TRANS_GOAL) {
4205163816Smjacob				if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
4206163816Smjacob					tp->tinfo.disc_tag |= NCR_CUR_DISCENB;
4207163816Smjacob				else
4208163816Smjacob					tp->tinfo.disc_tag &= ~NCR_CUR_DISCENB;
4209163816Smjacob			}
4210163816Smjacob
4211163816Smjacob			if (update_type & NCR_TRANS_USER) {
4212163816Smjacob				if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
4213163816Smjacob					tp->tinfo.disc_tag |= NCR_USR_DISCENB;
4214163816Smjacob				else
4215163816Smjacob					tp->tinfo.disc_tag &= ~NCR_USR_DISCENB;
4216163816Smjacob			}
4217163816Smjacob
4218163816Smjacob		}
4219163816Smjacob
4220163816Smjacob		if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
4221163816Smjacob			if (update_type & NCR_TRANS_GOAL) {
4222163816Smjacob				if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
4223163816Smjacob					tp->tinfo.disc_tag |= NCR_CUR_TAGENB;
4224163816Smjacob				else
4225163816Smjacob					tp->tinfo.disc_tag &= ~NCR_CUR_TAGENB;
4226163816Smjacob			}
4227163816Smjacob
4228163816Smjacob			if (update_type & NCR_TRANS_USER) {
4229163816Smjacob				if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
4230163816Smjacob					tp->tinfo.disc_tag |= NCR_USR_TAGENB;
4231163816Smjacob				else
4232163816Smjacob					tp->tinfo.disc_tag &= ~NCR_USR_TAGENB;
4233163816Smjacob			}
4234163816Smjacob		}
4235163816Smjacob
4236163816Smjacob		/* Filter bus width and sync negotiation settings */
4237163816Smjacob		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
4238163816Smjacob			if (spi->bus_width > np->maxwide)
4239163816Smjacob				spi->bus_width = np->maxwide;
4240163816Smjacob		}
4241163816Smjacob
4242163816Smjacob		if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0)
4243163816Smjacob		 || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) {
4244163816Smjacob			if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4245163816Smjacob				if (spi->sync_period != 0
4246163816Smjacob				 && (spi->sync_period < np->minsync))
4247163816Smjacob					spi->sync_period = np->minsync;
4248163816Smjacob			}
4249163816Smjacob			if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) {
4250163816Smjacob				if (spi->sync_offset == 0)
4251163816Smjacob					spi->sync_period = 0;
4252163816Smjacob				if (spi->sync_offset > np->maxoffs)
4253163816Smjacob					spi->sync_offset = np->maxoffs;
4254163816Smjacob			}
4255163816Smjacob		}
4256163816Smjacob		if ((update_type & NCR_TRANS_USER) != 0) {
4257163816Smjacob			if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0)
4258163816Smjacob				tp->tinfo.user.period = spi->sync_period;
4259163816Smjacob			if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
4260163816Smjacob				tp->tinfo.user.offset = spi->sync_offset;
4261163816Smjacob			if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
4262163816Smjacob				tp->tinfo.user.width = spi->bus_width;
4263163816Smjacob		}
4264163816Smjacob		if ((update_type & NCR_TRANS_GOAL) != 0) {
4265163816Smjacob			if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0)
4266163816Smjacob				tp->tinfo.goal.period = spi->sync_period;
4267163816Smjacob
4268163816Smjacob			if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
4269163816Smjacob				tp->tinfo.goal.offset = spi->sync_offset;
4270163816Smjacob
4271163816Smjacob			if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
4272163816Smjacob				tp->tinfo.goal.width = spi->bus_width;
4273163816Smjacob		}
4274163816Smjacob		splx(s);
427539247Sgibbs		ccb->ccb_h.status = CAM_REQ_CMP;
427639247Sgibbs		xpt_done(ccb);
427739247Sgibbs		break;
427839247Sgibbs	}
427939247Sgibbs	case XPT_GET_TRAN_SETTINGS:
428039247Sgibbs	/* Get default/user set transfer settings for the target */
428139247Sgibbs	{
4282163816Smjacob		struct	ccb_trans_settings *cts = &ccb->cts;
428339247Sgibbs		struct	ncr_transinfo *tinfo;
4284163816Smjacob		tcb_p	tp = &np->target[ccb->ccb_h.target_id];
428539247Sgibbs		int	s;
4286163816Smjacob		struct ccb_trans_settings_scsi *scsi =
4287163816Smjacob		    &cts->proto_specific.scsi;
4288163816Smjacob		struct ccb_trans_settings_spi *spi =
4289163816Smjacob		    &cts->xport_specific.spi;
42902814Sse
4291163816Smjacob		cts->protocol = PROTO_SCSI;
4292163816Smjacob		cts->protocol_version = SCSI_REV_2;
4293163816Smjacob		cts->transport = XPORT_SPI;
4294163816Smjacob		cts->transport_version = 2;
4295163816Smjacob
429639247Sgibbs		s = splcam();
4297163816Smjacob		if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
4298163816Smjacob			tinfo = &tp->tinfo.current;
4299163816Smjacob			if (tp->tinfo.disc_tag & NCR_CUR_DISCENB)
4300163816Smjacob				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
4301163816Smjacob			else
4302163816Smjacob				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
4303163816Smjacob
4304163816Smjacob			if (tp->tinfo.disc_tag & NCR_CUR_TAGENB)
4305163816Smjacob				scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
4306163816Smjacob			else
4307163816Smjacob				scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
4308163816Smjacob		} else {
4309163816Smjacob			tinfo = &tp->tinfo.user;
4310163816Smjacob			if (tp->tinfo.disc_tag & NCR_USR_DISCENB)
4311163816Smjacob				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
4312163816Smjacob			else
4313163816Smjacob				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
4314163816Smjacob
4315163816Smjacob			if (tp->tinfo.disc_tag & NCR_USR_TAGENB)
4316163816Smjacob				scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
4317163816Smjacob			else
4318163816Smjacob				scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
4319163816Smjacob		}
4320163816Smjacob
4321163816Smjacob		spi->sync_period = tinfo->period;
4322163816Smjacob		spi->sync_offset = tinfo->offset;
4323163816Smjacob		spi->bus_width = tinfo->width;
4324163816Smjacob
4325163816Smjacob		splx(s);
4326163816Smjacob		spi->valid = CTS_SPI_VALID_SYNC_RATE
4327163816Smjacob			   | CTS_SPI_VALID_SYNC_OFFSET
4328163816Smjacob			   | CTS_SPI_VALID_BUS_WIDTH
4329163816Smjacob			   | CTS_SPI_VALID_DISC;
4330163816Smjacob		scsi->valid = CTS_SCSI_VALID_TQ;
43317228Sse
433239247Sgibbs		ccb->ccb_h.status = CAM_REQ_CMP;
433339247Sgibbs		xpt_done(ccb);
433439247Sgibbs		break;
433539247Sgibbs	}
433639247Sgibbs	case XPT_CALC_GEOMETRY:
433739247Sgibbs	{
433839247Sgibbs		/* XXX JGibbs - I'm sure the NCR uses a different strategy,
433939247Sgibbs		 *		but it should be able to deal with Adaptec
434039247Sgibbs		 *		geometry too.
434139247Sgibbs		 */
4342116351Snjl		cam_calc_geometry(&ccb->ccg, /*extended*/1);
434339247Sgibbs		xpt_done(ccb);
434439247Sgibbs		break;
434539247Sgibbs	}
434639247Sgibbs	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */
434739247Sgibbs	{
434839247Sgibbs		OUTB (nc_scntl1, CRST);
434939247Sgibbs		ccb->ccb_h.status = CAM_REQ_CMP;
435039247Sgibbs		DELAY(10000);	/* Wait until our interrupt handler sees it */
435139247Sgibbs		xpt_done(ccb);
435239247Sgibbs		break;
435339247Sgibbs	}
435439247Sgibbs	case XPT_TERM_IO:		/* Terminate the I/O process */
435539247Sgibbs		/* XXX Implement */
435639247Sgibbs		ccb->ccb_h.status = CAM_REQ_INVALID;
435739247Sgibbs		xpt_done(ccb);
435839247Sgibbs		break;
435939247Sgibbs	case XPT_PATH_INQ:		/* Path routing inquiry */
436039247Sgibbs	{
436139247Sgibbs		struct ccb_pathinq *cpi = &ccb->cpi;
436239247Sgibbs
436339247Sgibbs		cpi->version_num = 1; /* XXX??? */
436439247Sgibbs		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
436539247Sgibbs		if ((np->features & FE_WIDE) != 0)
436639247Sgibbs			cpi->hba_inquiry |= PI_WIDE_16;
436739247Sgibbs		cpi->target_sprt = 0;
436839247Sgibbs		cpi->hba_misc = 0;
436939247Sgibbs		cpi->hba_eng_cnt = 0;
437039247Sgibbs		cpi->max_target = (np->features & FE_WIDE) ? 15 : 7;
437139247Sgibbs		cpi->max_lun = MAX_LUN - 1;
437239247Sgibbs		cpi->initiator_id = np->myaddr;
437339247Sgibbs		cpi->bus_id = cam_sim_bus(sim);
437446581Sken		cpi->base_transfer_speed = 3300;
437539247Sgibbs		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
437639247Sgibbs		strncpy(cpi->hba_vid, "Symbios", HBA_IDLEN);
437739247Sgibbs		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
437839247Sgibbs		cpi->unit_number = cam_sim_unit(sim);
4379163816Smjacob                cpi->transport = XPORT_SPI;
4380163816Smjacob                cpi->transport_version = 2;
4381163816Smjacob                cpi->protocol = PROTO_SCSI;
4382163816Smjacob                cpi->protocol_version = SCSI_REV_2;
438339247Sgibbs		cpi->ccb_h.status = CAM_REQ_CMP;
438439247Sgibbs		xpt_done(ccb);
438539247Sgibbs		break;
438639247Sgibbs	}
438739247Sgibbs	default:
438839247Sgibbs		ccb->ccb_h.status = CAM_REQ_INVALID;
438939247Sgibbs		xpt_done(ccb);
439039247Sgibbs		break;
439139247Sgibbs	}
43922432Sse}
43937228Sse
43942432Sse/*==========================================================
43952432Sse**
43962432Sse**
43972432Sse**	Complete execution of a SCSI command.
43982432Sse**	Signal completion to the generic SCSI driver.
43992432Sse**
44002432Sse**
44012432Sse**==========================================================
44022432Sse*/
44032432Sse
4404105219Sphkstatic void
440539247Sgibbsncr_complete (ncb_p np, nccb_p cp)
44062432Sse{
440739247Sgibbs	union ccb *ccb;
44082432Sse	tcb_p tp;
44092432Sse
44102432Sse	/*
44112432Sse	**	Sanity check
44122432Sse	*/
44132432Sse
441439247Sgibbs	if (!cp || (cp->magic!=CCB_MAGIC) || !cp->ccb) return;
44152432Sse	cp->magic = 1;
44162432Sse	cp->tlimit= 0;
44172432Sse
44182432Sse	/*
44192432Sse	**	No Reselect anymore.
44202432Sse	*/
442139247Sgibbs	cp->jump_nccb.l_cmd = (SCR_JUMP);
44222432Sse
44232432Sse	/*
44242432Sse	**	No starting.
44252432Sse	*/
442610677Sse	cp->phys.header.launch.l_paddr= NCB_SCRIPT_PHYS (np, idle);
44272432Sse
44282432Sse	/*
44292432Sse	**	timestamp
44302432Sse	*/
44312432Sse	ncb_profile (np, cp);
44327228Sse
44333552Sse	if (DEBUG_FLAGS & DEBUG_TINY)
443439532Sken		printf ("CCB=%x STAT=%x/%x\n", (int)(intptr_t)cp & 0xfff,
443539247Sgibbs			cp->host_status,cp->s_status);
44362432Sse
443739247Sgibbs	ccb = cp->ccb;
443839247Sgibbs	cp->ccb = NULL;
443939247Sgibbs	tp = &np->target[ccb->ccb_h.target_id];
44402432Sse
44412432Sse	/*
444239247Sgibbs	**	We do not queue more than 1 nccb per target
444339247Sgibbs	**	with negotiation at any time. If this nccb was
444427684Sse	**	used for negotiation, clear this info in the tcb.
444527684Sse	*/
444627684Sse
444727684Sse	if (cp == tp->nego_cp)
444839247Sgibbs		tp->nego_cp = NULL;
444927684Sse
445027684Sse	/*
44512432Sse	**	Check for parity errors.
44522432Sse	*/
445339247Sgibbs	/* XXX JGibbs - What about reporting them??? */
44542432Sse
44552814Sse	if (cp->parity_status) {
445639247Sgibbs		PRINT_ADDR(ccb);
44572814Sse		printf ("%d parity error(s), fallback.\n", cp->parity_status);
44582432Sse		/*
44592432Sse		**	fallback to asynch transfer.
44602432Sse		*/
446139247Sgibbs		tp->tinfo.goal.period = 0;
446239247Sgibbs		tp->tinfo.goal.offset = 0;
44632432Sse	};
44642814Sse
44652814Sse	/*
44662814Sse	**	Check for extended errors.
44672814Sse	*/
44682814Sse
44697250Sse	if (cp->xerr_status != XE_OK) {
447039247Sgibbs		PRINT_ADDR(ccb);
44712814Sse		switch (cp->xerr_status) {
44722814Sse		case XE_EXTRA_DATA:
44732814Sse			printf ("extraneous data discarded.\n");
44742814Sse			break;
44752814Sse		case XE_BAD_PHASE:
44762814Sse			printf ("illegal scsi phase (4/5).\n");
44772814Sse			break;
44782814Sse		default:
44792814Sse			printf ("extended error %d.\n", cp->xerr_status);
44802814Sse			break;
44812814Sse		};
44822814Sse		if (cp->host_status==HS_COMPLETE)
44832814Sse			cp->host_status = HS_FAIL;
44842814Sse	};
44857228Sse
44862432Sse	/*
44872432Sse	**	Check the status.
44882432Sse	*/
448939247Sgibbs	if (cp->host_status == HS_COMPLETE) {
44902432Sse
449139247Sgibbs		if (cp->s_status == SCSI_STATUS_OK) {
44922814Sse
44932814Sse			/*
449439247Sgibbs			**	All went well.
44952435Sse			*/
449639247Sgibbs			/* XXX JGibbs - Properly calculate residual */
44972432Sse
449839247Sgibbs			tp->bytes     += ccb->csio.dxfer_len;
449939247Sgibbs			tp->transfers ++;
45007228Sse
450139247Sgibbs			ccb->ccb_h.status = CAM_REQ_CMP;
450239247Sgibbs		} else if ((cp->s_status & SCSI_STATUS_SENSE) != 0) {
45032432Sse
450439247Sgibbs			/*
450539247Sgibbs			 * XXX Could be TERMIO too.  Should record
450639247Sgibbs			 * original status.
450739247Sgibbs			 */
450839247Sgibbs			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
450939247Sgibbs			cp->s_status &= ~SCSI_STATUS_SENSE;
451039247Sgibbs			if (cp->s_status == SCSI_STATUS_OK) {
451139247Sgibbs				ccb->ccb_h.status =
451239247Sgibbs				    CAM_AUTOSNS_VALID|CAM_SCSI_STATUS_ERROR;
451339247Sgibbs			} else {
451439247Sgibbs				ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
451539247Sgibbs			}
451639247Sgibbs		} else {
451739247Sgibbs			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
451839247Sgibbs			ccb->csio.scsi_status = cp->s_status;
451939247Sgibbs		}
452039247Sgibbs
452139247Sgibbs
452214938Sgibbs	} else if (cp->host_status == HS_SEL_TIMEOUT) {
45232432Sse
45242432Sse		/*
452514938Sgibbs		**   Device failed selection
452614938Sgibbs		*/
452739247Sgibbs		ccb->ccb_h.status = CAM_SEL_TIMEOUT;
452829292Sse
452939247Sgibbs	} else if (cp->host_status == HS_TIMEOUT) {
453014938Sgibbs
453114938Sgibbs		/*
45322432Sse		**   No response
45332432Sse		*/
453439247Sgibbs		ccb->ccb_h.status = CAM_CMD_TIMEOUT;
453539247Sgibbs	} else if (cp->host_status == HS_STALL) {
453639247Sgibbs		ccb->ccb_h.status = CAM_REQUEUE_REQ;
45372432Sse	} else {
45382432Sse
45392432Sse		/*
45402432Sse		**  Other protocol messes
45412432Sse		*/
454239247Sgibbs		PRINT_ADDR(ccb);
454339532Sken		printf ("COMMAND FAILED (%x %x) @%p.\n",
454439532Sken			cp->host_status, cp->s_status, cp);
45452432Sse
454639247Sgibbs		ccb->ccb_h.status = CAM_CMD_TIMEOUT;
45472432Sse	}
45487228Sse
454939247Sgibbs	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
455039247Sgibbs		xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
455139247Sgibbs		ccb->ccb_h.status |= CAM_DEV_QFRZN;
455239247Sgibbs	}
45532432Sse
45542432Sse	/*
455539247Sgibbs	**	Free this nccb
45562435Sse	*/
455739247Sgibbs	ncr_free_nccb (np, cp);
45582435Sse
45592435Sse	/*
45602432Sse	**	signal completion to generic driver.
45612432Sse	*/
456239247Sgibbs	xpt_done (ccb);
45632432Sse}
45647228Sse
45652432Sse/*==========================================================
45662432Sse**
45672432Sse**
45682432Sse**	Signal all (or one) control block done.
45692432Sse**
45702432Sse**
45712432Sse**==========================================================
45722432Sse*/
45732432Sse
4574105219Sphkstatic void
457539247Sgibbsncr_wakeup (ncb_p np, u_long code)
45762432Sse{
45772432Sse	/*
457839247Sgibbs	**	Starting at the default nccb and following
45792432Sse	**	the links, complete all jobs with a
45802432Sse	**	host_status greater than "disconnect".
45812432Sse	**
45822432Sse	**	If the "code" parameter is not zero,
45832432Sse	**	complete all jobs that are not IDLE.
45842432Sse	*/
45852432Sse
458639247Sgibbs	nccb_p cp = np->link_nccb;
45872432Sse	while (cp) {
45882432Sse		switch (cp->host_status) {
45892432Sse
45902432Sse		case HS_IDLE:
45912432Sse			break;
45922432Sse
45932432Sse		case HS_DISCONNECT:
45943552Sse			if(DEBUG_FLAGS & DEBUG_TINY) printf ("D");
4595102412Scharnier			/* FALLTHROUGH */
45962432Sse
45972432Sse		case HS_BUSY:
45982432Sse		case HS_NEGOTIATE:
45992432Sse			if (!code) break;
46002432Sse			cp->host_status = code;
46012432Sse
4602102412Scharnier			/* FALLTHROUGH */
46032432Sse
46042432Sse		default:
46052432Sse			ncr_complete (np, cp);
46062432Sse			break;
46072432Sse		};
460839247Sgibbs		cp = cp -> link_nccb;
46092432Sse	};
46102432Sse}
46117228Sse
461239247Sgibbsstatic void
461339247Sgibbsncr_freeze_devq (ncb_p np, struct cam_path *path)
461439247Sgibbs{
461539386Sgibbs	nccb_p	cp;
461639438Sgibbs	int	i;
461739386Sgibbs	int	count;
461839438Sgibbs	int	firstskip;
461939247Sgibbs	/*
462039247Sgibbs	**	Starting at the first nccb and following
462139247Sgibbs	**	the links, complete all jobs that match
462239247Sgibbs	**	the passed in path and are in the start queue.
462339247Sgibbs	*/
462439247Sgibbs
462539386Sgibbs	cp = np->link_nccb;
462639386Sgibbs	count = 0;
462739438Sgibbs	firstskip = 0;
462839247Sgibbs	while (cp) {
462939247Sgibbs		switch (cp->host_status) {
463039247Sgibbs
463139247Sgibbs		case HS_BUSY:
463239247Sgibbs		case HS_NEGOTIATE:
463339247Sgibbs			if ((cp->phys.header.launch.l_paddr
463439247Sgibbs			    == NCB_SCRIPT_PHYS (np, select))
463539247Sgibbs			 && (xpt_path_comp(path, cp->ccb->ccb_h.path) >= 0)) {
463639247Sgibbs
463739386Sgibbs				/* Mark for removal from the start queue */
463839438Sgibbs				for (i = 1; i < MAX_START; i++) {
463939438Sgibbs					int idx;
464039438Sgibbs
464139438Sgibbs					idx = np->squeueput - i;
464239438Sgibbs
464339438Sgibbs					if (idx < 0)
464439438Sgibbs						idx = MAX_START + idx;
464539438Sgibbs					if (np->squeue[idx]
464639438Sgibbs					 == CCB_PHYS(cp, phys)) {
464739438Sgibbs						np->squeue[idx] =
464839366Sgibbs						    NCB_SCRIPT_PHYS (np, skip);
464939438Sgibbs						if (i > firstskip)
465039438Sgibbs							firstskip = i;
465139438Sgibbs						break;
465239438Sgibbs					}
465339366Sgibbs				}
465439247Sgibbs				cp->host_status=HS_STALL;
465539247Sgibbs				ncr_complete (np, cp);
465639386Sgibbs				count++;
465739247Sgibbs			}
465839366Sgibbs			break;
465939247Sgibbs		default:
466039247Sgibbs			break;
466139247Sgibbs		}
466239247Sgibbs		cp = cp->link_nccb;
466339366Sgibbs	}
466439386Sgibbs
466539386Sgibbs	if (count > 0) {
466639386Sgibbs		int j;
466739386Sgibbs		int bidx;
466839386Sgibbs
466939386Sgibbs		/* Compress the start queue */
467039386Sgibbs		j = 0;
467139386Sgibbs		bidx = np->squeueput;
467239438Sgibbs		i = np->squeueput - firstskip;
467339438Sgibbs		if (i < 0)
467439438Sgibbs			i = MAX_START + i;
467539438Sgibbs		for (;;) {
467639386Sgibbs
467739386Sgibbs			bidx = i - j;
467839386Sgibbs			if (bidx < 0)
467939386Sgibbs				bidx = MAX_START + bidx;
468039386Sgibbs
468139438Sgibbs			if (np->squeue[i] == NCB_SCRIPT_PHYS (np, skip)) {
468239386Sgibbs				j++;
468339438Sgibbs			} else if (j != 0) {
468439386Sgibbs				np->squeue[bidx] = np->squeue[i];
468539386Sgibbs				if (np->squeue[bidx]
468639386Sgibbs				 == NCB_SCRIPT_PHYS(np, idle))
468739386Sgibbs					break;
468839386Sgibbs			}
468939438Sgibbs			i = (i + 1) % MAX_START;
469039386Sgibbs		}
469139386Sgibbs		np->squeueput = bidx;
469239386Sgibbs	}
469339247Sgibbs}
469439247Sgibbs
46952432Sse/*==========================================================
46962432Sse**
46972432Sse**
46982432Sse**	Start NCR chip.
46992432Sse**
47002432Sse**
47012432Sse**==========================================================
47022432Sse*/
47032432Sse
4704105219Sphkstatic void
470546581Skenncr_init(ncb_p np, char * msg, u_long code)
47062432Sse{
47072432Sse	int	i;
47082432Sse
47092432Sse	/*
47102432Sse	**	Reset chip.
47112432Sse	*/
47122432Sse
471310605Sse	OUTB (nc_istat,  SRST);
471410605Sse	DELAY (1000);
471528958Sse	OUTB (nc_istat, 0);
47162432Sse
47172432Sse	/*
47182432Sse	**	Message.
47192432Sse	*/
47202432Sse
47212432Sse	if (msg) printf ("%s: restart (%s).\n", ncr_name (np), msg);
47222432Sse
47232432Sse	/*
47242432Sse	**	Clear Start Queue
47252432Sse	*/
47262432Sse
47272432Sse	for (i=0;i<MAX_START;i++)
472810677Sse		np -> squeue [i] = NCB_SCRIPT_PHYS (np, idle);
47292432Sse
47302432Sse	/*
47312432Sse	**	Start at first entry.
47322432Sse	*/
47332432Sse
47342432Sse	np->squeueput = 0;
473539532Sken	WRITESCRIPT(startpos[0], NCB_SCRIPTH_PHYS (np, tryloop));
473639532Sken	WRITESCRIPT(start0  [0], SCR_INT ^ IFFALSE (0));
47372432Sse
47382432Sse	/*
47392432Sse	**	Wakeup all pending jobs.
47402432Sse	*/
47412432Sse
47422432Sse	ncr_wakeup (np, code);
47437228Sse
47442432Sse	/*
47452432Sse	**	Init chip.
47462432Sse	*/
47472432Sse
474820435Sse	OUTB (nc_istat,  0x00   );      /*  Remove Reset, abort ...	     */
47492432Sse	OUTB (nc_scntl0, 0xca   );      /*  full arb., ena parity, par->ATN  */
47502432Sse	OUTB (nc_scntl1, 0x00	);	/*  odd parity, and remove CRST!!    */
475127684Sse	ncr_selectclock(np, np->rv_scntl3); /* Select SCSI clock             */
47526856Sse	OUTB (nc_scid  , RRE|np->myaddr);/*  host adapter SCSI address       */
475310605Sse	OUTW (nc_respid, 1ul<<np->myaddr);/*  id to respond to		     */
475410605Sse	OUTB (nc_istat , SIGP	);	/*  Signal Process		     */
475520435Sse	OUTB (nc_dmode , np->rv_dmode);	/* XXX modify burstlen ??? */
475620435Sse	OUTB (nc_dcntl , np->rv_dcntl);
475720435Sse	OUTB (nc_ctest3, np->rv_ctest3);
475820435Sse	OUTB (nc_ctest5, np->rv_ctest5);
475927684Sse	OUTB (nc_ctest4, np->rv_ctest4);/*  enable master parity checking    */
476027684Sse	OUTB (nc_stest2, np->rv_stest2|EXT); /* Extended Sreq/Sack filtering */
476110605Sse	OUTB (nc_stest3, TE     );	/*  TolerANT enable		     */
476213447Sse	OUTB (nc_stime0, 0x0b	);	/*  HTH = disabled, STO = 0.1 sec.   */
47632432Sse
476427744Sse	if (bootverbose >= 2) {
476527684Sse		printf ("\tACTUAL values:SCNTL3:%02x DMODE:%02x  DCNTL:%02x\n",
476627684Sse			np->rv_scntl3, np->rv_dmode, np->rv_dcntl);
476727684Sse		printf ("\t              CTEST3:%02x CTEST4:%02x CTEST5:%02x\n",
476827684Sse			np->rv_ctest3, np->rv_ctest4, np->rv_ctest5);
476920435Sse	}
477020435Sse
47712432Sse	/*
477227684Sse	**    Enable GPIO0 pin for writing if LED support.
477327684Sse	*/
477427684Sse
477527684Sse	if (np->features & FE_LED0) {
477627684Sse		OUTOFFB (nc_gpcntl, 0x01);
477727684Sse	}
477827684Sse
477927684Sse	/*
47802814Sse	**	Fill in target structure.
47812814Sse	*/
47822432Sse	for (i=0;i<MAX_TARGET;i++) {
47832432Sse		tcb_p tp = &np->target[i];
47842814Sse
478539247Sgibbs		tp->tinfo.sval    = 0;
478639247Sgibbs		tp->tinfo.wval    = np->rv_scntl3;
47872814Sse
478839247Sgibbs		tp->tinfo.current.period = 0;
478939247Sgibbs		tp->tinfo.current.offset = 0;
479039247Sgibbs		tp->tinfo.current.width = MSG_EXT_WDTR_BUS_8_BIT;
47912432Sse	}
47922432Sse
47932432Sse	/*
47942432Sse	**      enable ints
47952432Sse	*/
47962432Sse
47972432Sse	OUTW (nc_sien , STO|HTH|MA|SGE|UDC|RST);
47982432Sse	OUTB (nc_dien , MDPE|BF|ABRT|SSI|SIR|IID);
47992432Sse
48002432Sse	/*
48012432Sse	**    Start script processor.
48022432Sse	*/
48032432Sse
480410677Sse	OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start));
48057228Sse
48062814Sse	/*
480739247Sgibbs	 * Notify the XPT of the event
480839247Sgibbs	 */
480939247Sgibbs	if (code == HS_RESET)
481039247Sgibbs		xpt_async(AC_BUS_RESET, np->path, NULL);
481139247Sgibbs}
48122814Sse
481339247Sgibbsstatic void
481439247Sgibbsncr_poll(struct cam_sim *sim)
481539247Sgibbs{
481639247Sgibbs	ncr_intr(cam_sim_softc(sim));
481739247Sgibbs}
48182814Sse
48192814Sse
48202814Sse/*==========================================================
48212814Sse**
482227684Sse**	Get clock factor and sync divisor for a given
482327684Sse**	synchronous factor period.
482427684Sse**	Returns the clock factor (in sxfer) and scntl3
482527684Sse**	synchronous divisor field.
482627684Sse**
482727684Sse**==========================================================
482827684Sse*/
482927684Sse
483027684Ssestatic void ncr_getsync(ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p)
483127684Sse{
483227684Sse	u_long	clk = np->clock_khz;	/* SCSI clock frequency in kHz	*/
483327684Sse	int	div = np->clock_divn;	/* Number of divisors supported	*/
483427684Sse	u_long	fak;			/* Sync factor in sxfer		*/
483527684Sse	u_long	per;			/* Period in tenths of ns	*/
483627684Sse	u_long	kpc;			/* (per * clk)			*/
483727684Sse
483827684Sse	/*
483927684Sse	**	Compute the synchronous period in tenths of nano-seconds
484027684Sse	*/
484127684Sse	if	(sfac <= 10)	per = 250;
484227684Sse	else if	(sfac == 11)	per = 303;
484327684Sse	else if	(sfac == 12)	per = 500;
484427684Sse	else			per = 40 * sfac;
484527684Sse
484627684Sse	/*
484727684Sse	**	Look for the greatest clock divisor that allows an
484827684Sse	**	input speed faster than the period.
484927684Sse	*/
485027684Sse	kpc = per * clk;
485127684Sse	while (--div >= 0)
485227684Sse		if (kpc >= (div_10M[div] * 4)) break;
485327684Sse
485427684Sse	/*
485527684Sse	**	Calculate the lowest clock factor that allows an output
485627684Sse	**	speed not faster than the period.
485727684Sse	*/
485827684Sse	fak = (kpc - 1) / div_10M[div] + 1;
485927684Sse
4860249585Sgabor#if 0	/* You can #if 1 if you think this optimization is useful */
486127684Sse
486227684Sse	per = (fak * div_10M[div]) / clk;
486327684Sse
486427684Sse	/*
486527684Sse	**	Why not to try the immediate lower divisor and to choose
486627684Sse	**	the one that allows the fastest output speed ?
486727684Sse	**	We dont want input speed too much greater than output speed.
486827684Sse	*/
486927684Sse	if (div >= 1 && fak < 6) {
487027684Sse		u_long fak2, per2;
487127684Sse		fak2 = (kpc - 1) / div_10M[div-1] + 1;
487227684Sse		per2 = (fak2 * div_10M[div-1]) / clk;
487327684Sse		if (per2 < per && fak2 <= 6) {
487427684Sse			fak = fak2;
487527684Sse			per = per2;
487627684Sse			--div;
487727684Sse		}
487827684Sse	}
487927684Sse#endif
488027684Sse
488127684Sse	if (fak < 4) fak = 4;	/* Should never happen, too bad ... */
488227684Sse
488327684Sse	/*
488427684Sse	**	Compute and return sync parameters for the ncr
488527684Sse	*/
488627684Sse	*fakp		= fak - 4;
488727684Sse	*scntl3p	= ((div+1) << 4) + (sfac < 25 ? 0x80 : 0);
488827684Sse}
488927684Sse
489027684Sse/*==========================================================
489127684Sse**
489235256Sdes**	Switch sync mode for current job and its target
48932432Sse**
48942432Sse**==========================================================
48952432Sse*/
48962432Sse
489739247Sgibbsstatic void
489839247Sgibbsncr_setsync(ncb_p np, nccb_p cp, u_char scntl3, u_char sxfer, u_char period)
48992432Sse{
490039247Sgibbs	union	ccb *ccb;
490139247Sgibbs	struct	ccb_trans_settings neg;
490239247Sgibbs	tcb_p	tp;
490339247Sgibbs	int	div;
490446843Sse	u_int	target = INB (nc_sdid) & 0x0f;
490539247Sgibbs	u_int	period_10ns;
49062432Sse
49072432Sse	assert (cp);
49082432Sse	if (!cp) return;
49092432Sse
491039247Sgibbs	ccb = cp->ccb;
491139247Sgibbs	assert (ccb);
491239247Sgibbs	if (!ccb) return;
491339247Sgibbs	assert (target == ccb->ccb_h.target_id);
49142432Sse
49152432Sse	tp = &np->target[target];
49162814Sse
491727684Sse	if (!scntl3 || !(sxfer & 0x1f))
491827684Sse		scntl3 = np->rv_scntl3;
491939247Sgibbs	scntl3 = (scntl3 & 0xf0) | (tp->tinfo.wval & EWS)
492039247Sgibbs	       | (np->rv_scntl3 & 0x07);
492127684Sse
492227684Sse	/*
492327684Sse	**	Deduce the value of controller sync period from scntl3.
492427684Sse	**	period is in tenths of nano-seconds.
492527684Sse	*/
492627684Sse
492727684Sse	div = ((scntl3 >> 4) & 0x7);
492827684Sse	if ((sxfer & 0x1f) && div)
492939247Sgibbs		period_10ns =
493039247Sgibbs		    (((sxfer>>5)+4)*div_10M[div-1])/np->clock_khz;
493127684Sse	else
493239247Sgibbs		period_10ns = 0;
493327684Sse
493439247Sgibbs	tp->tinfo.goal.period = period;
493539247Sgibbs	tp->tinfo.goal.offset = sxfer & 0x1f;
493639247Sgibbs	tp->tinfo.current.period = period;
493739247Sgibbs	tp->tinfo.current.offset = sxfer & 0x1f;
493839247Sgibbs
493927684Sse	/*
494027684Sse	**	 Stop there if sync parameters are unchanged
494127684Sse	*/
494239247Sgibbs	if (tp->tinfo.sval == sxfer && tp->tinfo.wval == scntl3) return;
494339247Sgibbs	tp->tinfo.sval = sxfer;
494439247Sgibbs	tp->tinfo.wval = scntl3;
494527684Sse
494620435Sse	if (sxfer & 0x1f) {
49472432Sse		/*
49482432Sse		**  Disable extended Sreq/Sack filtering
49492432Sse		*/
495039247Sgibbs		if (period_10ns <= 2000) OUTOFFB (nc_stest2, EXT);
495139247Sgibbs	}
49522432Sse
49532432Sse	/*
495439247Sgibbs	** Tell the SCSI layer about the
495539247Sgibbs	** new transfer parameters.
495639247Sgibbs	*/
4957163816Smjacob	memset(&neg, 0, sizeof (neg));
4958163816Smjacob	neg.protocol = PROTO_SCSI;
4959163816Smjacob	neg.protocol_version = SCSI_REV_2;
4960163816Smjacob	neg.transport = XPORT_SPI;
4961163816Smjacob	neg.transport_version = 2;
4962163816Smjacob	neg.xport_specific.spi.sync_period = period;
4963163816Smjacob	neg.xport_specific.spi.sync_offset = sxfer & 0x1f;
4964163816Smjacob	neg.xport_specific.spi.valid = CTS_SPI_VALID_SYNC_RATE
4965163816Smjacob		| CTS_SPI_VALID_SYNC_OFFSET;
496639247Sgibbs	xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path,
496739247Sgibbs		      /*priority*/1);
496839247Sgibbs	xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg);
496939247Sgibbs
497039247Sgibbs	/*
49712432Sse	**	set actual value and sync_status
49722432Sse	*/
49732432Sse	OUTB (nc_sxfer, sxfer);
49742814Sse	np->sync_st = sxfer;
497527684Sse	OUTB (nc_scntl3, scntl3);
497627684Sse	np->wide_st = scntl3;
49772432Sse
49782432Sse	/*
497939247Sgibbs	**	patch ALL nccbs of this target.
49802432Sse	*/
498139247Sgibbs	for (cp = np->link_nccb; cp; cp = cp->link_nccb) {
498239247Sgibbs		if (!cp->ccb) continue;
498339247Sgibbs		if (cp->ccb->ccb_h.target_id != target) continue;
49842432Sse		cp->sync_status = sxfer;
498527684Sse		cp->wide_status = scntl3;
49862432Sse	};
49872432Sse}
49887228Sse
49892432Sse/*==========================================================
49902432Sse**
499135256Sdes**	Switch wide mode for current job and its target
499227684Sse**	SCSI specs say: a SCSI device that accepts a WDTR
499327684Sse**	message shall reset the synchronous agreement to
499427684Sse**	asynchronous mode.
49952814Sse**
49962814Sse**==========================================================
49972814Sse*/
49982814Sse
499939247Sgibbsstatic void ncr_setwide (ncb_p np, nccb_p cp, u_char wide, u_char ack)
50002814Sse{
500139247Sgibbs	union	ccb *ccb;
500239247Sgibbs	struct	ccb_trans_settings neg;
500346843Sse	u_int	target = INB (nc_sdid) & 0x0f;
500439247Sgibbs	tcb_p	tp;
500527684Sse	u_char	scntl3;
500627684Sse	u_char	sxfer;
50072814Sse
50082814Sse	assert (cp);
50092814Sse	if (!cp) return;
50102814Sse
501139247Sgibbs	ccb = cp->ccb;
501239247Sgibbs	assert (ccb);
501339247Sgibbs	if (!ccb) return;
501439247Sgibbs	assert (target == ccb->ccb_h.target_id);
50152814Sse
50162814Sse	tp = &np->target[target];
501739247Sgibbs	tp->tinfo.current.width = wide;
501839247Sgibbs	tp->tinfo.goal.width = wide;
501939247Sgibbs	tp->tinfo.current.period = 0;
502039247Sgibbs	tp->tinfo.current.offset = 0;
502127684Sse
502239247Sgibbs	scntl3 = (tp->tinfo.wval & (~EWS)) | (wide ? EWS : 0);
502327684Sse
502439247Sgibbs	sxfer = ack ? 0 : tp->tinfo.sval;
502539247Sgibbs
502627684Sse	/*
502727684Sse	**	 Stop there if sync/wide parameters are unchanged
502827684Sse	*/
502939247Sgibbs	if (tp->tinfo.sval == sxfer && tp->tinfo.wval == scntl3) return;
503039247Sgibbs	tp->tinfo.sval = sxfer;
503139247Sgibbs	tp->tinfo.wval = scntl3;
50322814Sse
503339247Sgibbs	/* Tell the SCSI layer about the new transfer params */
5034163816Smjacob	memset(&neg, 0, sizeof (neg));
5035163816Smjacob	neg.protocol = PROTO_SCSI;
5036163816Smjacob	neg.protocol_version = SCSI_REV_2;
5037163816Smjacob	neg.transport = XPORT_SPI;
5038163816Smjacob	neg.transport_version = 2;
5039163816Smjacob	neg.xport_specific.spi.bus_width = (scntl3 & EWS) ?
5040163816Smjacob	    MSG_EXT_WDTR_BUS_16_BIT : MSG_EXT_WDTR_BUS_8_BIT;
5041163816Smjacob	neg.xport_specific.spi.sync_period = 0;
5042163816Smjacob	neg.xport_specific.spi.sync_offset = 0;
5043163816Smjacob	neg.xport_specific.spi.valid = CTS_SPI_VALID_SYNC_RATE
5044163816Smjacob		| CTS_SPI_VALID_SYNC_OFFSET
5045163816Smjacob		| CTS_SPI_VALID_BUS_WIDTH;
5046163816Smjacob	xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, /*priority*/1);
504739247Sgibbs	xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg);
50482814Sse
50492814Sse	/*
50502814Sse	**	set actual value and sync_status
50512814Sse	*/
505227684Sse	OUTB (nc_sxfer, sxfer);
505327684Sse	np->sync_st = sxfer;
50542814Sse	OUTB (nc_scntl3, scntl3);
50552814Sse	np->wide_st = scntl3;
50562814Sse
50572814Sse	/*
505839247Sgibbs	**	patch ALL nccbs of this target.
50592814Sse	*/
506039247Sgibbs	for (cp = np->link_nccb; cp; cp = cp->link_nccb) {
506139247Sgibbs		if (!cp->ccb) continue;
506239247Sgibbs		if (cp->ccb->ccb_h.target_id != target) continue;
506327684Sse		cp->sync_status = sxfer;
50642814Sse		cp->wide_status = scntl3;
50652814Sse	};
50662814Sse}
50677228Sse
50682814Sse/*==========================================================
50692814Sse**
50702432Sse**
50712432Sse**	ncr timeout handler.
50722432Sse**
50732432Sse**
50742432Sse**==========================================================
50752432Sse**
50762432Sse**	Misused to keep the driver running when
50776705Sse**	interrupts are not configured correctly.
50782432Sse**
50792432Sse**----------------------------------------------------------
50802432Sse*/
50812432Sse
508239247Sgibbsstatic void
508339247Sgibbsncr_timeout (void *arg)
50842432Sse{
508525048Sbde	ncb_p	np = arg;
508639554Sgibbs	time_t	thistime = time_second;
508739554Sgibbs	ticks_t	step  = np->ticks;
50882432Sse	u_long	count = 0;
50892432Sse	long signed   t;
509039247Sgibbs	nccb_p cp;
50912432Sse
50922432Sse	if (np->lasttime != thistime) {
50936132Sdg		/*
50946705Sse		**	block ncr interrupts
50956132Sdg		*/
509639247Sgibbs		int oldspl = splcam();
50972432Sse		np->lasttime = thistime;
50982432Sse
50992432Sse		/*----------------------------------------------------
51002432Sse		**
51012432Sse		**	handle ncr chip timeouts
51022432Sse		**
51032432Sse		**	Assumption:
51042432Sse		**	We have a chance to arbitrate for the
51052432Sse		**	SCSI bus at least every 10 seconds.
51062432Sse		**
51072432Sse		**----------------------------------------------------
51082432Sse		*/
51092432Sse
51102432Sse		t = thistime - np->heartbeat;
51112432Sse
51122432Sse		if (t<2) np->latetime=0; else np->latetime++;
51132432Sse
51142432Sse		if (np->latetime>2) {
51152432Sse			/*
51162432Sse			**      If there are no requests, the script
51172432Sse			**      processor will sleep on SEL_WAIT_RESEL.
51182432Sse			**      But we have to check whether it died.
511920435Sse			**      Let's try to wake it up.
51202432Sse			*/
51212432Sse			OUTB (nc_istat, SIGP);
51222432Sse		};
51232432Sse
51242432Sse		/*----------------------------------------------------
51252432Sse		**
512639247Sgibbs		**	handle nccb timeouts
51272432Sse		**
51282432Sse		**----------------------------------------------------
51292432Sse		*/
51302432Sse
513139247Sgibbs		for (cp=np->link_nccb; cp; cp=cp->link_nccb) {
51322432Sse			/*
513339247Sgibbs			**	look for timed out nccbs.
51342432Sse			*/
51352432Sse			if (!cp->host_status) continue;
51362432Sse			count++;
51372432Sse			if (cp->tlimit > thistime) continue;
51382432Sse
51392432Sse			/*
51402432Sse			**	Disable reselect.
51412432Sse			**      Remove it from startqueue.
51422432Sse			*/
514339247Sgibbs			cp->jump_nccb.l_cmd = (SCR_JUMP);
51442432Sse			if (cp->phys.header.launch.l_paddr ==
514510677Sse				NCB_SCRIPT_PHYS (np, select)) {
514639532Sken				printf ("%s: timeout nccb=%p (skip)\n",
514739532Sken					ncr_name (np), cp);
51482432Sse				cp->phys.header.launch.l_paddr
514910677Sse				= NCB_SCRIPT_PHYS (np, skip);
51502432Sse			};
51512432Sse
51522432Sse			switch (cp->host_status) {
51532432Sse
51542432Sse			case HS_BUSY:
51552432Sse			case HS_NEGOTIATE:
5156102412Scharnier				/* FALLTHROUGH */
51572432Sse			case HS_DISCONNECT:
51582432Sse				cp->host_status=HS_TIMEOUT;
51592432Sse			};
51602432Sse			cp->tag = 0;
51612432Sse
51622432Sse			/*
516339247Sgibbs			**	wakeup this nccb.
51642432Sse			*/
51656132Sdg			ncr_complete (np, cp);
51662432Sse		};
51676132Sdg		splx (oldspl);
51682432Sse	}
51697228Sse
517039247Sgibbs	np->timeout_ch =
517139247Sgibbs		timeout (ncr_timeout, (caddr_t) np, step ? step : 1);
51722432Sse
51736302Sse	if (INB(nc_istat) & (INTF|SIP|DIP)) {
51742432Sse
51752432Sse		/*
51766705Sse		**	Process pending interrupts.
51772432Sse		*/
51782432Sse
517939247Sgibbs		int	oldspl	= splcam();
51803552Sse		if (DEBUG_FLAGS & DEBUG_TINY) printf ("{");
51812432Sse		ncr_exception (np);
51823552Sse		if (DEBUG_FLAGS & DEBUG_TINY) printf ("}");
51832432Sse		splx (oldspl);
51842432Sse	};
51852432Sse}
51867228Sse
51872432Sse/*==========================================================
51882432Sse**
518927744Sse**	log message for real hard errors
51902432Sse**
519127744Sse**	"ncr0 targ 0?: ERROR (ds:si) (so-si-sd) (sxfer/scntl3) @ name (dsp:dbc)."
519227744Sse**	"	      reg: r0 r1 r2 r3 r4 r5 r6 ..... rf."
519327744Sse**
519427744Sse**	exception register:
519527744Sse**		ds:	dstat
519627744Sse**		si:	sist
519727744Sse**
519827744Sse**	SCSI bus lines:
519927744Sse**		so:	control lines as driver by NCR.
520027744Sse**		si:	control lines as seen by NCR.
520127744Sse**		sd:	scsi data lines as seen by NCR.
520227744Sse**
520327744Sse**	wide/fastmode:
520427744Sse**		sxfer:	(see the manual)
520527744Sse**		scntl3:	(see the manual)
520627744Sse**
520727744Sse**	current script command:
520880203Skris**		dsp:	script address (relative to start of script).
520927744Sse**		dbc:	first word of script command.
521027744Sse**
521127744Sse**	First 16 register of the chip:
521227744Sse**		r0..rf
521327744Sse**
521427744Sse**==========================================================
521527744Sse*/
521627744Sse
521727744Ssestatic void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat)
521827744Sse{
521928960Sse	u_int32_t dsp;
522027744Sse	int	script_ofs;
522127744Sse	int	script_size;
522227744Sse	char	*script_name;
522327744Sse	u_char	*script_base;
522427744Sse	int	i;
522527744Sse
522627744Sse	dsp	= INL (nc_dsp);
522727744Sse
522828636Sse	if (np->p_script < dsp &&
522928636Sse	    dsp <= np->p_script + sizeof(struct script)) {
523027744Sse		script_ofs	= dsp - np->p_script;
523127744Sse		script_size	= sizeof(struct script);
523227744Sse		script_base	= (u_char *) np->script;
523327744Sse		script_name	= "script";
523427744Sse	}
523528636Sse	else if (np->p_scripth < dsp &&
523628636Sse		 dsp <= np->p_scripth + sizeof(struct scripth)) {
523727744Sse		script_ofs	= dsp - np->p_scripth;
523827744Sse		script_size	= sizeof(struct scripth);
523927744Sse		script_base	= (u_char *) np->scripth;
524027744Sse		script_name	= "scripth";
524128636Sse	} else {
524228636Sse		script_ofs	= dsp;
524328636Sse		script_size	= 0;
524428636Sse		script_base	= 0;
524528636Sse		script_name	= "mem";
524627744Sse	}
524727744Sse
524828636Sse	printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n",
524946843Sse		ncr_name (np), (unsigned)INB (nc_sdid)&0x0f, dstat, sist,
525027744Sse		(unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl), (unsigned)INB (nc_sbdl),
525127744Sse		(unsigned)INB (nc_sxfer),(unsigned)INB (nc_scntl3), script_name, script_ofs,
525227744Sse		(unsigned)INL (nc_dbc));
525327744Sse
525427744Sse	if (((script_ofs & 3) == 0) &&
525527744Sse	    (unsigned)script_ofs < script_size) {
525627744Sse		printf ("%s: script cmd = %08x\n", ncr_name(np),
525739532Sken			(int)READSCRIPT_OFF(script_base, script_ofs));
525827744Sse	}
525927744Sse
526027744Sse        printf ("%s: regdump:", ncr_name(np));
526127744Sse        for (i=0; i<16;i++)
526227744Sse            printf (" %02x", (unsigned)INB_OFF(i));
526327744Sse        printf (".\n");
526427744Sse}
526527744Sse
526627744Sse/*==========================================================
526727744Sse**
526827744Sse**
52692432Sse**	ncr chip exception handler.
52702432Sse**
52712432Sse**
52722432Sse**==========================================================
52732432Sse*/
52742432Sse
5275105219Sphkstatic void ncr_exception (ncb_p np)
52762432Sse{
527710072Sse	u_char	istat, dstat;
527810072Sse	u_short	sist;
52792432Sse
52802432Sse	/*
52816705Sse	**	interrupt on the fly ?
52822432Sse	*/
52832432Sse	while ((istat = INB (nc_istat)) & INTF) {
528418875Sse		if (DEBUG_FLAGS & DEBUG_TINY) printf ("F ");
528513448Sse		OUTB (nc_istat, INTF);
52862432Sse		np->profile.num_fly++;
52872432Sse		ncr_wakeup (np, 0);
52882432Sse	};
528918875Sse	if (!(istat & (SIP|DIP))) {
529018875Sse		return;
529118875Sse	}
52922432Sse
52932432Sse	/*
52942432Sse	**	Steinbach's Guideline for Systems Programming:
52952432Sse	**	Never test for an error condition you don't know how to handle.
52962432Sse	*/
52972432Sse
529820435Sse	sist  = (istat & SIP) ? INW (nc_sist)  : 0;
529919548Sse	dstat = (istat & DIP) ? INB (nc_dstat) : 0;
53002432Sse	np->profile.num_int++;
53012432Sse
53023552Sse	if (DEBUG_FLAGS & DEBUG_TINY)
53032432Sse		printf ("<%d|%x:%x|%x:%x>",
53042432Sse			INB(nc_scr0),
53052432Sse			dstat,sist,
53063533Sse			(unsigned)INL(nc_dsp),
53073533Sse			(unsigned)INL(nc_dbc));
53082432Sse	if ((dstat==DFE) && (sist==PAR)) return;
53097228Sse
53102432Sse/*==========================================================
53112432Sse**
53122432Sse**	First the normal cases.
53132432Sse**
53142432Sse**==========================================================
53152432Sse*/
53162432Sse	/*-------------------------------------------
53172432Sse	**	SCSI reset
53182432Sse	**-------------------------------------------
53192432Sse	*/
53202432Sse
53212432Sse	if (sist & RST) {
532210605Sse		ncr_init (np, bootverbose ? "scsi reset" : NULL, HS_RESET);
53232432Sse		return;
53242432Sse	};
53252432Sse
53262432Sse	/*-------------------------------------------
53272432Sse	**	selection timeout
53282432Sse	**
53292432Sse	**	IID excluded from dstat mask!
53302432Sse	**	(chip bug)
53312432Sse	**-------------------------------------------
53322432Sse	*/
53332432Sse
53342432Sse	if ((sist  & STO) &&
53352432Sse		!(sist  & (GEN|HTH|MA|SGE|UDC|RST|PAR)) &&
53362432Sse		!(dstat & (MDPE|BF|ABRT|SIR))) {
53372432Sse		ncr_int_sto (np);
53382432Sse		return;
53392432Sse	};
53402432Sse
53412432Sse	/*-------------------------------------------
53422432Sse	**      Phase mismatch.
53432432Sse	**-------------------------------------------
53442432Sse	*/
53452432Sse
53462432Sse	if ((sist  & MA) &&
53472432Sse		!(sist  & (STO|GEN|HTH|SGE|UDC|RST|PAR)) &&
53482432Sse		!(dstat & (MDPE|BF|ABRT|SIR|IID))) {
534927512Sse		ncr_int_ma (np, dstat);
53502432Sse		return;
53512432Sse	};
53527228Sse
53532814Sse	/*----------------------------------------
53542814Sse	**	move command with length 0
53552814Sse	**----------------------------------------
53562814Sse	*/
53572432Sse
53582814Sse	if ((dstat & IID) &&
53592814Sse		!(sist  & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) &&
53602814Sse		!(dstat & (MDPE|BF|ABRT|SIR)) &&
53612814Sse		((INL(nc_dbc) & 0xf8000000) == SCR_MOVE_TBL)) {
53622814Sse		/*
53632814Sse		**      Target wants more data than available.
53642814Sse		**	The "no_data" script will do it.
53652814Sse		*/
536610677Sse		OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, no_data));
53672814Sse		return;
53682814Sse	};
53692814Sse
53702432Sse	/*-------------------------------------------
53716705Sse	**	Programmed interrupt
53722432Sse	**-------------------------------------------
53732432Sse	*/
53742432Sse
53752432Sse	if ((dstat & SIR) &&
53762432Sse		!(sist  & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) &&
53772432Sse		!(dstat & (MDPE|BF|ABRT|IID)) &&
53782814Sse		(INB(nc_dsps) <= SIR_MAX)) {
53792432Sse		ncr_int_sir (np);
53802432Sse		return;
53812432Sse	};
53822814Sse
53832432Sse	/*========================================
538427744Sse	**	log message for real hard errors
538527744Sse	**========================================
538627744Sse	*/
538727744Sse
538827744Sse	ncr_log_hard_error(np, sist, dstat);
538927744Sse
539027744Sse	/*========================================
53912432Sse	**	do the register dump
53922432Sse	**========================================
53932432Sse	*/
53942432Sse
539539554Sgibbs	if (time_second - np->regtime > 10) {
53962432Sse		int i;
539739554Sgibbs		np->regtime = time_second;
53982432Sse		for (i=0; i<sizeof(np->regdump); i++)
539943309Sdillon			((volatile char*)&np->regdump)[i] = INB_OFF(i);
54002432Sse		np->regdump.nc_dstat = dstat;
54012432Sse		np->regdump.nc_sist  = sist;
54022432Sse	};
54037228Sse
54042432Sse
54052432Sse	/*----------------------------------------
54062432Sse	**	clean up the dma fifo
54072432Sse	**----------------------------------------
54082432Sse	*/
54092432Sse
54102814Sse	if ( (INB(nc_sstat0) & (ILF|ORF|OLF)   ) ||
54117228Sse	     (INB(nc_sstat1) & (FF3210)	) ||
54122814Sse	     (INB(nc_sstat2) & (ILF1|ORF1|OLF1)) ||	/* wide .. */
54132814Sse	     !(dstat & DFE)) {
54142432Sse		printf ("%s: have to clear fifos.\n", ncr_name (np));
54152432Sse		OUTB (nc_stest3, TE|CSF);	/* clear scsi fifo */
541620435Sse		OUTB (nc_ctest3, np->rv_ctest3 | CLF);
541720435Sse						/* clear dma fifo  */
54182432Sse	}
54192432Sse
54202432Sse	/*----------------------------------------
542110605Sse	**	handshake timeout
542210605Sse	**----------------------------------------
542310605Sse	*/
542410605Sse
542510605Sse	if (sist & HTH) {
542610605Sse		printf ("%s: handshake timeout\n", ncr_name(np));
542710605Sse		OUTB (nc_scntl1, CRST);
542810605Sse		DELAY (1000);
542910605Sse		OUTB (nc_scntl1, 0x00);
543010605Sse		OUTB (nc_scr0, HS_FAIL);
543110677Sse		OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, cleanup));
543210605Sse		return;
543310605Sse	}
543410605Sse
543510605Sse	/*----------------------------------------
54362432Sse	**	unexpected disconnect
54372432Sse	**----------------------------------------
54382432Sse	*/
54392432Sse
54402432Sse	if ((sist  & UDC) &&
54412432Sse		!(sist  & (STO|GEN|HTH|MA|SGE|RST|PAR)) &&
54422432Sse		!(dstat & (MDPE|BF|ABRT|SIR|IID))) {
54432432Sse		OUTB (nc_scr0, HS_UNEXPECTED);
544410677Sse		OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, cleanup));
54452432Sse		return;
54462432Sse	};
54472814Sse
54482432Sse	/*----------------------------------------
54492432Sse	**	cannot disconnect
54502432Sse	**----------------------------------------
54512432Sse	*/
54522432Sse
54532432Sse	if ((dstat & IID) &&
54542432Sse		!(sist  & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) &&
54552432Sse		!(dstat & (MDPE|BF|ABRT|SIR)) &&
54562814Sse		((INL(nc_dbc) & 0xf8000000) == SCR_WAIT_DISC)) {
54572432Sse		/*
54586132Sdg		**      Unexpected data cycle while waiting for disconnect.
54592432Sse		*/
54606132Sdg		if (INB(nc_sstat2) & LDSC) {
54616132Sdg			/*
54626132Sdg			**	It's an early reconnect.
54636132Sdg			**	Let's continue ...
54646132Sdg			*/
546520435Sse			OUTB (nc_dcntl, np->rv_dcntl | STD);
54666132Sdg			/*
54676132Sdg			**	info message
54686132Sdg			*/
54697228Sse			printf ("%s: INFO: LDSC while IID.\n",
54706132Sdg				ncr_name (np));
54716132Sdg			return;
54726132Sdg		};
547310605Sse		printf ("%s: target %d doesn't release the bus.\n",
547446843Sse			ncr_name (np), INB (nc_sdid)&0x0f);
54752432Sse		/*
54766132Sdg		**	return without restarting the NCR.
54776132Sdg		**	timeout will do the real work.
54782432Sse		*/
54792432Sse		return;
54802432Sse	};
54812432Sse
54822432Sse	/*----------------------------------------
54832432Sse	**	single step
54842432Sse	**----------------------------------------
54852432Sse	*/
54862432Sse
54872432Sse	if ((dstat & SSI) &&
54882432Sse		!(sist  & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) &&
54892432Sse		!(dstat & (MDPE|BF|ABRT|SIR|IID))) {
549020435Sse		OUTB (nc_dcntl, np->rv_dcntl | STD);
54912432Sse		return;
54922432Sse	};
54937228Sse
54942432Sse/*
54952432Sse**	@RECOVER@ HTH, SGE, ABRT.
54962432Sse**
54976705Sse**	We should try to recover from these interrupts.
549810567Sse**	They may occur if there are problems with synch transfers, or
549910567Sse**	if targets are switched on or off while the driver is running.
55002432Sse*/
55012432Sse
55022432Sse	if (sist & SGE) {
550320435Sse		/* clear scsi offsets */
550420435Sse		OUTB (nc_ctest3, np->rv_ctest3 | CLF);
55052432Sse	}
55062432Sse
55072432Sse	/*
55082432Sse	**	Freeze controller to be able to read the messages.
55092432Sse	*/
55102432Sse
55113552Sse	if (DEBUG_FLAGS & DEBUG_FREEZE) {
55122432Sse		int i;
55132432Sse		unsigned char val;
55142432Sse		for (i=0; i<0x60; i++) {
55152432Sse			switch (i%16) {
55162432Sse
55172432Sse			case 0:
55182432Sse				printf ("%s: reg[%d0]: ",
55192432Sse					ncr_name(np),i/16);
55202432Sse				break;
55212432Sse			case 4:
55222432Sse			case 8:
55232432Sse			case 12:
55242432Sse				printf (" ");
55252432Sse				break;
55262432Sse			};
552760974Sdfr			val = bus_space_read_1(np->bst, np->bsh, i);
55282432Sse			printf (" %x%x", val/16, val%16);
55292432Sse			if (i%16==15) printf (".\n");
55302432Sse		};
55312432Sse
553229681Sgibbs		untimeout (ncr_timeout, (caddr_t) np, np->timeout_ch);
55332432Sse
55342432Sse		printf ("%s: halted!\n", ncr_name(np));
55352432Sse		/*
55362432Sse		**	don't restart controller ...
55372432Sse		*/
55382432Sse		OUTB (nc_istat,  SRST);
55392432Sse		return;
55402432Sse	};
55412432Sse
55426705Sse#ifdef NCR_FREEZE
55432432Sse	/*
55446705Sse	**	Freeze system to be able to read the messages.
55456705Sse	*/
55466705Sse	printf ("ncr: fatal error: system halted - press reset to reboot ...");
55476705Sse	for (;;);
55486705Sse#endif
55496705Sse
55506705Sse	/*
55512432Sse	**	sorry, have to kill ALL jobs ...
55522432Sse	*/
55532432Sse
55542432Sse	ncr_init (np, "fatal error", HS_FAIL);
55552432Sse}
55567228Sse
55572432Sse/*==========================================================
55582432Sse**
55592432Sse**	ncr chip exception handler for selection timeout
55602432Sse**
55612432Sse**==========================================================
55622432Sse**
55632432Sse**	There seems to be a bug in the 53c810.
55646705Sse**	Although a STO-Interrupt is pending,
55652432Sse**	it continues executing script commands.
55666705Sse**	But it will fail and interrupt (IID) on
55672432Sse**	the next instruction where it's looking
55682432Sse**	for a valid phase.
55692432Sse**
55702432Sse**----------------------------------------------------------
55712432Sse*/
55722432Sse
5573105219Sphkstatic void ncr_int_sto (ncb_p np)
55742432Sse{
55752432Sse	u_long dsa, scratcha, diff;
557639247Sgibbs	nccb_p cp;
55773552Sse	if (DEBUG_FLAGS & DEBUG_TINY) printf ("T");
55782432Sse
55792432Sse	/*
558039247Sgibbs	**	look for nccb and set the status.
55812432Sse	*/
55822432Sse
55832432Sse	dsa = INL (nc_dsa);
558439247Sgibbs	cp = np->link_nccb;
558510677Sse	while (cp && (CCB_PHYS (cp, phys) != dsa))
558639247Sgibbs		cp = cp->link_nccb;
55872432Sse
55882432Sse	if (cp) {
55892432Sse		cp-> host_status = HS_SEL_TIMEOUT;
55902432Sse		ncr_complete (np, cp);
55912432Sse	};
55922432Sse
55932432Sse	/*
55942432Sse	**	repair start queue
55952432Sse	*/
55962432Sse
55972432Sse	scratcha = INL (nc_scratcha);
559827744Sse	diff = scratcha - NCB_SCRIPTH_PHYS (np, tryloop);
55992432Sse
56009364Sse/*	assert ((diff <= MAX_START * 20) && !(diff % 20));*/
56012432Sse
56022432Sse	if ((diff <= MAX_START * 20) && !(diff % 20)) {
560339532Sken		WRITESCRIPT(startpos[0], scratcha);
560410677Sse		OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start));
56052432Sse		return;
56062432Sse	};
56072432Sse	ncr_init (np, "selection timeout", HS_FAIL);
56082432Sse}
56097228Sse
56102432Sse/*==========================================================
56112432Sse**
56122432Sse**
56132432Sse**	ncr chip exception handler for phase errors.
56142432Sse**
56152432Sse**
56162432Sse**==========================================================
56172432Sse**
56182432Sse**	We have to construct a new transfer descriptor,
56192432Sse**	to transfer the rest of the current block.
56202432Sse**
56212432Sse**----------------------------------------------------------
56222432Sse*/
56232432Sse
562427512Ssestatic void ncr_int_ma (ncb_p np, u_char dstat)
56252432Sse{
562628960Sse	u_int32_t	dbc;
562728960Sse	u_int32_t	rest;
562828960Sse	u_int32_t	dsa;
562928960Sse	u_int32_t	dsp;
563028960Sse	u_int32_t	nxtdsp;
563139532Sken	volatile void	*vdsp_base;
563239532Sken	size_t		vdsp_off;
563328960Sse	u_int32_t	oadr, olen;
563428960Sse	u_int32_t	*tblp, *newcmd;
563527684Sse	u_char	cmd, sbcl, ss0, ss2, ctest5;
563627684Sse	u_short	delta;
563739247Sgibbs	nccb_p	cp;
56382432Sse
56392432Sse	dsp = INL (nc_dsp);
56402432Sse	dsa = INL (nc_dsa);
56412432Sse	dbc = INL (nc_dbc);
56422432Sse	ss0 = INB (nc_sstat0);
56432814Sse	ss2 = INB (nc_sstat2);
56442432Sse	sbcl= INB (nc_sbcl);
56452432Sse
56462432Sse	cmd = dbc >> 24;
56472432Sse	rest= dbc & 0xffffff;
56482432Sse
564927684Sse	ctest5 = (np->rv_ctest5 & DFS) ? INB (nc_ctest5) : 0;
565027684Sse	if (ctest5 & DFS)
565127684Sse		delta=(((ctest5<<8) | (INB (nc_dfifo) & 0xff)) - rest) & 0x3ff;
565227684Sse	else
565327684Sse		delta=(INB (nc_dfifo) - rest) & 0x7f;
565427684Sse
565527684Sse
56562432Sse	/*
56572432Sse	**	The data in the dma fifo has not been transfered to
56582432Sse	**	the target -> add the amount to the rest
56592432Sse	**	and clear the data.
56602814Sse	**	Check the sstat2 register in case of wide transfer.
56612432Sse	*/
56622432Sse
566327512Sse	if (!(dstat & DFE)) rest += delta;
56642432Sse	if (ss0 & OLF) rest++;
56652432Sse	if (ss0 & ORF) rest++;
56662814Sse	if (INB(nc_scntl3) & EWS) {
56672814Sse		if (ss2 & OLF1) rest++;
56682814Sse		if (ss2 & ORF1) rest++;
56692814Sse	};
567020435Sse	OUTB (nc_ctest3, np->rv_ctest3 | CLF);	/* clear dma fifo  */
567120435Sse	OUTB (nc_stest3, TE|CSF);		/* clear scsi fifo */
56727228Sse
56732432Sse	/*
56749364Sse	**	locate matching cp
56752432Sse	*/
567639247Sgibbs	cp = np->link_nccb;
567710677Sse	while (cp && (CCB_PHYS (cp, phys) != dsa))
567839247Sgibbs		cp = cp->link_nccb;
56792432Sse
56809364Sse	if (!cp) {
568139554Sgibbs	    printf ("%s: SCSI phase error fixup: CCB already dequeued (%p)\n",
568239554Sgibbs		    ncr_name (np), (void *) np->header.cp);
56839364Sse	    return;
56849364Sse	}
56859364Sse	if (cp != np->header.cp) {
568639310Sgibbs	    printf ("%s: SCSI phase error fixup: CCB address mismatch "
568739390Sgibbs		    "(%p != %p) np->nccb = %p\n",
568839390Sgibbs		    ncr_name (np), (void *)cp, (void *)np->header.cp,
568939390Sgibbs		    (void *)np->link_nccb);
569013809Sse/*	    return;*/
56919364Sse	}
56922432Sse
56932432Sse	/*
56946705Sse	**	find the interrupted script command,
56959364Sse	**	and the address at which to continue.
56962432Sse	*/
56972432Sse
56982432Sse	if (dsp == vtophys (&cp->patch[2])) {
569939532Sken		vdsp_base = cp;
570039532Sken		vdsp_off = offsetof(struct nccb, patch[0]);
570139532Sken		nxtdsp = READSCRIPT_OFF(vdsp_base, vdsp_off + 3*4);
57022432Sse	} else if (dsp == vtophys (&cp->patch[6])) {
570339532Sken		vdsp_base = cp;
570439532Sken		vdsp_off = offsetof(struct nccb, patch[4]);
570539532Sken		nxtdsp = READSCRIPT_OFF(vdsp_base, vdsp_off + 3*4);
570627744Sse	} else if (dsp > np->p_script &&
570727744Sse		   dsp <= np->p_script + sizeof(struct script)) {
570839532Sken		vdsp_base = np->script;
570939532Sken		vdsp_off = dsp - np->p_script - 8;
571027744Sse		nxtdsp = dsp;
57112432Sse	} else {
571239532Sken		vdsp_base = np->scripth;
571339532Sken		vdsp_off = dsp - np->p_scripth - 8;
57142432Sse		nxtdsp = dsp;
57152432Sse	};
57162432Sse
57172432Sse	/*
57182432Sse	**	log the information
57192432Sse	*/
57203552Sse	if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE)) {
572110605Sse		printf ("P%x%x ",cmd&7, sbcl&7);
57223533Sse		printf ("RL=%d D=%d SS0=%x ",
57233533Sse			(unsigned) rest, (unsigned) delta, ss0);
57242432Sse	};
57253552Sse	if (DEBUG_FLAGS & DEBUG_PHASE) {
572639532Sken		printf ("\nCP=%p CP2=%p DSP=%x NXT=%x VDSP=%p CMD=%x ",
572739532Sken			cp, np->header.cp,
572839532Sken			dsp,
572960974Sdfr			nxtdsp, (volatile char*)vdsp_base+vdsp_off, cmd);
57302432Sse	};
57312432Sse
57322432Sse	/*
57332432Sse	**	get old startaddress and old length.
57342432Sse	*/
57352432Sse
573639532Sken	oadr = READSCRIPT_OFF(vdsp_base, vdsp_off + 1*4);
57372432Sse
57382432Sse	if (cmd & 0x10) {	/* Table indirect */
573928960Sse		tblp = (u_int32_t *) ((char*) &cp->phys + oadr);
57402432Sse		olen = tblp[0];
57412432Sse		oadr = tblp[1];
57422432Sse	} else {
574328960Sse		tblp = (u_int32_t *) 0;
574439532Sken		olen = READSCRIPT_OFF(vdsp_base, vdsp_off) & 0xffffff;
57452432Sse	};
57467228Sse
57473552Sse	if (DEBUG_FLAGS & DEBUG_PHASE) {
574839757Sbde		printf ("OCMD=%x\nTBLP=%p OLEN=%lx OADR=%lx\n",
574939532Sken			(unsigned) (READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24),
575039757Sbde			(void *) tblp,
575139757Sbde			(u_long) olen,
575239757Sbde			(u_long) oadr);
57532432Sse	};
57542432Sse
57552432Sse	/*
57562432Sse	**	if old phase not dataphase, leave here.
57572432Sse	*/
57582432Sse
575939532Sken	if (cmd != (READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24)) {
576039247Sgibbs		PRINT_ADDR(cp->ccb);
576110567Sse		printf ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n",
576239532Sken			(unsigned)cmd,
576339532Sken			(unsigned)READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24);
576410567Sse
576510567Sse		return;
576610567Sse	}
57672432Sse	if (cmd & 0x06) {
576839247Sgibbs		PRINT_ADDR(cp->ccb);
576910605Sse		printf ("phase change %x-%x %d@%08x resid=%d.\n",
57703533Sse			cmd&7, sbcl&7, (unsigned)olen,
57713533Sse			(unsigned)oadr, (unsigned)rest);
57722432Sse
577320435Sse		OUTB (nc_dcntl, np->rv_dcntl | STD);
57742432Sse		return;
57752432Sse	};
57762432Sse
57772432Sse	/*
57782432Sse	**	choose the correct patch area.
57792432Sse	**	if savep points to one, choose the other.
57802432Sse	*/
57812432Sse
57822432Sse	newcmd = cp->patch;
57832432Sse	if (cp->phys.header.savep == vtophys (newcmd)) newcmd+=4;
57842432Sse
57852432Sse	/*
57862432Sse	**	fillin the commands
57872432Sse	*/
57882432Sse
57892432Sse	newcmd[0] = ((cmd & 0x0f) << 24) | rest;
57902432Sse	newcmd[1] = oadr + olen - rest;
57912432Sse	newcmd[2] = SCR_JUMP;
57922432Sse	newcmd[3] = nxtdsp;
57932432Sse
57943552Sse	if (DEBUG_FLAGS & DEBUG_PHASE) {
579539247Sgibbs		PRINT_ADDR(cp->ccb);
57962432Sse		printf ("newcmd[%d] %x %x %x %x.\n",
579739532Sken			(int)(newcmd - cp->patch),
57983533Sse			(unsigned)newcmd[0],
57993533Sse			(unsigned)newcmd[1],
58003533Sse			(unsigned)newcmd[2],
58013533Sse			(unsigned)newcmd[3]);
58022432Sse	}
58032432Sse	/*
58042432Sse	**	fake the return address (to the patch).
58052432Sse	**	and restart script processor at dispatcher.
58062432Sse	*/
58072432Sse	np->profile.num_break++;
58082432Sse	OUTL (nc_temp, vtophys (newcmd));
580927512Sse	if ((cmd & 7) == 0)
581027512Sse		OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch));
581127512Sse	else
581227512Sse		OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, checkatn));
58132432Sse}
58147228Sse
58152432Sse/*==========================================================
58162432Sse**
58172432Sse**
58186705Sse**      ncr chip exception handler for programmed interrupts.
58192432Sse**
58202432Sse**
58212432Sse**==========================================================
58222432Sse*/
58232432Sse
58242814Ssestatic int ncr_show_msg (u_char * msg)
58252432Sse{
58262432Sse	u_char i;
58272432Sse	printf ("%x",*msg);
582839247Sgibbs	if (*msg==MSG_EXTENDED) {
58292432Sse		for (i=1;i<8;i++) {
58302432Sse			if (i-1>msg[1]) break;
58312432Sse			printf ("-%x",msg[i]);
58322432Sse		};
58332814Sse		return (i+1);
58342432Sse	} else if ((*msg & 0xf0) == 0x20) {
58352432Sse		printf ("-%x",msg[1]);
58362814Sse		return (2);
58372814Sse	};
58382814Sse	return (1);
58392432Sse}
58402432Sse
5841105219Sphkstatic void ncr_int_sir (ncb_p np)
58422432Sse{
584327762Sse	u_char scntl3;
58442814Sse	u_char chg, ofs, per, fak, wide;
58452432Sse	u_char num = INB (nc_dsps);
584639247Sgibbs	nccb_p	cp=0;
58472432Sse	u_long	dsa;
584846843Sse	u_int	target = INB (nc_sdid) & 0x0f;
58492814Sse	tcb_p	tp     = &np->target[target];
58502814Sse	int     i;
58513552Sse	if (DEBUG_FLAGS & DEBUG_TINY) printf ("I#%d", num);
58522432Sse
58532432Sse	switch (num) {
58542814Sse	case SIR_SENSE_RESTART:
58552814Sse	case SIR_STALL_RESTART:
58562814Sse		break;
58572814Sse
58582814Sse	default:
58592432Sse		/*
586039247Sgibbs		**	lookup the nccb
58612432Sse		*/
58622432Sse		dsa = INL (nc_dsa);
586339247Sgibbs		cp = np->link_nccb;
586410677Sse		while (cp && (CCB_PHYS (cp, phys) != dsa))
586539247Sgibbs			cp = cp->link_nccb;
58662432Sse
58672432Sse		assert (cp);
58682432Sse		if (!cp)
58692432Sse			goto out;
587010639Sse		assert (cp == np->header.cp);
587110639Sse		if (cp != np->header.cp)
587210639Sse			goto out;
58732432Sse	}
58742432Sse
58752432Sse	switch (num) {
58767228Sse
58772432Sse/*--------------------------------------------------------------------
58782432Sse**
58796705Sse**	Processing of interrupted getcc selects
58802432Sse**
58812432Sse**--------------------------------------------------------------------
58822432Sse*/
58832432Sse
58842814Sse	case SIR_SENSE_RESTART:
58852814Sse		/*------------------------------------------
58862432Sse		**	Script processor is idle.
58876705Sse		**	Look for interrupted "check cond"
58882435Sse		**------------------------------------------
58892432Sse		*/
58902432Sse
58913552Sse		if (DEBUG_FLAGS & DEBUG_RESTART)
58922435Sse			printf ("%s: int#%d",ncr_name (np),num);
589339247Sgibbs		cp = (nccb_p) 0;
58942432Sse		for (i=0; i<MAX_TARGET; i++) {
58953552Sse			if (DEBUG_FLAGS & DEBUG_RESTART) printf (" t%d", i);
58962432Sse			tp = &np->target[i];
58973552Sse			if (DEBUG_FLAGS & DEBUG_RESTART) printf ("+");
58982432Sse			cp = tp->hold_cp;
58992432Sse			if (!cp) continue;
59003552Sse			if (DEBUG_FLAGS & DEBUG_RESTART) printf ("+");
59012432Sse			if ((cp->host_status==HS_BUSY) &&
590239247Sgibbs				(cp->s_status==SCSI_STATUS_CHECK_COND))
59032432Sse				break;
59043552Sse			if (DEBUG_FLAGS & DEBUG_RESTART) printf ("- (remove)");
590539247Sgibbs			tp->hold_cp = cp = (nccb_p) 0;
59062432Sse		};
59072432Sse
59082432Sse		if (cp) {
59093552Sse			if (DEBUG_FLAGS & DEBUG_RESTART)
59102435Sse				printf ("+ restart job ..\n");
591110677Sse			OUTL (nc_dsa, CCB_PHYS (cp, phys));
591227744Sse			OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, getcc));
59132432Sse			return;
59142432Sse		};
59157228Sse
59162432Sse		/*
59172432Sse		**	no job, resume normal processing
59182432Sse		*/
59193552Sse		if (DEBUG_FLAGS & DEBUG_RESTART) printf (" -- remove trap\n");
592039532Sken		WRITESCRIPT(start0[0], SCR_INT ^ IFFALSE (0));
59212432Sse		break;
59222435Sse
59232814Sse	case SIR_SENSE_FAILED:
59242814Sse		/*-------------------------------------------
59256632Sse		**	While trying to select for
59262432Sse		**	getting the condition code,
59272432Sse		**	a target reselected us.
59282435Sse		**-------------------------------------------
59292432Sse		*/
593010072Sse		if (DEBUG_FLAGS & DEBUG_RESTART) {
593139247Sgibbs			PRINT_ADDR(cp->ccb);
59322435Sse			printf ("in getcc reselect by t%d.\n",
593310605Sse				INB(nc_ssid) & 0x0f);
593410072Sse		}
59352432Sse
59362432Sse		/*
59372432Sse		**	Mark this job
59382432Sse		*/
59392432Sse		cp->host_status = HS_BUSY;
594039247Sgibbs		cp->s_status = SCSI_STATUS_CHECK_COND;
594139247Sgibbs		np->target[cp->ccb->ccb_h.target_id].hold_cp = cp;
59422432Sse
59432432Sse		/*
59442432Sse		**	And patch code to restart it.
59452432Sse		*/
594639532Sken		WRITESCRIPT(start0[0], SCR_INT);
59472432Sse		break;
59487228Sse
59492814Sse/*-----------------------------------------------------------------------------
59502432Sse**
59512814Sse**	Was Sie schon immer ueber transfermode negotiation wissen wollten ...
59522432Sse**
59532814Sse**	We try to negotiate sync and wide transfer only after
59549364Sse**	a successfull inquire command. We look at byte 7 of the
59552814Sse**	inquire data to determine the capabilities if the target.
59562814Sse**
59572814Sse**	When we try to negotiate, we append the negotiation message
59589364Sse**	to the identify and (maybe) simple tag message.
59592814Sse**	The host status field is set to HS_NEGOTIATE to mark this
59602814Sse**	situation.
59612814Sse**
59622814Sse**	If the target doesn't answer this message immidiately
59636705Sse**	(as required by the standard), the SIR_NEGO_FAIL interrupt
59642814Sse**	will be raised eventually.
59652814Sse**	The handler removes the HS_NEGOTIATE status, and sets the
59662814Sse**	negotiated value to the default (async / nowide).
59672814Sse**
59682814Sse**	If we receive a matching answer immediately, we check it
59692814Sse**	for validity, and set the values.
59702814Sse**
59712814Sse**	If we receive a Reject message immediately, we assume the
59729364Sse**	negotiation has failed, and fall back to standard values.
59732814Sse**
59742814Sse**	If we receive a negotiation message while not in HS_NEGOTIATE
59752814Sse**	state, it's a target initiated negotiation. We prepare a
59769364Sse**	(hopefully) valid answer, set our parameters, and send back
59779364Sse**	this answer to the target.
59782814Sse**
59792814Sse**	If the target doesn't fetch the answer (no message out phase),
59809364Sse**	we assume the negotiation has failed, and fall back to default
59819364Sse**	settings.
59822814Sse**
598339247Sgibbs**	When we set the values, we adjust them in all nccbs belonging
59849364Sse**	to this target, in the controller's register, and in the "phys"
59859364Sse**	field of the controller's struct ncb.
59862814Sse**
598710072Sse**	Possible cases:		   hs  sir   msg_in value  send   goto
59882432Sse**	We try try to negotiate:
59892814Sse**	-> target doesnt't msgin   NEG FAIL  noop   defa.  -      dispatch
59902814Sse**	-> target rejected our msg NEG FAIL  reject defa.  -      dispatch
59912814Sse**	-> target answered  (ok)   NEG SYNC  sdtr   set    -      clrack
59922814Sse**	-> target answered (!ok)   NEG SYNC  sdtr   defa.  REJ--->msg_bad
59932814Sse**	-> target answered  (ok)   NEG WIDE  wdtr   set    -      clrack
59942814Sse**	-> target answered (!ok)   NEG WIDE  wdtr   defa.  REJ--->msg_bad
599510072Sse**	-> any other msgin	   NEG FAIL  noop   defa.  -      dispatch
59962432Sse**
59972432Sse**	Target tries to negotiate:
599810072Sse**	-> incoming message	   --- SYNC  sdtr   set    SDTR   -
599910072Sse**	-> incoming message	   --- WIDE  wdtr   set    WDTR   -
60002814Sse**      We sent our answer:
60012814Sse**	-> target doesn't msgout   --- PROTO ?      defa.  -      dispatch
60022432Sse**
60032814Sse**-----------------------------------------------------------------------------
60042432Sse*/
60057228Sse
60062814Sse	case SIR_NEGO_FAILED:
60072814Sse		/*-------------------------------------------------------
60082814Sse		**
60092814Sse		**	Negotiation failed.
60102814Sse		**	Target doesn't send an answer message,
60112814Sse		**	or target rejected our message.
60122814Sse		**
60132814Sse		**      Remove negotiation request.
60142814Sse		**
60152814Sse		**-------------------------------------------------------
60162814Sse		*/
60172814Sse		OUTB (HS_PRT, HS_BUSY);
60182814Sse
6019102412Scharnier		/* FALLTHROUGH */
60202814Sse
60212814Sse	case SIR_NEGO_PROTO:
60222814Sse		/*-------------------------------------------------------
60232814Sse		**
60242814Sse		**	Negotiation failed.
60252814Sse		**	Target doesn't fetch the answer message.
60262814Sse		**
60272814Sse		**-------------------------------------------------------
60282814Sse		*/
60293552Sse
60303552Sse		if (DEBUG_FLAGS & DEBUG_NEGO) {
603139247Sgibbs			PRINT_ADDR(cp->ccb);
60322814Sse			printf ("negotiation failed sir=%x status=%x.\n",
60332814Sse				num, cp->nego_status);
60342814Sse		};
60353552Sse
60362432Sse		/*
60372814Sse		**	any error in negotiation:
60382814Sse		**	fall back to default mode.
60392432Sse		*/
60402814Sse		switch (cp->nego_status) {
60412432Sse
60422814Sse		case NS_SYNC:
604339247Sgibbs			ncr_setsync (np, cp, 0, 0xe0, 0);
60442814Sse			break;
60452814Sse
60462814Sse		case NS_WIDE:
604727684Sse			ncr_setwide (np, cp, 0, 0);
60482814Sse			break;
60492814Sse
60502814Sse		};
605139247Sgibbs		np->msgin [0] = MSG_NOOP;
605239247Sgibbs		np->msgout[0] = MSG_NOOP;
60532814Sse		cp->nego_status = 0;
605410677Sse		OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch));
60552814Sse		break;
60567228Sse
60572814Sse	case SIR_NEGO_SYNC:
60582814Sse		/*
60592814Sse		**	Synchronous request message received.
60602814Sse		*/
60613552Sse
60623552Sse		if (DEBUG_FLAGS & DEBUG_NEGO) {
606339247Sgibbs			PRINT_ADDR(cp->ccb);
60642432Sse			printf ("sync msgin: ");
60652814Sse			(void) ncr_show_msg (np->msgin);
60662432Sse			printf (".\n");
60672432Sse		};
60682432Sse
60692432Sse		/*
60702814Sse		**	get requested values.
60712432Sse		*/
60722432Sse
60732814Sse		chg = 0;
60742432Sse		per = np->msgin[3];
60752432Sse		ofs = np->msgin[4];
60762814Sse		if (ofs==0) per=255;
60772814Sse
60782432Sse		/*
60792814Sse		**	check values against driver limits.
60802432Sse		*/
608127684Sse		if (per < np->minsync)
608227684Sse			{chg = 1; per = np->minsync;}
608339247Sgibbs		if (per < tp->tinfo.user.period)
608439247Sgibbs			{chg = 1; per = tp->tinfo.user.period;}
608539247Sgibbs		if (ofs > tp->tinfo.user.offset)
608639247Sgibbs			{chg = 1; ofs = tp->tinfo.user.offset;}
60872814Sse
60882814Sse		/*
60892814Sse		**	Check against controller limits.
60902814Sse		*/
609127684Sse
609227684Sse		fak	= 7;
609327684Sse		scntl3	= 0;
609417449Sse		if (ofs != 0) {
609527684Sse			ncr_getsync(np, per, &fak, &scntl3);
609627684Sse			if (fak > 7) {
609717449Sse				chg = 1;
609817449Sse				ofs = 0;
609917449Sse			}
610017449Sse		}
610117449Sse		if (ofs == 0) {
610227684Sse			fak	= 7;
610327684Sse			per	= 0;
610427684Sse			scntl3	= 0;
610517449Sse		}
61062432Sse
61073552Sse		if (DEBUG_FLAGS & DEBUG_NEGO) {
610839247Sgibbs			PRINT_ADDR(cp->ccb);
610927684Sse			printf ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n",
611027684Sse				per, scntl3, ofs, fak, chg);
61112432Sse		}
61127228Sse
61132814Sse		if (INB (HS_PRT) == HS_NEGOTIATE) {
61142814Sse			OUTB (HS_PRT, HS_BUSY);
61152814Sse			switch (cp->nego_status) {
61162432Sse
61172814Sse			case NS_SYNC:
61182814Sse				/*
61192814Sse				**      This was an answer message
61202814Sse				*/
61212814Sse				if (chg) {
61222814Sse					/*
61232814Sse					**	Answer wasn't acceptable.
61242814Sse					*/
612539247Sgibbs					ncr_setsync (np, cp, 0, 0xe0, 0);
612610677Sse					OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad));
61272814Sse				} else {
61282814Sse					/*
61292814Sse					**	Answer is ok.
61302814Sse					*/
613139247Sgibbs					ncr_setsync (np,cp,scntl3,(fak<<5)|ofs, per);
613210677Sse					OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack));
61332814Sse				};
61342814Sse				return;
61352432Sse
61362814Sse			case NS_WIDE:
613727684Sse				ncr_setwide (np, cp, 0, 0);
61382814Sse				break;
61392814Sse			};
61402814Sse		};
61412432Sse
61422432Sse		/*
61432814Sse		**	It was a request. Set value and
61442814Sse		**      prepare an answer message
61452432Sse		*/
61462814Sse
614739247Sgibbs		ncr_setsync (np, cp, scntl3, (fak<<5)|ofs, per);
61482432Sse
614939247Sgibbs		np->msgout[0] = MSG_EXTENDED;
61502432Sse		np->msgout[1] = 3;
615139247Sgibbs		np->msgout[2] = MSG_EXT_SDTR;
61522432Sse		np->msgout[3] = per;
61532432Sse		np->msgout[4] = ofs;
61542432Sse
61552814Sse		cp->nego_status = NS_SYNC;
61562814Sse
61573552Sse		if (DEBUG_FLAGS & DEBUG_NEGO) {
615839247Sgibbs			PRINT_ADDR(cp->ccb);
61592432Sse			printf ("sync msgout: ");
616013809Sse			(void) ncr_show_msg (np->msgout);
61612432Sse			printf (".\n");
61622432Sse		}
61639364Sse
61649364Sse		if (!ofs) {
616510677Sse			OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad));
61669364Sse			return;
61679364Sse		}
616839247Sgibbs		np->msgin [0] = MSG_NOOP;
61699364Sse
61702432Sse		break;
61717228Sse
61722814Sse	case SIR_NEGO_WIDE:
61732814Sse		/*
61742814Sse		**	Wide request message received.
61752814Sse		*/
61763552Sse		if (DEBUG_FLAGS & DEBUG_NEGO) {
617739247Sgibbs			PRINT_ADDR(cp->ccb);
61782814Sse			printf ("wide msgin: ");
61792814Sse			(void) ncr_show_msg (np->msgin);
61802814Sse			printf (".\n");
61812814Sse		};
61822432Sse
61832814Sse		/*
61842814Sse		**	get requested values.
61852814Sse		*/
61862432Sse
61872814Sse		chg  = 0;
61882814Sse		wide = np->msgin[3];
61892814Sse
61902814Sse		/*
61912814Sse		**	check values against driver limits.
61922814Sse		*/
61932814Sse
619439247Sgibbs		if (wide > tp->tinfo.user.width)
619539247Sgibbs			{chg = 1; wide = tp->tinfo.user.width;}
61962814Sse
61973552Sse		if (DEBUG_FLAGS & DEBUG_NEGO) {
619839247Sgibbs			PRINT_ADDR(cp->ccb);
61992814Sse			printf ("wide: wide=%d chg=%d.\n", wide, chg);
62002814Sse		}
62017228Sse
62022814Sse		if (INB (HS_PRT) == HS_NEGOTIATE) {
62032814Sse			OUTB (HS_PRT, HS_BUSY);
62042814Sse			switch (cp->nego_status) {
62052814Sse
62062814Sse			case NS_WIDE:
62072814Sse				/*
62082814Sse				**      This was an answer message
62092814Sse				*/
62102814Sse				if (chg) {
62112814Sse					/*
62122814Sse					**	Answer wasn't acceptable.
62132814Sse					*/
621427684Sse					ncr_setwide (np, cp, 0, 1);
621510677Sse					OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad));
62162814Sse				} else {
62172814Sse					/*
62182814Sse					**	Answer is ok.
62192814Sse					*/
622027684Sse					ncr_setwide (np, cp, wide, 1);
622110677Sse					OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack));
62222814Sse				};
62232814Sse				return;
62242814Sse
62252814Sse			case NS_SYNC:
622639247Sgibbs				ncr_setsync (np, cp, 0, 0xe0, 0);
62272814Sse				break;
62282814Sse			};
62292814Sse		};
62302814Sse
62312814Sse		/*
62322814Sse		**	It was a request, set value and
62332814Sse		**      prepare an answer message
62342814Sse		*/
62352814Sse
623627684Sse		ncr_setwide (np, cp, wide, 1);
62372814Sse
623839247Sgibbs		np->msgout[0] = MSG_EXTENDED;
62392814Sse		np->msgout[1] = 2;
624039247Sgibbs		np->msgout[2] = MSG_EXT_WDTR;
62412814Sse		np->msgout[3] = wide;
62422814Sse
624339247Sgibbs		np->msgin [0] = MSG_NOOP;
62442814Sse
62452814Sse		cp->nego_status = NS_WIDE;
62462814Sse
62473552Sse		if (DEBUG_FLAGS & DEBUG_NEGO) {
624839247Sgibbs			PRINT_ADDR(cp->ccb);
62492814Sse			printf ("wide msgout: ");
625013809Sse			(void) ncr_show_msg (np->msgout);
62512814Sse			printf (".\n");
62522814Sse		}
62532814Sse		break;
62547228Sse
62552432Sse/*--------------------------------------------------------------------
62562432Sse**
62572432Sse**	Processing of special messages
62582432Sse**
62592432Sse**--------------------------------------------------------------------
62602432Sse*/
62612432Sse
62622814Sse	case SIR_REJECT_RECEIVED:
62632814Sse		/*-----------------------------------------------
62642814Sse		**
626539247Sgibbs		**	We received a MSG_MESSAGE_REJECT message.
62662814Sse		**
62672814Sse		**-----------------------------------------------
62682432Sse		*/
62692814Sse
627039247Sgibbs		PRINT_ADDR(cp->ccb);
627139247Sgibbs		printf ("MSG_MESSAGE_REJECT received (%x:%x).\n",
62723533Sse			(unsigned)np->lastmsg, np->msgout[0]);
62732432Sse		break;
62742432Sse
62752814Sse	case SIR_REJECT_SENT:
62762814Sse		/*-----------------------------------------------
62772814Sse		**
62782432Sse		**	We received an unknown message
62792814Sse		**
62802814Sse		**-----------------------------------------------
62812432Sse		*/
62822814Sse
628339247Sgibbs		PRINT_ADDR(cp->ccb);
628439247Sgibbs		printf ("MSG_MESSAGE_REJECT sent for ");
62852814Sse		(void) ncr_show_msg (np->msgin);
62862432Sse		printf (".\n");
62872432Sse		break;
62887228Sse
62892432Sse/*--------------------------------------------------------------------
62902432Sse**
62912814Sse**	Processing of special messages
62922814Sse**
62932814Sse**--------------------------------------------------------------------
62942814Sse*/
62952814Sse
62962814Sse	case SIR_IGN_RESIDUE:
62972814Sse		/*-----------------------------------------------
62982814Sse		**
62992814Sse		**	We received an IGNORE RESIDUE message,
63002814Sse		**	which couldn't be handled by the script.
63012814Sse		**
63022814Sse		**-----------------------------------------------
63032814Sse		*/
63042814Sse
630539247Sgibbs		PRINT_ADDR(cp->ccb);
630639247Sgibbs		printf ("MSG_IGN_WIDE_RESIDUE received, but not yet implemented.\n");
63072814Sse		break;
63082814Sse
63092814Sse	case SIR_MISSING_SAVE:
63102814Sse		/*-----------------------------------------------
63112814Sse		**
63122814Sse		**	We received an DISCONNECT message,
63132814Sse		**	but the datapointer wasn't saved before.
63142814Sse		**
63152814Sse		**-----------------------------------------------
63162814Sse		*/
63172814Sse
631839247Sgibbs		PRINT_ADDR(cp->ccb);
631939247Sgibbs		printf ("MSG_DISCONNECT received, but datapointer not saved:\n"
63203533Sse			"\tdata=%x save=%x goal=%x.\n",
63213533Sse			(unsigned) INL (nc_temp),
63223533Sse			(unsigned) np->header.savep,
63233533Sse			(unsigned) np->header.goalp);
63242814Sse		break;
63257228Sse
63262814Sse/*--------------------------------------------------------------------
63272814Sse**
632839247Sgibbs**	Processing of a "SCSI_STATUS_QUEUE_FULL" status.
63292432Sse**
633039247Sgibbs**	XXX JGibbs - We should do the same thing for BUSY status.
633139247Sgibbs**
63322814Sse**	The current command has been rejected,
63332814Sse**	because there are too many in the command queue.
63342432Sse**	We have started too many commands for that target.
63352432Sse**
63362432Sse**--------------------------------------------------------------------
63372432Sse*/
63382814Sse	case SIR_STALL_QUEUE:
633939386Sgibbs		cp->xerr_status = XE_OK;
634039386Sgibbs		cp->host_status = HS_COMPLETE;
634139247Sgibbs		cp->s_status = SCSI_STATUS_QUEUE_FULL;
634239247Sgibbs		ncr_freeze_devq(np, cp->ccb->ccb_h.path);
634339247Sgibbs		ncr_complete(np, cp);
63442432Sse
6345102412Scharnier		/* FALLTHROUGH */
63462432Sse
63472814Sse	case SIR_STALL_RESTART:
63482814Sse		/*-----------------------------------------------
63492814Sse		**
63502814Sse		**	Enable selecting again,
63512814Sse		**	if NO disconnected jobs.
63522814Sse		**
63532814Sse		**-----------------------------------------------
63543043Srgrimes		*/
63552814Sse		/*
63562432Sse		**	Look for a disconnected job.
63572432Sse		*/
635839247Sgibbs		cp = np->link_nccb;
63592432Sse		while (cp && cp->host_status != HS_DISCONNECT)
636039247Sgibbs			cp = cp->link_nccb;
63612432Sse
63622432Sse		/*
63632432Sse		**	if there is one, ...
63642432Sse		*/
63652432Sse		if (cp) {
63662432Sse			/*
63672432Sse			**	wait for reselection
63682432Sse			*/
636910677Sse			OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, reselect));
63702432Sse			return;
63712432Sse		};
63722432Sse
63732432Sse		/*
63746705Sse		**	else remove the interrupt.
63752432Sse		*/
63762432Sse
63772432Sse		printf ("%s: queue empty.\n", ncr_name (np));
637839532Sken		WRITESCRIPT(start1[0], SCR_INT ^ IFFALSE (0));
63792432Sse		break;
63802432Sse	};
63812432Sse
63822432Sseout:
638320435Sse	OUTB (nc_dcntl, np->rv_dcntl | STD);
63842432Sse}
63857228Sse
63862432Sse/*==========================================================
63872432Sse**
63882432Sse**
63892432Sse**	Aquire a control block
63902432Sse**
63912432Sse**
63922432Sse**==========================================================
63932432Sse*/
63942432Sse
639539247Sgibbsstatic	nccb_p ncr_get_nccb
639639247Sgibbs	(ncb_p np, u_long target, u_long lun)
63972432Sse{
63982432Sse	lcb_p lp;
639939247Sgibbs	nccb_p cp = NULL;
64002432Sse
64012432Sse	/*
64022432Sse	**	Lun structure available ?
64032432Sse	*/
64042432Sse
64052432Sse	lp = np->target[target].lp[lun];
640610567Sse	if (lp) {
640739247Sgibbs		cp = lp->next_nccb;
64082432Sse
640910567Sse		/*
641010567Sse		**	Look for free CCB
641110567Sse		*/
64122432Sse
641320435Sse		while (cp && cp->magic) {
641439247Sgibbs			cp = cp->next_nccb;
641520435Sse		}
641610567Sse	}
64172432Sse
64182432Sse	/*
641939247Sgibbs	**	if nothing available, create one.
64202432Sse	*/
64212432Sse
642239247Sgibbs	if (cp == NULL)
642339247Sgibbs		cp = ncr_alloc_nccb(np, target, lun);
64242432Sse
642539247Sgibbs	if (cp != NULL) {
642639247Sgibbs		if (cp->magic) {
642739247Sgibbs			printf("%s: Bogus free cp found\n", ncr_name(np));
642839247Sgibbs			return (NULL);
642939247Sgibbs		}
643039247Sgibbs		cp->magic = 1;
643120435Sse	}
64322432Sse	return (cp);
64332432Sse}
64347228Sse
64352432Sse/*==========================================================
64362432Sse**
64372432Sse**
64382432Sse**	Release one control block
64392432Sse**
64402432Sse**
64412432Sse**==========================================================
64422432Sse*/
64432432Sse
6444105219Sphkstatic void ncr_free_nccb (ncb_p np, nccb_p cp)
64452432Sse{
64462432Sse	/*
64472432Sse	**    sanity
64482432Sse	*/
64492432Sse
645010567Sse	assert (cp != NULL);
64512432Sse
64522432Sse	cp -> host_status = HS_IDLE;
64532432Sse	cp -> magic = 0;
64542432Sse}
64557228Sse
64562432Sse/*==========================================================
64572432Sse**
64582432Sse**
64592432Sse**      Allocation of resources for Targets/Luns/Tags.
64602432Sse**
64612432Sse**
64622432Sse**==========================================================
64632432Sse*/
64642432Sse
646539247Sgibbsstatic nccb_p
646639247Sgibbsncr_alloc_nccb (ncb_p np, u_long target, u_long lun)
64672432Sse{
64682432Sse	tcb_p tp;
64692432Sse	lcb_p lp;
647039247Sgibbs	nccb_p cp;
64712432Sse
647210567Sse	assert (np != NULL);
64732432Sse
647439247Sgibbs	if (target>=MAX_TARGET) return(NULL);
647539247Sgibbs	if (lun   >=MAX_LUN   ) return(NULL);
64762432Sse
64772432Sse	tp=&np->target[target];
64782432Sse
64792432Sse	if (!tp->jump_tcb.l_cmd) {
64802432Sse
64812432Sse		/*
64822432Sse		**	initialize it.
64832432Sse		*/
64842432Sse		tp->jump_tcb.l_cmd   = (SCR_JUMP^IFFALSE (DATA (0x80 + target)));
64852432Sse		tp->jump_tcb.l_paddr = np->jump_tcb.l_paddr;
64862432Sse
648727684Sse		tp->getscr[0] =
648827684Sse			(np->features & FE_PFEN)? SCR_COPY(1) : SCR_COPY_F(1);
648939247Sgibbs		tp->getscr[1] = vtophys (&tp->tinfo.sval);
649060974Sdfr		tp->getscr[2] = rman_get_start(np->reg_res) + offsetof (struct ncr_reg, nc_sxfer);
649127684Sse		tp->getscr[3] =
649227684Sse			(np->features & FE_PFEN)? SCR_COPY(1) : SCR_COPY_F(1);
649339247Sgibbs		tp->getscr[4] = vtophys (&tp->tinfo.wval);
649460974Sdfr		tp->getscr[5] = rman_get_start(np->reg_res) + offsetof (struct ncr_reg, nc_scntl3);
64952432Sse
649639247Sgibbs		assert (((offsetof(struct ncr_reg, nc_sxfer) ^
649739247Sgibbs			 (offsetof(struct tcb ,tinfo)
649839247Sgibbs			+ offsetof(struct ncr_target_tinfo, sval))) & 3) == 0);
649939247Sgibbs		assert (((offsetof(struct ncr_reg, nc_scntl3) ^
650039247Sgibbs			 (offsetof(struct tcb, tinfo)
650139247Sgibbs			+ offsetof(struct ncr_target_tinfo, wval))) &3) == 0);
65022432Sse
65032432Sse		tp->call_lun.l_cmd   = (SCR_CALL);
650410677Sse		tp->call_lun.l_paddr = NCB_SCRIPT_PHYS (np, resel_lun);
65052432Sse
65062432Sse		tp->jump_lcb.l_cmd   = (SCR_JUMP);
650727744Sse		tp->jump_lcb.l_paddr = NCB_SCRIPTH_PHYS (np, abort);
65082432Sse		np->jump_tcb.l_paddr = vtophys (&tp->jump_tcb);
65092432Sse	}
65107228Sse
65112432Sse	/*
65122432Sse	**	Logic unit control block
65132432Sse	*/
65142432Sse	lp = tp->lp[lun];
65152432Sse	if (!lp) {
65162432Sse		/*
65172432Sse		**	Allocate a lcb
65182432Sse		*/
651969781Sdwmalone		lp = (lcb_p) malloc (sizeof (struct lcb), M_DEVBUF,
652069781Sdwmalone			M_NOWAIT | M_ZERO);
652139247Sgibbs		if (!lp) return(NULL);
65222432Sse
65232432Sse		/*
65242432Sse		**	Initialize it
65252432Sse		*/
65262432Sse		lp->jump_lcb.l_cmd   = (SCR_JUMP ^ IFFALSE (DATA (lun)));
65272432Sse		lp->jump_lcb.l_paddr = tp->jump_lcb.l_paddr;
65282432Sse
65292432Sse		lp->call_tag.l_cmd   = (SCR_CALL);
653010677Sse		lp->call_tag.l_paddr = NCB_SCRIPT_PHYS (np, resel_tag);
65312432Sse
653239247Sgibbs		lp->jump_nccb.l_cmd   = (SCR_JUMP);
653339247Sgibbs		lp->jump_nccb.l_paddr = NCB_SCRIPTH_PHYS (np, aborttag);
65342432Sse
65352432Sse		lp->actlink = 1;
65369364Sse
65372432Sse		/*
65389364Sse		**   Chain into LUN list
65392432Sse		*/
65402432Sse		tp->jump_lcb.l_paddr = vtophys (&lp->jump_lcb);
65412432Sse		tp->lp[lun] = lp;
65422432Sse
65432432Sse	}
65442432Sse
65452432Sse	/*
654639247Sgibbs	**	Allocate a nccb
65472432Sse	*/
654869781Sdwmalone	cp = (nccb_p) malloc (sizeof (struct nccb), M_DEVBUF, M_NOWAIT|M_ZERO);
65492432Sse
65502432Sse	if (!cp)
655139247Sgibbs		return (NULL);
65522432Sse
655339247Sgibbs	if (DEBUG_FLAGS & DEBUG_ALLOC) {
655439532Sken		printf ("new nccb @%p.\n", cp);
65552432Sse	}
65562432Sse
65572432Sse	/*
655810639Sse	**	Fill in physical addresses
655910639Sse	*/
656010639Sse
656139247Sgibbs	cp->p_nccb	     = vtophys (cp);
656210639Sse
656310639Sse	/*
65649364Sse	**	Chain into reselect list
65652432Sse	*/
656639247Sgibbs	cp->jump_nccb.l_cmd   = SCR_JUMP;
656739247Sgibbs	cp->jump_nccb.l_paddr = lp->jump_nccb.l_paddr;
656839247Sgibbs	lp->jump_nccb.l_paddr = CCB_PHYS (cp, jump_nccb);
65692432Sse	cp->call_tmp.l_cmd   = SCR_CALL;
657010677Sse	cp->call_tmp.l_paddr = NCB_SCRIPT_PHYS (np, resel_tmp);
65712432Sse
65722432Sse	/*
65739364Sse	**	Chain into wakeup list
65742432Sse	*/
657539247Sgibbs	cp->link_nccb      = np->link_nccb;
657639247Sgibbs	np->link_nccb	   = cp;
65772432Sse
65782432Sse	/*
65799364Sse	**	Chain into CCB list
65802432Sse	*/
658139247Sgibbs	cp->next_nccb	= lp->next_nccb;
658239247Sgibbs	lp->next_nccb	= cp;
65837228Sse
658439247Sgibbs	return (cp);
65852432Sse}
65867228Sse
65872432Sse/*==========================================================
65882432Sse**
65892432Sse**
65902432Sse**	Build Scatter Gather Block
65912432Sse**
65922432Sse**
65932432Sse**==========================================================
65942432Sse**
65952432Sse**	The transfer area may be scattered among
65962432Sse**	several non adjacent physical pages.
65972432Sse**
65982432Sse**	We may use MAX_SCATTER blocks.
65992432Sse**
66002432Sse**----------------------------------------------------------
66012432Sse*/
66022432Sse
66032814Ssestatic	int	ncr_scatter
66042432Sse	(struct dsb* phys, vm_offset_t vaddr, vm_size_t datalen)
66052432Sse{
66062432Sse	u_long	paddr, pnext;
66072432Sse
66082432Sse	u_short	segment  = 0;
66092432Sse	u_long	segsize, segaddr;
66102432Sse	u_long	size, csize    = 0;
66112432Sse	u_long	chunk = MAX_SIZE;
66122432Sse	int	free;
66132432Sse
66142432Sse	bzero (&phys->data, sizeof (phys->data));
66152432Sse	if (!datalen) return (0);
66162432Sse
66172432Sse	paddr = vtophys (vaddr);
66182432Sse
66192432Sse	/*
66202432Sse	**	insert extra break points at a distance of chunk.
662110567Sse	**	We try to reduce the number of interrupts caused
662210567Sse	**	by unexpected phase changes due to disconnects.
66232432Sse	**	A typical harddisk may disconnect before ANY block.
662410567Sse	**	If we wanted to avoid unexpected phase changes at all
662510567Sse	**	we had to use a break point every 512 bytes.
66262432Sse	**	Of course the number of scatter/gather blocks is
66272432Sse	**	limited.
66282432Sse	*/
66292432Sse
66302432Sse	free = MAX_SCATTER - 1;
66312432Sse
663215583Sphk	if (vaddr & PAGE_MASK) free -= datalen / PAGE_SIZE;
66332432Sse
66342432Sse	if (free>1)
66352432Sse		while ((chunk * free >= 2 * datalen) && (chunk>=1024))
66362432Sse			chunk /= 2;
66372432Sse
66383552Sse	if(DEBUG_FLAGS & DEBUG_SCATTER)
663939532Sken		printf("ncr?:\tscattering virtual=%p size=%d chunk=%d.\n",
664039532Sken		       (void *) vaddr, (unsigned) datalen, (unsigned) chunk);
66417228Sse
66422432Sse	/*
66432432Sse	**   Build data descriptors.
66442432Sse	*/
66452432Sse	while (datalen && (segment < MAX_SCATTER)) {
66462432Sse
66472432Sse		/*
66482432Sse		**	this segment is empty
66492432Sse		*/
66502432Sse		segsize = 0;
66512432Sse		segaddr = paddr;
66522432Sse		pnext   = paddr;
66532432Sse
66542432Sse		if (!csize) csize = chunk;
66552432Sse
66562432Sse		while ((datalen) && (paddr == pnext) && (csize)) {
66572432Sse
66582432Sse			/*
66592432Sse			**	continue this segment
66602432Sse			*/
666115583Sphk			pnext = (paddr & (~PAGE_MASK)) + PAGE_SIZE;
66622432Sse
66632432Sse			/*
66642432Sse			**	Compute max size
66652432Sse			*/
66662432Sse
66677228Sse			size = pnext - paddr;		/* page size */
66682432Sse			if (size > datalen) size = datalen;  /* data size */
66692432Sse			if (size > csize  ) size = csize  ;  /* chunksize */
66702432Sse
66712432Sse			segsize += size;
66722432Sse			vaddr   += size;
66732432Sse			csize   -= size;
66742432Sse			datalen -= size;
66752432Sse			paddr    = vtophys (vaddr);
66762432Sse		};
66772432Sse
66783552Sse		if(DEBUG_FLAGS & DEBUG_SCATTER)
66792432Sse			printf ("\tseg #%d  addr=%x  size=%d  (rest=%d).\n",
66803533Sse			segment,
66813533Sse			(unsigned) segaddr,
66823533Sse			(unsigned) segsize,
66833533Sse			(unsigned) datalen);
66842432Sse
66852432Sse		phys->data[segment].addr = segaddr;
66862432Sse		phys->data[segment].size = segsize;
66872432Sse		segment++;
66882432Sse	}
66892432Sse
66902814Sse	if (datalen) {
66912432Sse		printf("ncr?: scatter/gather failed (residue=%d).\n",
66923533Sse			(unsigned) datalen);
66932814Sse		return (-1);
66942814Sse	};
66952432Sse
66962814Sse	return (segment);
66972432Sse}
66987228Sse
66992432Sse/*==========================================================
67002432Sse**
67012432Sse**
67023166Sse**	Test the pci bus snoop logic :-(
67033166Sse**
67046705Sse**	Has to be called with interrupts disabled.
67053166Sse**
67063166Sse**
67073166Sse**==========================================================
67083166Sse*/
67093166Sse
67106401Sse#ifndef NCR_IOMAPPED
67116398Ssestatic int ncr_regtest (struct ncb* np)
67126398Sse{
671339532Sken	register volatile u_int32_t data;
67146398Sse	/*
67156398Sse	**	ncr registers may NOT be cached.
67166398Sse	**	write 0xffffffff to a read only register area,
67176398Sse	**	and try to read it back.
67186398Sse	*/
67196398Sse	data = 0xffffffff;
672039532Sken	OUTL_OFF(offsetof(struct ncr_reg, nc_dstat), data);
672139532Sken	data = INL_OFF(offsetof(struct ncr_reg, nc_dstat));
67226398Sse#if 1
67236398Sse	if (data == 0xffffffff) {
67246398Sse#else
67256398Sse	if ((data & 0xe2f0fffd) != 0x02000080) {
67266398Sse#endif
67276398Sse		printf ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n",
67286398Sse			(unsigned) data);
67296398Sse		return (0x10);
67306398Sse	};
67316398Sse	return (0);
67326401Sse}
67336398Sse#endif
67346398Sse
67353166Ssestatic int ncr_snooptest (struct ncb* np)
67363166Sse{
673728960Sse	u_int32_t ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc;
673828960Sse	int	i, err=0;
67396398Sse#ifndef NCR_IOMAPPED
67406398Sse	err |= ncr_regtest (np);
67416398Sse	if (err) return (err);
67426398Sse#endif
67433166Sse	/*
67443166Sse	**	init
67453166Sse	*/
674627744Sse	pc  = NCB_SCRIPTH_PHYS (np, snooptest);
67473166Sse	host_wr = 1;
67483166Sse	ncr_wr  = 2;
67493166Sse	/*
67503166Sse	**	Set memory and register.
67513166Sse	*/
67523166Sse	ncr_cache = host_wr;
67533166Sse	OUTL (nc_temp, ncr_wr);
67543166Sse	/*
67553166Sse	**	Start script (exchange values)
67563166Sse	*/
67573166Sse	OUTL (nc_dsp, pc);
67583166Sse	/*
67596526Sse	**	Wait 'til done (with timeout)
67603166Sse	*/
67616526Sse	for (i=0; i<NCR_SNOOP_TIMEOUT; i++)
67626526Sse		if (INB(nc_istat) & (INTF|SIP|DIP))
67636526Sse			break;
67643166Sse	/*
67656526Sse	**	Save termination position.
67666526Sse	*/
67676526Sse	pc = INL (nc_dsp);
67686526Sse	/*
67693166Sse	**	Read memory and register.
67703166Sse	*/
67713166Sse	host_rd = ncr_cache;
67723166Sse	ncr_rd  = INL (nc_scratcha);
67733166Sse	ncr_bk  = INL (nc_temp);
67743166Sse	/*
67753166Sse	**	Reset ncr chip
67763166Sse	*/
67773166Sse	OUTB (nc_istat,  SRST);
677810605Sse	DELAY (1000);
67793166Sse	OUTB (nc_istat,  0   );
67803166Sse	/*
67816526Sse	**	check for timeout
67826526Sse	*/
67836526Sse	if (i>=NCR_SNOOP_TIMEOUT) {
67846526Sse		printf ("CACHE TEST FAILED: timeout.\n");
67856526Sse		return (0x20);
67866526Sse	};
67876526Sse	/*
67886526Sse	**	Check termination position.
67896526Sse	*/
679027744Sse	if (pc != NCB_SCRIPTH_PHYS (np, snoopend)+8) {
67916526Sse		printf ("CACHE TEST FAILED: script execution failed.\n");
679228960Sse		printf ("start=%08lx, pc=%08lx, end=%08lx\n",
679328960Sse			(u_long) NCB_SCRIPTH_PHYS (np, snooptest), (u_long) pc,
679428960Sse			(u_long) NCB_SCRIPTH_PHYS (np, snoopend) +8);
67956526Sse		return (0x40);
67966526Sse	};
67976526Sse	/*
67983166Sse	**	Show results.
67993166Sse	*/
68003166Sse	if (host_wr != ncr_rd) {
68013166Sse		printf ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n",
68023533Sse			(int) host_wr, (int) ncr_rd);
68033166Sse		err |= 1;
68043166Sse	};
68053166Sse	if (host_rd != ncr_wr) {
68063166Sse		printf ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n",
68073533Sse			(int) ncr_wr, (int) host_rd);
68083166Sse		err |= 2;
68093166Sse	};
68103166Sse	if (ncr_bk != ncr_wr) {
68113166Sse		printf ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n",
68123533Sse			(int) ncr_wr, (int) ncr_bk);
68133166Sse		err |= 4;
68143166Sse	};
68153166Sse	return (err);
68163166Sse}
68177228Sse
68183166Sse/*==========================================================
68193166Sse**
68203166Sse**
68212432Sse**	Profiling the drivers and targets performance.
68222432Sse**
68232432Sse**
68242432Sse**==========================================================
68252432Sse*/
68262432Sse
68272432Sse/*
68282432Sse**	Compute the difference in milliseconds.
68292432Sse**/
68302432Sse
683134961Sphkstatic	int ncr_delta (int *from, int *to)
68322432Sse{
683334961Sphk	if (!from) return (-1);
683434961Sphk	if (!to)   return (-2);
683534961Sphk	return ((to - from) * 1000 / hz);
68362432Sse}
68377228Sse
68382432Sse#define PROFILE  cp->phys.header.stamp
683939247Sgibbsstatic	void ncb_profile (ncb_p np, nccb_p cp)
68402432Sse{
68412432Sse	int co, da, st, en, di, se, post,work,disc;
68422432Sse	u_long diff;
68432432Sse
684434961Sphk	PROFILE.end = ticks;
68452432Sse
68462432Sse	st = ncr_delta (&PROFILE.start,&PROFILE.status);
68472432Sse	if (st<0) return;	/* status  not reached  */
68482432Sse
68492432Sse	da = ncr_delta (&PROFILE.start,&PROFILE.data);
68502432Sse	if (da<0) return;	/* No data transfer phase */
68512432Sse
68522432Sse	co = ncr_delta (&PROFILE.start,&PROFILE.command);
68532432Sse	if (co<0) return;	/* command not executed */
68542432Sse
68552432Sse	en = ncr_delta (&PROFILE.start,&PROFILE.end),
68562432Sse	di = ncr_delta (&PROFILE.start,&PROFILE.disconnect),
68572432Sse	se = ncr_delta (&PROFILE.start,&PROFILE.select);
68582432Sse	post = en - st;
68592432Sse
68602432Sse	/*
68612432Sse	**	@PROFILE@  Disconnect time invalid if multiple disconnects
68622432Sse	*/
68632432Sse
68642432Sse	if (di>=0) disc = se-di; else  disc = 0;
68652432Sse
68662432Sse	work = (st - co) - disc;
68672432Sse
68682432Sse	diff = (np->disc_phys - np->disc_ref) & 0xff;
68692432Sse	np->disc_ref += diff;
68702432Sse
68712432Sse	np->profile.num_trans	+= 1;
687239247Sgibbs	if (cp->ccb)
687339247Sgibbs		np->profile.num_bytes	+= cp->ccb->csio.dxfer_len;
68742432Sse	np->profile.num_disc	+= diff;
68752432Sse	np->profile.ms_setup	+= co;
68762432Sse	np->profile.ms_data	+= work;
68772432Sse	np->profile.ms_disc	+= disc;
68782432Sse	np->profile.ms_post	+= post;
68792432Sse}
68802432Sse#undef PROFILE
68817228Sse
68822432Sse/*==========================================================
68832432Sse**
68842432Sse**	Determine the ncr's clock frequency.
688527684Sse**	This is essential for the negotiation
68862432Sse**	of the synchronous transfer rate.
68872432Sse**
68882432Sse**==========================================================
68892432Sse**
68902432Sse**	Note: we have to return the correct value.
68912432Sse**	THERE IS NO SAVE DEFAULT VALUE.
68922432Sse**
689327684Sse**	Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock.
689427684Sse**	53C860 and 53C875 rev. 1 support fast20 transfers but
689527684Sse**	do not have a clock doubler and so are provided with a
689627684Sse**	80 MHz clock. All other fast20 boards incorporate a doubler
689727684Sse**	and so should be delivered with a 40 MHz clock.
689827684Sse**	The future fast40 chips (895/895) use a 40 Mhz base clock
689927684Sse**	and provide a clock quadrupler (160 Mhz). The code below
690027684Sse**	tries to deal as cleverly as possible with all this stuff.
69012432Sse**
69022432Sse**----------------------------------------------------------
69032432Sse*/
69042432Sse
690527684Sse/*
690627684Sse *	Select NCR SCSI clock frequency
690727684Sse */
690827684Ssestatic void ncr_selectclock(ncb_p np, u_char scntl3)
690927684Sse{
691027684Sse	if (np->multiplier < 2) {
691127684Sse		OUTB(nc_scntl3,	scntl3);
691227684Sse		return;
691327684Sse	}
69142432Sse
691527684Sse	if (bootverbose >= 2)
691627684Sse		printf ("%s: enabling clock multiplier\n", ncr_name(np));
691727684Sse
691827684Sse	OUTB(nc_stest1, DBLEN);	   /* Enable clock multiplier		  */
691927684Sse	if (np->multiplier > 2) {  /* Poll bit 5 of stest4 for quadrupler */
692027684Sse		int i = 20;
692127684Sse		while (!(INB(nc_stest4) & LCKFRQ) && --i > 0)
692227684Sse			DELAY(20);
692327684Sse		if (!i)
692427684Sse			printf("%s: the chip cannot lock the frequency\n", ncr_name(np));
692527684Sse	} else			/* Wait 20 micro-seconds for doubler	*/
692627684Sse		DELAY(20);
692727684Sse	OUTB(nc_stest3, HSC);		/* Halt the scsi clock		*/
692827684Sse	OUTB(nc_scntl3,	scntl3);
692927684Sse	OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier	*/
693027684Sse	OUTB(nc_stest3, 0x00);		/* Restart scsi clock 		*/
693127684Sse}
693227684Sse
693318875Sse/*
693418875Sse *	calculate NCR SCSI clock frequency (in KHz)
693518875Sse */
693618875Ssestatic unsigned
693718875Ssencrgetfreq (ncb_p np, int gen)
69382432Sse{
693918875Sse	int ms = 0;
69402432Sse	/*
694118875Sse	 * Measure GEN timer delay in order
694218875Sse	 * to calculate SCSI clock frequency
694318875Sse	 *
694418875Sse	 * This code will never execute too
694518875Sse	 * many loop iterations (if DELAY is
694618875Sse	 * reasonably correct). It could get
694718875Sse	 * too low a delay (too high a freq.)
694818875Sse	 * if the CPU is slow executing the
694918875Sse	 * loop for some reason (an NMI, for
695018875Sse	 * example). For this reason we will
695118875Sse	 * if multiple measurements are to be
695218875Sse	 * performed trust the higher delay
695318875Sse	 * (lower frequency returned).
695418875Sse	 */
695518875Sse	OUTB (nc_stest1, 0);	/* make sure clock doubler is OFF	    */
695618875Sse	OUTW (nc_sien , 0);	/* mask all scsi interrupts		    */
695718875Sse	(void) INW (nc_sist);	/* clear pending scsi interrupt		    */
695818875Sse	OUTB (nc_dien , 0);	/* mask all dma interrupts		    */
695918875Sse	(void) INW (nc_sist);	/* another one, just to be sure :)	    */
696018875Sse	OUTB (nc_scntl3, 4);	/* set pre-scaler to divide by 3	    */
696118875Sse	OUTB (nc_stime1, 0);	/* disable general purpose timer	    */
696218875Sse	OUTB (nc_stime1, gen);	/* set to nominal delay of (1<<gen) * 125us */
696318875Sse	while (!(INW(nc_sist) & GEN) && ms++ < 1000)
696418875Sse		DELAY(1000);	/* count ms				    */
696518875Sse	OUTB (nc_stime1, 0);	/* disable general purpose timer	    */
696618875Sse	OUTB (nc_scntl3, 0);
696718875Sse	/*
696818875Sse	 * Set prescaler to divide by whatever "0" means.
696918875Sse	 * "0" ought to choose divide by 2, but appears
697018875Sse	 * to set divide by 3.5 mode in my 53c810 ...
697118875Sse	 */
697218875Sse	OUTB (nc_scntl3, 0);
69732432Sse
697427744Sse	if (bootverbose >= 2)
697539310Sgibbs	  	printf ("\tDelay (GEN=%d): %u msec\n", gen, ms);
697617836Sse	/*
697718875Sse	 * adjust for prescaler, and convert into KHz
697817836Sse	 */
697918875Sse	return ms ? ((1 << gen) * 4440) / ms : 0;
698018875Sse}
698117836Sse
698227684Ssestatic void ncr_getclock (ncb_p np, u_char multiplier)
698318875Sse{
698418875Sse	unsigned char scntl3;
698518875Sse	unsigned char stest1;
698618875Sse	scntl3 = INB(nc_scntl3);
698718875Sse	stest1 = INB(nc_stest1);
698818875Sse
698927684Sse	np->multiplier = 1;
699046581Sken
699146581Sken	if (multiplier > 1) {
699227684Sse		np->multiplier	= multiplier;
699327684Sse		np->clock_khz	= 40000 * multiplier;
699418875Sse	} else {
699518875Sse		if ((scntl3 & 7) == 0) {
699618875Sse			unsigned f1, f2;
699718875Sse			/* throw away first result */
699818875Sse			(void) ncrgetfreq (np, 11);
699918875Sse			f1 = ncrgetfreq (np, 11);
700018875Sse			f2 = ncrgetfreq (np, 11);
700118875Sse
700227744Sse			if (bootverbose >= 2)
700339310Sgibbs			  printf ("\tNCR clock is %uKHz, %uKHz\n", f1, f2);
700418875Sse			if (f1 > f2) f1 = f2;	/* trust lower result	*/
700518875Sse			if (f1 > 45000) {
700618875Sse				scntl3 = 5;	/* >45Mhz: assume 80MHz	*/
700718875Sse			} else {
700818875Sse				scntl3 = 3;	/* <45Mhz: assume 40MHz	*/
700918875Sse			}
701018875Sse		}
701127684Sse		else if ((scntl3 & 7) == 5)
701227684Sse			np->clock_khz = 80000;	/* Probably a 875 rev. 1 ? */
701317850Sse	}
70142432Sse}
70152432Sse
70162432Sse/*=========================================================================*/
701720435Sse
701820435Sse#ifdef NCR_TEKRAM_EEPROM
701920435Sse
702020435Ssestruct tekram_eeprom_dev {
702120435Sse  u_char	devmode;
702220435Sse#define	TKR_PARCHK	0x01
702320435Sse#define	TKR_TRYSYNC	0x02
702420435Sse#define	TKR_ENDISC	0x04
702520435Sse#define	TKR_STARTUNIT	0x08
702620435Sse#define	TKR_USETAGS	0x10
702720435Sse#define	TKR_TRYWIDE	0x20
702820435Sse  u_char	syncparam;	/* max. sync transfer rate (table ?) */
702920435Sse  u_char	filler1;
703020435Sse  u_char	filler2;
703120435Sse};
703220435Sse
703320435Sse
703420435Ssestruct tekram_eeprom {
703520435Sse  struct tekram_eeprom_dev
703620435Sse		dev[16];
703720435Sse  u_char	adaptid;
703820435Sse  u_char	adaptmode;
703920435Sse#define	TKR_ADPT_GT2DRV	0x01
704020435Sse#define	TKR_ADPT_GT1GB	0x02
704120435Sse#define	TKR_ADPT_RSTBUS	0x04
704220435Sse#define	TKR_ADPT_ACTNEG	0x08
704320435Sse#define	TKR_ADPT_NOSEEK	0x10
704420435Sse#define	TKR_ADPT_MORLUN	0x20
704542155Shoek  u_char	delay;		/* unit ? ( table ??? ) */
704620435Sse  u_char	tags;		/* use 4 times as many ... */
704720435Sse  u_char	filler[60];
704820435Sse};
704920435Sse
705020435Ssestatic void
705120435Ssetekram_write_bit (ncb_p np, int bit)
705220435Sse{
705320435Sse	u_char val = 0x10 + ((bit & 1) << 1);
705420435Sse
705520435Sse	DELAY(10);
705620435Sse	OUTB (nc_gpreg, val);
705720435Sse	DELAY(10);
705820435Sse	OUTB (nc_gpreg, val | 0x04);
705920435Sse	DELAY(10);
706020435Sse	OUTB (nc_gpreg, val);
706120435Sse	DELAY(10);
706220435Sse}
706320435Sse
706420435Ssestatic int
706520435Ssetekram_read_bit (ncb_p np)
706620435Sse{
706720435Sse	OUTB (nc_gpreg, 0x10);
706820435Sse	DELAY(10);
706920435Sse	OUTB (nc_gpreg, 0x14);
707020435Sse	DELAY(10);
707120435Sse	return INB (nc_gpreg) & 1;
707220435Sse}
707320435Sse
707420435Ssestatic u_short
707520435Sseread_tekram_eeprom_reg (ncb_p np, int reg)
707620435Sse{
707720435Sse	int bit;
707820435Sse	u_short result = 0;
707920435Sse	int cmd = 0x80 | reg;
708020435Sse
708120435Sse	OUTB (nc_gpreg, 0x10);
708220435Sse
708320435Sse	tekram_write_bit (np, 1);
708420435Sse	for (bit = 7; bit >= 0; bit--)
708520435Sse	{
708620435Sse		tekram_write_bit (np, cmd >> bit);
708720435Sse	}
708820435Sse
708920435Sse	for (bit = 0; bit < 16; bit++)
709020435Sse	{
709120435Sse		result <<= 1;
709220435Sse		result |= tekram_read_bit (np);
709320435Sse	}
709420435Sse
709520435Sse	OUTB (nc_gpreg, 0x00);
709620435Sse	return result;
709720435Sse}
709820435Sse
709920435Ssestatic int
710020435Sseread_tekram_eeprom(ncb_p np, struct tekram_eeprom *buffer)
710120435Sse{
710220435Sse	u_short *p = (u_short *) buffer;
710320435Sse	u_short sum = 0;
710420435Sse	int i;
710520435Sse
710620435Sse	if (INB (nc_gpcntl) != 0x09)
710720435Sse	{
710820435Sse		return 0;
710920435Sse        }
711020435Sse	for (i = 0; i < 64; i++)
711120435Sse	{
711220435Sse		u_short val;
711320435Sseif((i&0x0f) == 0) printf ("%02x:", i*2);
711420435Sse		val = read_tekram_eeprom_reg (np, i);
711520435Sse		if (p)
711620435Sse			*p++ = val;
711720435Sse		sum += val;
711820435Sseif((i&0x01) == 0x00) printf (" ");
711920435Sse		printf ("%02x%02x", val & 0xff, (val >> 8) & 0xff);
712020435Sseif((i&0x0f) == 0x0f) printf ("\n");
712120435Sse	}
712220435Sseprintf ("Sum = %04x\n", sum);
712320435Sse	return sum == 0x1234;
712420435Sse}
712520435Sse#endif /* NCR_TEKRAM_EEPROM */
712620435Sse
712760974Sdfrstatic device_method_t ncr_methods[] = {
712860974Sdfr	/* Device interface */
712960974Sdfr	DEVMETHOD(device_probe,		ncr_probe),
713060974Sdfr	DEVMETHOD(device_attach,	ncr_attach),
713160974Sdfr
713260974Sdfr	{ 0, 0 }
713360974Sdfr};
713460974Sdfr
713560974Sdfrstatic driver_t ncr_driver = {
713660974Sdfr	"ncr",
713760974Sdfr	ncr_methods,
713860974Sdfr	sizeof(struct ncb),
713960974Sdfr};
714060974Sdfr
714160974Sdfrstatic devclass_t ncr_devclass;
714260974Sdfr
7143113506SmdoddDRIVER_MODULE(ncr, pci, ncr_driver, ncr_devclass, 0, 0);
7144135043SseMODULE_DEPEND(ncr, cam, 1, 1, 1);
7145113506SmdoddMODULE_DEPEND(ncr, pci, 1, 1, 1);
714660974Sdfr
714720435Sse/*=========================================================================*/
714855206Speter#endif /* _KERNEL */
7149