1105059Scognet/*
2111158Scognet *      O.S   : FreeBSD CAM
3105059Scognet *	FILE NAME  : trm.c
4105059Scognet *	     BY    : C.L. Huang 	(ching@tekram.com.tw)
5111158Scognet *                   Erich Chen     (erich@tekram.com.tw)
6111158Scognet *      Description: Device Driver for Tekram SCSI adapters
7111158Scognet *                   DC395U/UW/F ,DC315/U(TRM-S1040)
8111158Scognet *                   DC395U2D/U2W(TRM-S2080)
9111158Scognet *                   PCI SCSI Bus Master Host Adapter
10111158Scognet *                   (SCSI chip set used Tekram ASIC TRM-S1040,TRM-S2080)
11105059Scognet */
12105059Scognet
13119418Sobrien#include <sys/cdefs.h>
14119418Sobrien__FBSDID("$FreeBSD$");
15119418Sobrien
16105059Scognet/*
17105059Scognet *	HISTORY:
18105059Scognet *
19105059Scognet *	REV#	DATE	NAME    	DESCRIPTION
20105059Scognet *  1.05   05/01/1999  ERICH CHEN  First released for 3.x.x (CAM)
21105059Scognet *  1.06   07/29/1999  ERICH CHEN  Modify for NEW PCI
22105059Scognet *  1.07   12/12/1999  ERICH CHEN  Modify for 3.3.x ,DCB no free
23105059Scognet *  1.08   06/12/2000  ERICH CHEN  Modify for 4.x.x
24111158Scognet *  1.09   11/03/2000  ERICH CHEN  Modify for 4.1.R ,new sim
25111158Scognet *  1.10   10/10/2001  Oscar Feng  Fixed CAM rescan hang up bug.
26111158Scognet *  1.11   10/13/2001  Oscar Feng  Fixed wrong Async speed display bug.
27105059Scognet */
28105059Scognet
29139749Simp/*-
30139749Simp * (C)Copyright 1995-2001 Tekram Technology Co.,Ltd.
31105059Scognet *
32105059Scognet * Redistribution and use in source and binary forms, with or without
33105059Scognet * modification, are permitted provided that the following conditions
34105059Scognet * are met:
35105059Scognet * 1. Redistributions of source code must retain the above copyright
36105059Scognet *    notice, this list of conditions and the following disclaimer.
37105059Scognet * 2. Redistributions in binary form must reproduce the above copyright
38105059Scognet *    notice, this list of conditions and the following disclaimer in the
39105059Scognet *    documentation and/or other materials provided with the distribution.
40105059Scognet * 3. The name of the author may not be used to endorse or promote products
41105059Scognet *    derived from this software without specific prior written permission.
42105059Scognet *
43105059Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
44105059Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
45105059Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
46105059Scognet * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
47105059Scognet * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
48105059Scognet * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49105059Scognet * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50105059Scognet * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51105059Scognet * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
52105059Scognet * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53105059Scognet *
54105059Scognet */
55105059Scognet
56105059Scognet/*
57105059Scognet * Imported into FreeBSD source repository, and updated to compile under
58105059Scognet * FreeBSD-3.0-DEVELOPMENT, by Stefan Esser <se@FreeBSD.Org>, 1996-12-17
59105059Scognet */
60105059Scognet
61105059Scognet/*
62105059Scognet * Updated to compile under FreeBSD 5.0-CURRENT by Olivier Houchard
63105059Scognet * <doginou@ci0.org>, 2002-03-04
64105059Scognet */
65105059Scognet
66105059Scognet#include <sys/param.h>
67105059Scognet
68105059Scognet#include <sys/systm.h>
69105059Scognet#include <sys/malloc.h>
70105059Scognet#include <sys/queue.h>
71105059Scognet#if __FreeBSD_version >= 500000
72105059Scognet#include <sys/bio.h>
73105059Scognet#endif
74105059Scognet#include <sys/buf.h>
75105059Scognet#include <sys/bus.h>
76105059Scognet#include <sys/kernel.h>
77129879Sphk#include <sys/module.h>
78105059Scognet
79105059Scognet#include <vm/vm.h>
80105059Scognet#include <vm/pmap.h>
81105059Scognet
82119287Simp#include <dev/pci/pcivar.h>
83119287Simp#include <dev/pci/pcireg.h>
84105059Scognet#include <machine/resource.h>
85105059Scognet#include <machine/bus.h>
86105059Scognet#include <sys/rman.h>
87105059Scognet
88105059Scognet#include <cam/cam.h>
89105059Scognet#include <cam/cam_ccb.h>
90105059Scognet#include <cam/cam_sim.h>
91105059Scognet#include <cam/cam_xpt_sim.h>
92105059Scognet#include <cam/cam_debug.h>
93105059Scognet
94105059Scognet#include <cam/scsi/scsi_all.h>
95111158Scognet#include <cam/scsi/scsi_message.h>
96105059Scognet
97105059Scognet#include <dev/trm/trm.h>
98105059Scognet
99105059Scognet#define trm_reg_read8(reg)	bus_space_read_1(pACB->tag, pACB->bsh, reg)
100105059Scognet#define trm_reg_read16(reg)	bus_space_read_2(pACB->tag, pACB->bsh, reg)
101105059Scognet#define trm_reg_read32(reg)	bus_space_read_4(pACB->tag, pACB->bsh, reg)
102105059Scognet#define trm_reg_write8(value,reg)	bus_space_write_1(pACB->tag, pACB->bsh,\
103105059Scognet		reg, value)
104105059Scognet#define trm_reg_write16(value,reg)	bus_space_write_2(pACB->tag, pACB->bsh,\
105105059Scognet		reg, value)
106105059Scognet#define trm_reg_write32(value,reg)	bus_space_write_4(pACB->tag, pACB->bsh,\
107105059Scognet		reg, value)
108105059Scognet
109105059Scognet#define PCI_Vendor_ID_TEKRAM	0x1DE1
110105059Scognet#define PCI_Device_ID_TRM_S1040	0x0391
111105059Scognet#define PCI_DEVICEID_TRMS1040	0x03911DE1
112111158Scognet#define PCI_DEVICEID_TRMS2080   0x03921DE1
113105059Scognet
114105059Scognet#ifdef trm_DEBUG1
115105059Scognet#define TRM_DPRINTF(fmt, arg...) printf("trm: " fmt, ##arg)
116105059Scognet#else
117105059Scognet#define TRM_DPRINTF(fmt, arg...) {}
118105059Scognet#endif /* TRM_DEBUG */
119105059Scognet
120105059Scognetstatic void	trm_check_eeprom(PNVRAMTYPE pEEpromBuf,PACB pACB);
121111158Scognetstatic void	NVRAM_trm_read_all(PNVRAMTYPE pEEpromBuf,PACB pACB);
122111158Scognetstatic u_int8_t	NVRAM_trm_get_data(PACB pACB, u_int8_t bAddr);
123111158Scognetstatic void	NVRAM_trm_write_all(PNVRAMTYPE pEEpromBuf,PACB pACB);
124111158Scognetstatic void	NVRAM_trm_set_data(PACB pACB, u_int8_t bAddr, u_int8_t bData);
125111158Scognetstatic void	NVRAM_trm_write_cmd(PACB pACB, u_int8_t bCmd, u_int8_t bAddr);
126111158Scognetstatic void	NVRAM_trm_wait_30us(PACB pACB);
127105059Scognet
128105059Scognetstatic void	trm_Interrupt(void *vpACB);
129105059Scognetstatic void	trm_DataOutPhase0(PACB pACB, PSRB pSRB,
130111158Scognet					 u_int16_t * pscsi_status);
131105059Scognetstatic void	trm_DataInPhase0(PACB pACB, PSRB pSRB,
132111158Scognet					u_int16_t * pscsi_status);
133105059Scognetstatic void	trm_CommandPhase0(PACB pACB, PSRB pSRB,
134111158Scognet					 u_int16_t * pscsi_status);
135105059Scognetstatic void	trm_StatusPhase0(PACB pACB, PSRB pSRB,
136111158Scognet					u_int16_t * pscsi_status);
137105059Scognetstatic void	trm_MsgOutPhase0(PACB pACB, PSRB pSRB,
138111158Scognet					u_int16_t * pscsi_status);
139105059Scognetstatic void	trm_MsgInPhase0(PACB pACB, PSRB pSRB,
140111158Scognet					u_int16_t * pscsi_status);
141105059Scognetstatic void	trm_DataOutPhase1(PACB pACB, PSRB pSRB,
142111158Scognet					 u_int16_t * pscsi_status);
143105059Scognetstatic void	trm_DataInPhase1(PACB pACB, PSRB pSRB,
144111158Scognet					u_int16_t * pscsi_status);
145105059Scognetstatic void	trm_CommandPhase1(PACB pACB, PSRB pSRB,
146111158Scognet					 u_int16_t * pscsi_status);
147105059Scognetstatic void	trm_StatusPhase1(PACB pACB, PSRB pSRB,
148111158Scognet					u_int16_t * pscsi_status);
149105059Scognetstatic void	trm_MsgOutPhase1(PACB pACB, PSRB pSRB,
150111158Scognet					u_int16_t * pscsi_status);
151105059Scognetstatic void	trm_MsgInPhase1(PACB pACB, PSRB pSRB,
152111158Scognet					u_int16_t * pscsi_status);
153111158Scognetstatic void	trm_Nop0(PACB pACB, PSRB pSRB, u_int16_t * pscsi_status);
154111158Scognetstatic void	trm_Nop1(PACB pACB, PSRB pSRB, u_int16_t * pscsi_status);
155105059Scognetstatic void	trm_SetXferRate(PACB pACB, PSRB pSRB,PDCB pDCB);
156105059Scognetstatic void	trm_DataIO_transfer(PACB pACB, PSRB pSRB, u_int16_t ioDir);
157105059Scognetstatic void	trm_Disconnect(PACB pACB);
158105059Scognetstatic void	trm_Reselect(PACB pACB);
159105059Scognetstatic void	trm_SRBdone(PACB pACB, PDCB pDCB, PSRB pSRB);
160105059Scognetstatic void	trm_DoingSRB_Done(PACB pACB);
161105059Scognetstatic void	trm_ScsiRstDetect(PACB pACB);
162105059Scognetstatic void	trm_ResetSCSIBus(PACB pACB);
163105059Scognetstatic void	trm_RequestSense(PACB pACB, PDCB pDCB, PSRB pSRB);
164105059Scognetstatic void	trm_EnableMsgOutAbort2(PACB pACB, PSRB pSRB);
165105059Scognetstatic void	trm_EnableMsgOutAbort1(PACB pACB, PSRB pSRB);
166105059Scognetstatic void	trm_SendSRB(PACB pACB, PSRB pSRB);
167105059Scognetstatic int	trm_probe(device_t tag);
168105059Scognetstatic int	trm_attach(device_t tag);
169105059Scognetstatic void	trm_reset(PACB pACB);
170105059Scognet
171105059Scognetstatic u_int16_t	trm_StartSCSI(PACB pACB, PDCB pDCB, PSRB pSRB);
172105059Scognet
173111158Scognetstatic int	trm_initAdapter(PACB pACB, u_int16_t unit);
174105059Scognetstatic void	trm_initDCB(PACB pACB, PDCB pDCB, u_int16_t unit,
175105059Scognet    					u_int32_t i, u_int32_t j);
176111158Scognetstatic int	trm_initSRB(PACB pACB);
177111158Scognetstatic void	trm_initACB(PACB pACB, u_int8_t adaptType, u_int16_t unit);
178105059Scognet/* CAM SIM entry points */
179105059Scognet#define ccb_trmsrb_ptr spriv_ptr0
180105059Scognet#define ccb_trmacb_ptr spriv_ptr1
181105059Scognetstatic void	trm_action(struct cam_sim *psim, union ccb *pccb);
182105059Scognetstatic void	trm_poll(struct cam_sim *psim);
183105059Scognet
184105059Scognet
185105059Scognetstatic void * trm_SCSI_phase0[] = {
186105059Scognet	trm_DataOutPhase0,    /* phase:0 */
187105059Scognet	trm_DataInPhase0,     /* phase:1 */
188105059Scognet	trm_CommandPhase0,    /* phase:2 */
189105059Scognet	trm_StatusPhase0,     /* phase:3 */
190105059Scognet	trm_Nop0,             /* phase:4 */
191105059Scognet	trm_Nop1,             /* phase:5 */
192105059Scognet	trm_MsgOutPhase0,     /* phase:6 */
193105059Scognet	trm_MsgInPhase0,      /* phase:7 */
194105059Scognet};
195105059Scognet
196105059Scognet/*
197105059Scognet *
198105059Scognet *          stateV = (void *) trm_SCSI_phase1[phase]
199105059Scognet *
200105059Scognet */
201105059Scognetstatic void * trm_SCSI_phase1[] = {
202105059Scognet	trm_DataOutPhase1,    /* phase:0 */
203105059Scognet	trm_DataInPhase1,     /* phase:1 */
204105059Scognet	trm_CommandPhase1,    /* phase:2 */
205105059Scognet	trm_StatusPhase1,     /* phase:3 */
206105059Scognet	trm_Nop0,             /* phase:4 */
207105059Scognet	trm_Nop1,             /* phase:5 */
208105059Scognet	trm_MsgOutPhase1,     /* phase:6 */
209105059Scognet	trm_MsgInPhase1,      /* phase:7 */
210105059Scognet};
211105059Scognet
212105059Scognet
213111158ScognetNVRAMTYPE trm_eepromBuf[TRM_MAX_ADAPTER_NUM];
214105059Scognet/*
215105059Scognet *Fast20:  000	 50ns, 20.0 Mbytes/s
216105059Scognet *	       001	 75ns, 13.3 Mbytes/s
217105059Scognet *	       010	100ns, 10.0 Mbytes/s
218105059Scognet *	       011	125ns,  8.0 Mbytes/s
219105059Scognet *	       100	150ns,  6.6 Mbytes/s
220105059Scognet *	       101	175ns,  5.7 Mbytes/s
221105059Scognet *	       110	200ns,  5.0 Mbytes/s
222105059Scognet *	       111	250ns,  4.0 Mbytes/s
223105059Scognet *
224105059Scognet *Fast40:  000	 25ns, 40.0 Mbytes/s
225105059Scognet *	       001	 50ns, 20.0 Mbytes/s
226105059Scognet *	       010	 75ns, 13.3 Mbytes/s
227105059Scognet *	       011	100ns, 10.0 Mbytes/s
228105059Scognet *	       100	125ns,  8.0 Mbytes/s
229105059Scognet *	       101	150ns,  6.6 Mbytes/s
230105059Scognet *	       110	175ns,  5.7 Mbytes/s
231105059Scognet *	       111	200ns,  5.0 Mbytes/s
232105059Scognet */
233105059Scognet                                             /* real period: */
234111158Scognetu_int8_t dc395x_clock_period[] = {
235105059Scognet	12,/*  48  ns 20   MB/sec */
236105059Scognet	18,/*  72  ns 13.3 MB/sec */
237105059Scognet	25,/* 100  ns 10.0 MB/sec */
238105059Scognet	31,/* 124  ns  8.0 MB/sec */
239105059Scognet	37,/* 148  ns  6.6 MB/sec */
240105059Scognet	43,/* 172  ns  5.7 MB/sec */
241105059Scognet	50,/* 200  ns  5.0 MB/sec */
242105059Scognet	62 /* 248  ns  4.0 MB/sec */
243105059Scognet};
244105059Scognet
245111158Scognetu_int8_t dc395u2x_clock_period[]={
246111158Scognet	10,/*  25  ns 40.0 MB/sec */
247111158Scognet	12,/*  48  ns 20.0 MB/sec */
248111158Scognet	18,/*  72  ns 13.3 MB/sec */
249111158Scognet	25,/* 100  ns 10.0 MB/sec */
250111158Scognet	31,/* 124  ns  8.0 MB/sec */
251111158Scognet	37,/* 148  ns  6.6 MB/sec */
252111158Scognet	43,/* 172  ns  5.7 MB/sec */
253111158Scognet	50,/* 200  ns  5.0 MB/sec */
254105059Scognet};
255105059Scognet
256111158Scognet#define  dc395x_tinfo_period           dc395x_clock_period
257111158Scognet#define  dc395u2x_tinfo_period         dc395u2x_clock_period
258111158Scognet
259105059Scognetstatic PSRB
260105059Scognettrm_GetSRB(PACB pACB)
261105059Scognet{
262105059Scognet	int	intflag;
263105059Scognet	PSRB	pSRB;
264105059Scognet
265105059Scognet	intflag = splcam();
266105059Scognet    	pSRB = pACB->pFreeSRB;
267105059Scognet	if (pSRB) {
268105059Scognet		pACB->pFreeSRB = pSRB->pNextSRB;
269105059Scognet		pSRB->pNextSRB = NULL;
270105059Scognet	}
271105059Scognet	splx(intflag);
272105059Scognet    	return (pSRB);
273105059Scognet}
274105059Scognet
275105059Scognetstatic void
276105059Scognettrm_RewaitSRB0(PDCB pDCB, PSRB pSRB)
277105059Scognet{
278105059Scognet	PSRB	psrb1;
279105059Scognet	int	intflag;
280105059Scognet
281105059Scognet	intflag = splcam();
282105059Scognet    	if ((psrb1 = pDCB->pWaitingSRB)) {
283105059Scognet		pSRB->pNextSRB = psrb1;
284105059Scognet		pDCB->pWaitingSRB = pSRB;
285105059Scognet	} else {
286105059Scognet	  	pSRB->pNextSRB = NULL;
287105059Scognet		pDCB->pWaitingSRB = pSRB;
288111158Scognet		pDCB->pWaitingLastSRB = pSRB;
289105059Scognet	}
290105059Scognet	splx(intflag);
291105059Scognet}
292105059Scognet
293105059Scognetstatic void
294105059Scognettrm_RewaitSRB(PDCB pDCB, PSRB pSRB)
295105059Scognet{
296105059Scognet	PSRB	psrb1;
297105059Scognet	int	intflag;
298105059Scognet
299105059Scognet	intflag = splcam();
300105059Scognet    	pDCB->GoingSRBCnt--;
301105059Scognet	psrb1 = pDCB->pGoingSRB;
302105059Scognet	if (pSRB == psrb1)
303111158Scognet		/*
304111158Scognet		 * if this SRB is GoingSRB
305111158Scognet		 * remove this SRB from GoingSRB Q
306111158Scognet		 */
307105059Scognet		pDCB->pGoingSRB = psrb1->pNextSRB;
308105059Scognet	else {
309111158Scognet		/*
310111158Scognet		 * if this SRB is not current GoingSRB
311111158Scognet		 * remove this SRB from GoingSRB Q
312111158Scognet		 */
313105059Scognet		while (pSRB != psrb1->pNextSRB)
314105059Scognet			psrb1 = psrb1->pNextSRB;
315105059Scognet		psrb1->pNextSRB = pSRB->pNextSRB;
316105059Scognet		if (pSRB == pDCB->pGoingLastSRB)
317105059Scognet			pDCB->pGoingLastSRB = psrb1;
318105059Scognet	}
319105059Scognet	if ((psrb1 = pDCB->pWaitingSRB)) {
320111158Scognet		/*
321111158Scognet		 * if WaitingSRB Q is not NULL
322111158Scognet		 * Q back this SRB into WaitingSRB
323111158Scognet		 */
324111158Scognet
325105059Scognet		pSRB->pNextSRB = psrb1;
326105059Scognet		pDCB->pWaitingSRB = pSRB;
327105059Scognet	} else {
328105059Scognet		pSRB->pNextSRB = NULL;
329105059Scognet		pDCB->pWaitingSRB = pSRB;
330111158Scognet		pDCB->pWaitingLastSRB = pSRB;
331105059Scognet	}
332105059Scognet	splx(intflag);
333105059Scognet}
334105059Scognet
335105059Scognetstatic void
336105059Scognettrm_DoWaitingSRB(PACB pACB)
337105059Scognet{
338105059Scognet	int	intflag;
339105059Scognet	PDCB	ptr, ptr1;
340105059Scognet	PSRB	pSRB;
341105059Scognet
342105059Scognet	intflag = splcam();
343105059Scognet    	if (!(pACB->pActiveDCB) &&
344105059Scognet	    !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV))) {
345105059Scognet		ptr = pACB->pDCBRunRobin;
346105059Scognet		if (!ptr) {
347105059Scognet			ptr = pACB->pLinkDCB;
348105059Scognet			pACB->pDCBRunRobin = ptr;
349105059Scognet		}
350105059Scognet		ptr1 = ptr;
351105059Scognet		for (;ptr1 ;) {
352105059Scognet			pACB->pDCBRunRobin = ptr1->pNextDCB;
353111158Scognet			if (!(ptr1->MaxActiveCommandCnt > ptr1->GoingSRBCnt)
354105059Scognet			    || !(pSRB = ptr1->pWaitingSRB)) {
355105059Scognet				if (pACB->pDCBRunRobin == ptr)
356105059Scognet					break;
357105059Scognet				ptr1 = ptr1->pNextDCB;
358105059Scognet			} else {
359105059Scognet				if (!trm_StartSCSI(pACB, ptr1, pSRB)) {
360105059Scognet				/*
361105059Scognet				 * If trm_StartSCSI return 0 :
362105059Scognet				 * current interrupt status is interrupt enable
363105059Scognet				 * It's said that SCSI processor is unoccupied
364105059Scognet				 */
365105059Scognet					ptr1->GoingSRBCnt++;
366111158Scognet					if (ptr1->pWaitingLastSRB == pSRB) {
367105059Scognet						ptr1->pWaitingSRB = NULL;
368111158Scognet						ptr1->pWaitingLastSRB = NULL;
369105059Scognet					} else
370105059Scognet						ptr1->pWaitingSRB = pSRB->pNextSRB;
371105059Scognet					pSRB->pNextSRB = NULL;
372105059Scognet					if (ptr1->pGoingSRB)
373105059Scognet						ptr1->pGoingLastSRB->pNextSRB = pSRB;
374105059Scognet					else
375105059Scognet						ptr1->pGoingSRB = pSRB;
376105059Scognet					ptr1->pGoingLastSRB = pSRB;
377105059Scognet				}
378105059Scognet				break;
379105059Scognet			}
380105059Scognet		}
381105059Scognet	}
382105059Scognet	splx(intflag);
383105059Scognet	return;
384105059Scognet}
385105059Scognet
386105059Scognetstatic void
387105059Scognettrm_SRBwaiting(PDCB pDCB, PSRB pSRB)
388105059Scognet{
389105059Scognet
390105059Scognet	if (pDCB->pWaitingSRB) {
391111158Scognet		pDCB->pWaitingLastSRB->pNextSRB = pSRB;
392111158Scognet		pDCB->pWaitingLastSRB = pSRB;
393105059Scognet		pSRB->pNextSRB = NULL;
394105059Scognet	} else {
395105059Scognet		pDCB->pWaitingSRB = pSRB;
396111158Scognet		pDCB->pWaitingLastSRB = pSRB;
397105059Scognet	}
398105059Scognet}
399105059Scognet
400111158Scognetstatic u_int32_t
401111158Scognettrm_get_sense_bufaddr(PACB pACB, PSRB pSRB)
402111158Scognet{
403111158Scognet	int offset;
404111158Scognet
405111158Scognet	offset = pSRB->TagNumber;
406111158Scognet	return (pACB->sense_busaddr +
407111158Scognet	    (offset * sizeof(struct scsi_sense_data)));
408111158Scognet}
409111158Scognet
410111158Scognetstatic struct scsi_sense_data *
411111158Scognettrm_get_sense_buf(PACB pACB, PSRB pSRB)
412111158Scognet{
413111158Scognet	int offset;
414111158Scognet
415111158Scognet	offset = pSRB->TagNumber;
416111158Scognet	return (&pACB->sense_buffers[offset]);
417111158Scognet}
418105059Scognetstatic void
419111158Scognettrm_ExecuteSRB(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
420105059Scognet{
421105059Scognet	int		flags;
422105059Scognet	PACB		pACB;
423105059Scognet	PSRB		pSRB;
424105059Scognet	union ccb	*ccb;
425105059Scognet	u_long		totalxferlen=0;
426105059Scognet
427111158Scognet	flags = splcam();
428105059Scognet	pSRB = (PSRB)arg;
429105059Scognet	ccb = pSRB->pccb;
430105059Scognet	pACB = (PACB)ccb->ccb_h.ccb_trmacb_ptr;
431105059Scognet	TRM_DPRINTF("trm_ExecuteSRB..........\n");
432105059Scognet	if (nseg != 0) {
433105059Scognet		PSEG			psg;
434105059Scognet		bus_dma_segment_t	*end_seg;
435113350Smux		int			op;
436105059Scognet
437105059Scognet		/* Copy the segments into our SG list */
438105059Scognet		end_seg = dm_segs + nseg;
439111158Scognet		psg = pSRB->pSRBSGL;
440105059Scognet		while (dm_segs < end_seg) {
441111158Scognet			psg->address = dm_segs->ds_addr;
442105059Scognet			psg->length = (u_long)dm_segs->ds_len;
443105059Scognet			totalxferlen += dm_segs->ds_len;
444105059Scognet			psg++;
445105059Scognet			dm_segs++;
446105059Scognet		}
447105059Scognet		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
448105059Scognet			op = BUS_DMASYNC_PREREAD;
449105059Scognet		} else {
450105059Scognet			op = BUS_DMASYNC_PREWRITE;
451105059Scognet		}
452105059Scognet		bus_dmamap_sync(pACB->buffer_dmat, pSRB->dmamap, op);
453105059Scognet	}
454105059Scognet	pSRB->RetryCnt = 0;
455111158Scognet	pSRB->SRBTotalXferLength = totalxferlen;
456105059Scognet	pSRB->SRBSGCount = nseg;
457105059Scognet	pSRB->SRBSGIndex = 0;
458105059Scognet	pSRB->AdaptStatus = 0;
459105059Scognet	pSRB->TargetStatus = 0;
460105059Scognet	pSRB->MsgCnt = 0;
461105059Scognet	pSRB->SRBStatus = 0;
462105059Scognet	pSRB->SRBFlag = 0;
463105059Scognet	pSRB->SRBState = 0;
464105059Scognet	pSRB->ScsiPhase = PH_BUS_FREE; /* SCSI bus free Phase */
465105059Scognet
466105059Scognet	if (ccb->ccb_h.status != CAM_REQ_INPROG) {
467105059Scognet		if (nseg != 0)
468105059Scognet			bus_dmamap_unload(pACB->buffer_dmat, pSRB->dmamap);
469105059Scognet		pSRB->pNextSRB = pACB->pFreeSRB;
470105059Scognet		pACB->pFreeSRB = pSRB;
471105059Scognet		xpt_done(ccb);
472105059Scognet		splx(flags);
473105059Scognet		return;
474105059Scognet	}
475105059Scognet	ccb->ccb_h.status |= CAM_SIM_QUEUED;
476105059Scognet#if 0
477105059Scognet	/* XXX Need a timeout handler */
478105059Scognet	ccb->ccb_h.timeout_ch = timeout(trmtimeout, (caddr_t)srb, (ccb->ccb_h.timeout * hz) / 1000);
479105059Scognet#endif
480105059Scognet	trm_SendSRB(pACB, pSRB);
481105059Scognet	splx(flags);
482105059Scognet	return;
483105059Scognet}
484105059Scognet
485105059Scognetstatic void
486105059Scognettrm_SendSRB(PACB pACB, PSRB pSRB)
487105059Scognet{
488105059Scognet	PDCB	pDCB;
489105059Scognet
490105059Scognet	pDCB = pSRB->pSRBDCB;
491111158Scognet	if (!(pDCB->MaxActiveCommandCnt > pDCB->GoingSRBCnt) || (pACB->pActiveDCB)
492105059Scognet	    || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV))) {
493111158Scognet		TRM_DPRINTF("pDCB->MaxCommand=%d \n",pDCB->MaxActiveCommandCnt);
494105059Scognet		TRM_DPRINTF("pDCB->GoingSRBCnt=%d \n",pDCB->GoingSRBCnt);
495105059Scognet		TRM_DPRINTF("pACB->pActiveDCB=%8x \n",(u_int)pACB->pActiveDCB);
496105059Scognet		TRM_DPRINTF("pACB->ACBFlag=%x \n",pACB->ACBFlag);
497105059Scognet	    	trm_SRBwaiting(pDCB, pSRB);
498105059Scognet		goto SND_EXIT;
499105059Scognet	}
500105059Scognet
501105059Scognet	if (pDCB->pWaitingSRB) {
502105059Scognet		trm_SRBwaiting(pDCB, pSRB);
503105059Scognet		pSRB = pDCB->pWaitingSRB;
504105059Scognet		pDCB->pWaitingSRB = pSRB->pNextSRB;
505105059Scognet		pSRB->pNextSRB = NULL;
506105059Scognet	}
507105059Scognet
508105059Scognet	if (!trm_StartSCSI(pACB, pDCB, pSRB)) {
509105059Scognet	/*
510105059Scognet	 * If trm_StartSCSI return 0 :
511105059Scognet	 * current interrupt status is interrupt enable
512105059Scognet	 * It's said that SCSI processor is unoccupied
513105059Scognet	 */
514105059Scognet		pDCB->GoingSRBCnt++; /* stack waiting SRB*/
515105059Scognet		if (pDCB->pGoingSRB) {
516105059Scognet			pDCB->pGoingLastSRB->pNextSRB = pSRB;
517105059Scognet			pDCB->pGoingLastSRB = pSRB;
518105059Scognet		} else {
519105059Scognet			pDCB->pGoingSRB = pSRB;
520105059Scognet			pDCB->pGoingLastSRB = pSRB;
521105059Scognet		}
522105059Scognet	} else {
523105059Scognet	/*
524105059Scognet	 * If trm_StartSCSI return 1 :
525105059Scognet	 * current interrupt status is interrupt disreenable
526105059Scognet	 * It's said that SCSI processor has more one SRB need to do
527105059Scognet	 */
528105059Scognet		trm_RewaitSRB0(pDCB, pSRB);
529105059Scognet	}
530105059ScognetSND_EXIT:
531105059Scognet	return;
532105059Scognet}
533105059Scognet
534105059Scognet
535105059Scognetstatic void
536105059Scognettrm_action(struct cam_sim *psim, union ccb *pccb)
537105059Scognet{
538105059Scognet	PACB	pACB;
539111158Scognet	int	actionflags;
540105059Scognet	u_int	target_id,target_lun;
541105059Scognet
542105059Scognet	CAM_DEBUG(pccb->ccb_h.path, CAM_DEBUG_TRACE, ("trm_action\n"));
543105059Scognet
544111158Scognet	actionflags = splcam();
545105059Scognet	pACB = (PACB) cam_sim_softc(psim);
546105059Scognet    	target_id  = pccb->ccb_h.target_id;
547105059Scognet	target_lun = pccb->ccb_h.target_lun;
548105059Scognet
549105059Scognet	switch (pccb->ccb_h.func_code) {
550105059Scognet		case XPT_NOOP:
551105059Scognet			TRM_DPRINTF(" XPT_NOOP \n");
552105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
553105059Scognet			xpt_done(pccb);
554105059Scognet			break;
555105059Scognet		/*
556105059Scognet		 * Execute the requested I/O operation
557105059Scognet	 	 */
558105059Scognet		case XPT_SCSI_IO: {
559105059Scognet			PDCB			pDCB = NULL;
560105059Scognet			PSRB			pSRB;
561105059Scognet			struct ccb_scsiio	*pcsio;
562246713Skib			int			error;
563105059Scognet
564105059Scognet			pcsio = &pccb->csio;
565105059Scognet			TRM_DPRINTF(" XPT_SCSI_IO \n");
566105059Scognet			TRM_DPRINTF("trm: target_id= %d target_lun= %d \n"
567105059Scognet			     ,target_id, target_lun);
568105059Scognet			TRM_DPRINTF(
569105059Scognet			    "pACB->scan_devices[target_id][target_lun]= %d \n"
570105059Scognet			    ,pACB->scan_devices[target_id][target_lun]);
571116813Scognet			if ((pccb->ccb_h.status & CAM_STATUS_MASK) !=
572116813Scognet			    CAM_REQ_INPROG) {
573111158Scognet				xpt_done(pccb);
574111158Scognet				splx(actionflags);
575111158Scognet				return;
576111158Scognet			}
577111158Scognet			pDCB = &pACB->DCBarray[target_id][target_lun];
578116813Scognet			if (!(pDCB->DCBstatus & DS_IN_QUEUE)) {
579111158Scognet				pACB->scan_devices[target_id][target_lun] = 1;
580111158Scognet				trm_initDCB(pACB, pDCB, pACB->AdapterUnit,
581111158Scognet				    target_id, target_lun);
582111158Scognet			}
583105059Scognet			/*
584105059Scognet			 * Assign an SRB and connect it with this ccb.
585105059Scognet			 */
586105059Scognet			pSRB = trm_GetSRB(pACB);
587105059Scognet			if (!pSRB) {
588105059Scognet				/* Freeze SIMQ */
589105059Scognet				pccb->ccb_h.status = CAM_RESRC_UNAVAIL;
590105059Scognet				xpt_done(pccb);
591111158Scognet				splx(actionflags);
592105059Scognet				return;
593105059Scognet			}
594105059Scognet	    		pSRB->pSRBDCB = pDCB;
595105059Scognet	    		pccb->ccb_h.ccb_trmsrb_ptr = pSRB;
596105059Scognet	    		pccb->ccb_h.ccb_trmacb_ptr = pACB;
597105059Scognet		    	pSRB->pccb = pccb;
598105059Scognet			pSRB->ScsiCmdLen = pcsio->cdb_len;
599105059Scognet			/*
600105059Scognet			 * move layer of CAM command block to layer of SCSI
601105059Scognet			 * Request Block for SCSI processor command doing
602105059Scognet			 */
603116813Scognet			if ((pccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
604116813Scognet				if ((pccb->ccb_h.flags & CAM_CDB_PHYS) == 0) {
605111158Scognet					bcopy(pcsio->cdb_io.cdb_ptr,pSRB->CmdBlock
606111158Scognet					    ,pcsio->cdb_len);
607111158Scognet				} else {
608111158Scognet					pccb->ccb_h.status = CAM_REQ_INVALID;
609111158Scognet					pSRB->pNextSRB = pACB->pFreeSRB;
610111158Scognet					pACB->pFreeSRB=  pSRB;
611111158Scognet					xpt_done(pccb);
612111158Scognet					splx(actionflags);
613111158Scognet					return;
614111158Scognet				}
615111158Scognet			} else
616111158Scognet				bcopy(pcsio->cdb_io.cdb_bytes,
617111158Scognet				    pSRB->CmdBlock, pcsio->cdb_len);
618246713Skib			error = bus_dmamap_load_ccb(pACB->buffer_dmat,
619105059Scognet						    pSRB->dmamap,
620246713Skib						    pccb,
621105059Scognet						    trm_ExecuteSRB,
622105059Scognet						    pSRB,
623105059Scognet						    0);
624246713Skib			if (error == EINPROGRESS) {
625246713Skib				xpt_freeze_simq(pACB->psim, 1);
626246713Skib				pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
627246713Skib			}
628105059Scognet			break;
629246713Skib		}
630105059Scognet		case XPT_GDEV_TYPE:
631105059Scognet			TRM_DPRINTF(" XPT_GDEV_TYPE \n");
632105059Scognet	    		pccb->ccb_h.status = CAM_REQ_INVALID;
633105059Scognet			xpt_done(pccb);
634105059Scognet			break;
635105059Scognet		case XPT_GDEVLIST:
636105059Scognet			TRM_DPRINTF(" XPT_GDEVLIST \n");
637105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
638105059Scognet			xpt_done(pccb);
639105059Scognet			break;
640105059Scognet		/*
641105059Scognet		 * Path routing inquiry
642105059Scognet	       	 * Path Inquiry CCB
643105059Scognet		 */
644105059Scognet		case XPT_PATH_INQ: {
645105059Scognet			struct ccb_pathinq *cpi = &pccb->cpi;
646105059Scognet
647105059Scognet			TRM_DPRINTF(" XPT_PATH_INQ \n");
648105059Scognet			cpi->version_num = 1;
649105059Scognet			cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
650105059Scognet			cpi->target_sprt = 0;
651105059Scognet			cpi->hba_misc = 0;
652105059Scognet			cpi->hba_eng_cnt = 0;
653105059Scognet			cpi->max_target = 15 ;
654105059Scognet			cpi->max_lun = pACB->max_lun;        /* 7 or 0 */
655105059Scognet			cpi->initiator_id = pACB->AdaptSCSIID;
656105059Scognet			cpi->bus_id = cam_sim_bus(psim);
657111158Scognet			cpi->base_transfer_speed = 3300;
658105059Scognet			strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
659105059Scognet			strncpy(cpi->hba_vid, "Tekram_TRM", HBA_IDLEN);
660105059Scognet			strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN);
661105059Scognet			cpi->unit_number = cam_sim_unit(psim);
662163816Smjacob			cpi->transport = XPORT_SPI;
663163816Smjacob			cpi->transport_version = 2;
664163816Smjacob			cpi->protocol = PROTO_SCSI;
665163816Smjacob			cpi->protocol_version = SCSI_REV_2;
666105059Scognet			cpi->ccb_h.status = CAM_REQ_CMP;
667105059Scognet			xpt_done(pccb);
668105059Scognet				   }
669105059Scognet			break;
670105059Scognet		/*
671105059Scognet		 * Release a frozen SIM queue
672105059Scognet		 * Release SIM Queue
673105059Scognet		 */
674105059Scognet		case XPT_REL_SIMQ:
675105059Scognet			TRM_DPRINTF(" XPT_REL_SIMQ \n");
676105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
677105059Scognet			xpt_done(pccb);
678105059Scognet			break;
679105059Scognet		/*
680105059Scognet		 * Set Asynchronous Callback Parameters
681105059Scognet		 * Set Asynchronous Callback CCB
682105059Scognet 		 */
683105059Scognet		case XPT_SASYNC_CB:
684105059Scognet			TRM_DPRINTF(" XPT_SASYNC_CB \n");
685105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
686105059Scognet			xpt_done(pccb);
687105059Scognet			break;
688105059Scognet		/*
689105059Scognet		 * Set device type information
690105059Scognet		 * Set Device Type CCB
691105059Scognet 		 */
692105059Scognet		case XPT_SDEV_TYPE:
693105059Scognet			TRM_DPRINTF(" XPT_SDEV_TYPE \n");
694105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
695105059Scognet			xpt_done(pccb);
696105059Scognet			break;
697105059Scognet		/*
698105059Scognet		 * Get EDT entries matching the given pattern
699105059Scognet 		 */
700105059Scognet		case XPT_DEV_MATCH:
701105059Scognet			TRM_DPRINTF(" XPT_DEV_MATCH \n");
702105059Scognet	    		pccb->ccb_h.status = CAM_REQ_INVALID;
703105059Scognet			xpt_done(pccb);
704105059Scognet			break;
705105059Scognet		/*
706105059Scognet		 * Turn on debugging for a bus, target or lun
707105059Scognet      		 */
708105059Scognet		case XPT_DEBUG:
709105059Scognet			TRM_DPRINTF(" XPT_DEBUG \n");
710105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
711105059Scognet			xpt_done(pccb);
712105059Scognet			break;
713105059Scognet			/*
714105059Scognet			 * XPT_ABORT = 0x10, Abort the specified CCB
715105059Scognet			 * Abort XPT request CCB
716105059Scognet			 */
717105059Scognet		case XPT_ABORT:
718105059Scognet			TRM_DPRINTF(" XPT_ABORT \n");
719105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
720105059Scognet			xpt_done(pccb);
721105059Scognet			break;
722105059Scognet		/*
723105059Scognet		 * Reset the specified SCSI bus
724105059Scognet		 * Reset SCSI Bus CCB
725105059Scognet 		 */
726105059Scognet		case XPT_RESET_BUS: {
727105059Scognet			int i;
728105059Scognet
729105059Scognet			TRM_DPRINTF(" XPT_RESET_BUS \n");
730105059Scognet	    		trm_reset(pACB);
731105059Scognet			pACB->ACBFlag=0;
732105059Scognet			for (i=0; i<500; i++)
733105059Scognet				DELAY(1000);
734105059Scognet			pccb->ccb_h.status = CAM_REQ_CMP;
735105059Scognet			xpt_done(pccb);
736105059Scognet				    }
737105059Scognet			break;
738105059Scognet		/*
739105059Scognet		 * Bus Device Reset the specified SCSI device
740105059Scognet		 * Reset SCSI Device CCB
741105059Scognet 		 */
742105059Scognet		case XPT_RESET_DEV:
743105059Scognet		/*
744105059Scognet		 * Don't (yet?) support vendor
745105059Scognet		 * specific commands.
746105059Scognet		 */
747105059Scognet			TRM_DPRINTF(" XPT_RESET_DEV \n");
748105059Scognet	    		pccb->ccb_h.status = CAM_REQ_INVALID;
749105059Scognet			xpt_done(pccb);
750105059Scognet			break;
751105059Scognet		/*
752105059Scognet		 * Terminate the I/O process
753105059Scognet		 * Terminate I/O Process Request CCB
754105059Scognet 		 */
755105059Scognet		case XPT_TERM_IO:
756105059Scognet			TRM_DPRINTF(" XPT_TERM_IO \n");
757105059Scognet	    		pccb->ccb_h.status = CAM_REQ_INVALID;
758105059Scognet			xpt_done(pccb);
759105059Scognet			break;
760105059Scognet		/*
761105059Scognet		 * Get/Set transfer rate/width/disconnection/tag queueing
762105059Scognet		 * settings
763105059Scognet		 * (GET) default/user transfer settings for the target
764105059Scognet	 	 */
765105059Scognet		case XPT_GET_TRAN_SETTINGS: {
766163816Smjacob			struct	ccb_trans_settings *cts = &pccb->cts;
767105059Scognet			int	intflag;
768105059Scognet			struct	trm_transinfo *tinfo;
769105059Scognet			PDCB	pDCB;
770163816Smjacob			struct ccb_trans_settings_scsi *scsi =
771163816Smjacob			    &cts->proto_specific.scsi;
772163816Smjacob			struct ccb_trans_settings_spi *spi =
773163816Smjacob			    &cts->xport_specific.spi;
774163816Smjacob
775163816Smjacob			cts->protocol = PROTO_SCSI;
776163816Smjacob			cts->protocol_version = SCSI_REV_2;
777163816Smjacob			cts->transport = XPORT_SPI;
778163816Smjacob			cts->transport_version = 2;
779163816Smjacob
780105059Scognet			TRM_DPRINTF(" XPT_GET_TRAN_SETTINGS \n");
781111158Scognet			pDCB = &pACB->DCBarray[target_id][target_lun];
782105059Scognet			intflag = splcam();
783105059Scognet			/*
784105059Scognet			 * disable interrupt
785105059Scognet			 */
786163816Smjacob			if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
787163816Smjacob				/* current transfer settings */
788163816Smjacob				if (pDCB->tinfo.disc_tag & TRM_CUR_DISCENB)
789163816Smjacob					spi->flags = CTS_SPI_FLAGS_DISC_ENB;
790163816Smjacob				else
791163816Smjacob					spi->flags = 0;/* no tag & disconnect */
792163816Smjacob				if (pDCB->tinfo.disc_tag & TRM_CUR_TAGENB)
793163816Smjacob					scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
794163816Smjacob				tinfo = &pDCB->tinfo.current;
795163816Smjacob				TRM_DPRINTF("CURRENT:  cts->flags= %2x \n",
796163816Smjacob				    cts->flags);
797163816Smjacob			} else {
798163816Smjacob		  	  /* default(user) transfer settings */
799163816Smjacob				if (pDCB->tinfo.disc_tag & TRM_USR_DISCENB)
800163816Smjacob					spi->flags = CTS_SPI_FLAGS_DISC_ENB;
801163816Smjacob				else
802163816Smjacob					spi->flags = 0;
803163816Smjacob				if (pDCB->tinfo.disc_tag & TRM_USR_TAGENB)
804163816Smjacob					scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
805163816Smjacob				tinfo = &pDCB->tinfo.user;
806163816Smjacob				TRM_DPRINTF("USER: cts->flags= %2x \n",
807163816Smjacob					cts->flags);
808163816Smjacob			}
809163816Smjacob			spi->sync_period = tinfo->period;
810163816Smjacob			spi->sync_offset = tinfo->offset;
811163816Smjacob			spi->bus_width   = tinfo->width;
812163816Smjacob			TRM_DPRINTF("pDCB->SyncPeriod: %d  \n",
813163816Smjacob				pDCB->SyncPeriod);
814163816Smjacob			TRM_DPRINTF("period: %d  \n", tinfo->period);
815163816Smjacob			TRM_DPRINTF("offset: %d  \n", tinfo->offset);
816163816Smjacob			TRM_DPRINTF("width: %d  \n", tinfo->width);
817163816Smjacob
818163816Smjacob	    		splx(intflag);
819163816Smjacob			spi->valid = CTS_SPI_VALID_SYNC_RATE |
820163816Smjacob			    CTS_SPI_VALID_SYNC_OFFSET |
821163816Smjacob			    CTS_SPI_VALID_BUS_WIDTH |
822163816Smjacob			    CTS_SPI_VALID_DISC;
823163816Smjacob			scsi->valid = CTS_SCSI_VALID_TQ;
824105059Scognet			pccb->ccb_h.status = CAM_REQ_CMP;
825105059Scognet			xpt_done(pccb);
826105059Scognet					    }
827105059Scognet			break;
828105059Scognet		/*
829105059Scognet		 * Get/Set transfer rate/width/disconnection/tag queueing
830105059Scognet		 * settings
831105059Scognet		 * (Set) transfer rate/width negotiation settings
832105059Scognet		 */
833105059Scognet		case XPT_SET_TRAN_SETTINGS: {
834163816Smjacob			struct	ccb_trans_settings *cts =  &pccb->cts;
835105059Scognet			u_int	update_type;
836105059Scognet			int	intflag;
837105059Scognet			PDCB	pDCB;
838163816Smjacob			struct ccb_trans_settings_scsi *scsi =
839163816Smjacob			    &cts->proto_specific.scsi;
840163816Smjacob			struct ccb_trans_settings_spi *spi =
841163816Smjacob			    &cts->xport_specific.spi;
842105059Scognet
843105059Scognet			TRM_DPRINTF(" XPT_SET_TRAN_SETTINGS \n");
844105059Scognet			update_type = 0;
845163816Smjacob			if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
846163816Smjacob				update_type |= TRM_TRANS_GOAL;
847163816Smjacob			if (cts->type == CTS_TYPE_USER_SETTINGS)
848163816Smjacob				update_type |= TRM_TRANS_USER;
849163816Smjacob			intflag = splcam();
850163816Smjacob	    		pDCB = &pACB->DCBarray[target_id][target_lun];
851163816Smjacob
852163816Smjacob			if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
853163816Smjacob			  /*ccb disc enables */
854163816Smjacob				if (update_type & TRM_TRANS_GOAL) {
855163816Smjacob					if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB)
856163816Smjacob					    != 0)
857163816Smjacob				    		pDCB->tinfo.disc_tag
858163816Smjacob						    |= TRM_CUR_DISCENB;
859163816Smjacob					else
860163816Smjacob						pDCB->tinfo.disc_tag &=
861163816Smjacob						    ~TRM_CUR_DISCENB;
862163816Smjacob				}
863163816Smjacob				if (update_type & TRM_TRANS_USER) {
864163816Smjacob					if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB)
865163816Smjacob					    != 0)
866163816Smjacob						pDCB->tinfo.disc_tag
867163816Smjacob						    |= TRM_USR_DISCENB;
868163816Smjacob					else
869163816Smjacob						pDCB->tinfo.disc_tag &=
870163816Smjacob						    ~TRM_USR_DISCENB;
871163816Smjacob				}
872163816Smjacob			}
873163816Smjacob			if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
874163816Smjacob			  /* if ccb tag q active */
875163816Smjacob				if (update_type & TRM_TRANS_GOAL) {
876163816Smjacob					if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB)
877163816Smjacob					    != 0)
878163816Smjacob						pDCB->tinfo.disc_tag |=
879163816Smjacob						    TRM_CUR_TAGENB;
880163816Smjacob					else
881163816Smjacob						pDCB->tinfo.disc_tag &=
882163816Smjacob						    ~TRM_CUR_TAGENB;
883163816Smjacob				}
884163816Smjacob				if (update_type & TRM_TRANS_USER) {
885163816Smjacob					if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB)
886163816Smjacob					    != 0)
887163816Smjacob				  		pDCB->tinfo.disc_tag |=
888163816Smjacob						    TRM_USR_TAGENB;
889163816Smjacob					else
890163816Smjacob						pDCB->tinfo.disc_tag &=
891163816Smjacob						    ~TRM_USR_TAGENB;
892163816Smjacob				}
893163816Smjacob			}
894163816Smjacob			/* Minimum sync period factor	*/
895163816Smjacob
896163816Smjacob			if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
897163816Smjacob				/* if ccb sync active */
898163816Smjacob				/* TRM-S1040 MinSyncPeriod = 4 clocks/byte */
899163816Smjacob				if ((spi->sync_period != 0) &&
900163816Smjacob				    (spi->sync_period < 125))
901163816Smjacob					spi->sync_period = 125;
902163816Smjacob				/* 1/(125*4) minsync 2 MByte/sec */
903163816Smjacob				if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET)
904163816Smjacob				    != 0) {
905163816Smjacob					if (spi->sync_offset == 0)
906163816Smjacob				 		spi->sync_period = 0;
907163816Smjacob					/* TRM-S1040 MaxSyncOffset = 15 bytes*/
908163816Smjacob					if (spi->sync_offset > 15)
909163816Smjacob						spi->sync_offset = 15;
910163816Smjacob				}
911163816Smjacob			}
912163816Smjacob			if ((update_type & TRM_TRANS_USER) != 0) {
913163816Smjacob				pDCB->tinfo.user.period = spi->sync_period;
914163816Smjacob				pDCB->tinfo.user.offset = spi->sync_offset;
915163816Smjacob				pDCB->tinfo.user.width  = spi->bus_width;
916163816Smjacob			}
917163816Smjacob			if ((update_type & TRM_TRANS_GOAL) != 0) {
918163816Smjacob				pDCB->tinfo.goal.period = spi->sync_period;
919163816Smjacob				pDCB->tinfo.goal.offset = spi->sync_offset;
920163816Smjacob				pDCB->tinfo.goal.width  = spi->bus_width;
921163816Smjacob			}
922163816Smjacob			splx(intflag);
923105059Scognet			pccb->ccb_h.status = CAM_REQ_CMP;
924105059Scognet			xpt_done(pccb);
925105059Scognet			break;
926105059Scognet					    }
927105059Scognet		/*
928105059Scognet		 * Calculate the geometry parameters for a device give
929105059Scognet		 * the sector size and volume size.
930105059Scognet   		 */
931116351Snjl		case XPT_CALC_GEOMETRY:
932105059Scognet			TRM_DPRINTF(" XPT_CALC_GEOMETRY \n");
933116351Snjl			cam_calc_geometry(&pccb->ccg, /*extended*/1);
934105059Scognet			xpt_done(pccb);
935105059Scognet			break;
936105059Scognet		case XPT_ENG_INQ:
937105059Scognet			TRM_DPRINTF(" XPT_ENG_INQ \n");
938105059Scognet	    		pccb->ccb_h.status = CAM_REQ_INVALID;
939105059Scognet			xpt_done(pccb);
940105059Scognet			break;
941105059Scognet		/*
942105059Scognet		 * HBA execute engine request
943105059Scognet		 * This structure must match SCSIIO size
944105059Scognet		 */
945105059Scognet		case XPT_ENG_EXEC:
946105059Scognet			TRM_DPRINTF(" XPT_ENG_EXEC \n");
947105059Scognet	    		pccb->ccb_h.status = CAM_REQ_INVALID;
948105059Scognet			xpt_done(pccb);
949105059Scognet			break;
950105059Scognet		/*
951105059Scognet		 * XPT_EN_LUN = 0x30, Enable LUN as a target
952105059Scognet		 * Target mode structures.
953105059Scognet	 	 */
954105059Scognet		case XPT_EN_LUN:
955105059Scognet		/*
956105059Scognet		 * Don't (yet?) support vendor
957105059Scognet		 * specific commands.
958105059Scognet		 */
959105059Scognet			TRM_DPRINTF(" XPT_EN_LUN \n");
960105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
961105059Scognet			xpt_done(pccb);
962105059Scognet			break;
963105059Scognet		/*
964105059Scognet		* Execute target I/O request
965105059Scognet		*/
966105059Scognet		case XPT_TARGET_IO:
967105059Scognet		/*
968105059Scognet		 * Don't (yet?) support vendor
969105059Scognet		 * specific commands.
970105059Scognet		 */
971105059Scognet			TRM_DPRINTF(" XPT_TARGET_IO \n");
972105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
973105059Scognet			xpt_done(pccb);
974105059Scognet			break;
975105059Scognet		/*
976105059Scognet		 * Accept Host Target Mode CDB
977105059Scognet       		 */
978105059Scognet		case XPT_ACCEPT_TARGET_IO:
979105059Scognet		/*
980105059Scognet		 * Don't (yet?) support vendor
981105059Scognet		 * specific commands.
982105059Scognet		 */
983105059Scognet			TRM_DPRINTF(" XPT_ACCEPT_TARGET_IO \n");
984105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
985105059Scognet			xpt_done(pccb);
986105059Scognet			break;
987105059Scognet		/*
988105059Scognet		 * Continue Host Target I/O Connection
989105059Scognet 		 */
990105059Scognet		case XPT_CONT_TARGET_IO:
991105059Scognet		/*
992105059Scognet		 * Don't (yet?) support vendor
993105059Scognet		 * specific commands.
994105059Scognet		 */
995105059Scognet			TRM_DPRINTF(" XPT_CONT_TARGET_IO \n");
996105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
997105059Scognet			xpt_done(pccb);
998105059Scognet			break;
999105059Scognet		/*
1000105059Scognet		 * Notify Host Target driver of event
1001105059Scognet 		 */
1002105059Scognet		case XPT_IMMED_NOTIFY:
1003105059Scognet			TRM_DPRINTF(" XPT_IMMED_NOTIFY \n");
1004105059Scognet	    		pccb->ccb_h.status = CAM_REQ_INVALID;
1005105059Scognet			xpt_done(pccb);
1006105059Scognet			break;
1007105059Scognet		/*
1008105059Scognet		 * Acknowledgement of event
1009105059Scognet       		 */
1010105059Scognet		case XPT_NOTIFY_ACK:
1011105059Scognet			TRM_DPRINTF(" XPT_NOTIFY_ACK \n");
1012105059Scognet	    		pccb->ccb_h.status = CAM_REQ_INVALID;
1013105059Scognet			xpt_done(pccb);
1014105059Scognet			break;
1015105059Scognet		/*
1016105059Scognet		 * XPT_VUNIQUE = 0x80
1017105059Scognet		 */
1018105059Scognet		case XPT_VUNIQUE:
1019105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
1020105059Scognet			xpt_done(pccb);
1021105059Scognet			break;
1022105059Scognet		default:
1023105059Scognet			pccb->ccb_h.status = CAM_REQ_INVALID;
1024105059Scognet			xpt_done(pccb);
1025105059Scognet			break;
1026105059Scognet	}
1027111158Scognet	splx(actionflags);
1028105059Scognet}
1029105059Scognet
1030105059Scognetstatic void
1031105059Scognettrm_poll(struct cam_sim *psim)
1032105059Scognet{
1033128090Scognet	trm_Interrupt(cam_sim_softc(psim));
1034105059Scognet}
1035105059Scognet
1036105059Scognetstatic void
1037105059Scognettrm_ResetDevParam(PACB pACB)
1038105059Scognet{
1039105059Scognet	PDCB		pDCB, pdcb;
1040105059Scognet	PNVRAMTYPE 	pEEpromBuf;
1041105059Scognet	u_int8_t	PeriodIndex;
1042105059Scognet
1043105059Scognet	pDCB = pACB->pLinkDCB;
1044105059Scognet	if (pDCB == NULL)
1045105059Scognet		return;
1046105059Scognet	pdcb = pDCB;
1047105059Scognet	do {
1048105059Scognet		pDCB->SyncMode  &= ~(SYNC_NEGO_DONE+ WIDE_NEGO_DONE);
1049105059Scognet		pDCB->SyncPeriod = 0;
1050105059Scognet		pDCB->SyncOffset = 0;
1051105059Scognet		pEEpromBuf = &trm_eepromBuf[pACB->AdapterUnit];
1052105059Scognet		pDCB->DevMode =
1053105059Scognet		  pEEpromBuf->NvramTarget[pDCB->TargetID].NvmTarCfg0;
1054105059Scognet		pDCB->AdpMode = pEEpromBuf->NvramChannelCfg;
1055105059Scognet		PeriodIndex =
1056105059Scognet		   pEEpromBuf->NvramTarget[pDCB->TargetID].NvmTarPeriod & 0x07;
1057111158Scognet		if (pACB->AdaptType == 1) /* is U2? */
1058111158Scognet			pDCB->MaxNegoPeriod = dc395u2x_clock_period[PeriodIndex];
1059111158Scognet		else
1060111158Scognet			pDCB->MaxNegoPeriod = dc395x_clock_period[PeriodIndex];
1061105059Scognet		if ((pDCB->DevMode & NTC_DO_WIDE_NEGO) &&
1062105059Scognet		    (pACB->Config & HCC_WIDE_CARD))
1063105059Scognet			pDCB->SyncMode |= WIDE_NEGO_ENABLE;
1064105059Scognet		pDCB = pDCB->pNextDCB;
1065105059Scognet	}
1066105059Scognet	while (pdcb != pDCB);
1067105059Scognet}
1068105059Scognet
1069105059Scognetstatic void
1070105059Scognettrm_RecoverSRB(PACB pACB)
1071105059Scognet{
1072105059Scognet	PDCB		pDCB, pdcb;
1073105059Scognet	PSRB		psrb, psrb2;
1074105059Scognet       	u_int16_t	cnt, i;
1075105059Scognet
1076105059Scognet	pDCB = pACB->pLinkDCB;
1077105059Scognet	if (pDCB == NULL)
1078105059Scognet		return;
1079105059Scognet	pdcb = pDCB;
1080105059Scognet	do {
1081105059Scognet		cnt = pdcb->GoingSRBCnt;
1082105059Scognet		psrb = pdcb->pGoingSRB;
1083105059Scognet		for (i = 0; i < cnt; i++) {
1084105059Scognet			psrb2 = psrb;
1085105059Scognet			psrb = psrb->pNextSRB;
1086105059Scognet			if (pdcb->pWaitingSRB) {
1087105059Scognet				psrb2->pNextSRB = pdcb->pWaitingSRB;
1088105059Scognet				pdcb->pWaitingSRB = psrb2;
1089105059Scognet			} else {
1090105059Scognet				pdcb->pWaitingSRB = psrb2;
1091111158Scognet				pdcb->pWaitingLastSRB = psrb2;
1092105059Scognet				psrb2->pNextSRB = NULL;
1093105059Scognet			}
1094105059Scognet		}
1095105059Scognet		pdcb->GoingSRBCnt = 0;
1096105059Scognet		pdcb->pGoingSRB = NULL;
1097105059Scognet		pdcb = pdcb->pNextDCB;
1098105059Scognet	}
1099105059Scognet	while (pdcb != pDCB);
1100105059Scognet}
1101105059Scognet
1102105059Scognetstatic void
1103105059Scognettrm_reset(PACB pACB)
1104105059Scognet{
1105105059Scognet	int		intflag;
1106105059Scognet	u_int16_t	i;
1107105059Scognet
1108105059Scognet    	TRM_DPRINTF("trm: RESET");
1109105059Scognet    	intflag = splcam();
1110105059Scognet	trm_reg_write8(0x00, TRMREG_DMA_INTEN);
1111105059Scognet	trm_reg_write8(0x00, TRMREG_SCSI_INTEN);
1112105059Scognet
1113105059Scognet	trm_ResetSCSIBus(pACB);
1114105059Scognet	for (i = 0; i < 500; i++)
1115105059Scognet		DELAY(1000);
1116105059Scognet    	trm_reg_write8(0x7F, TRMREG_SCSI_INTEN);
1117105059Scognet	/* Enable DMA interrupt	*/
1118105059Scognet	trm_reg_write8(EN_SCSIINTR, TRMREG_DMA_INTEN);
1119105059Scognet	/* Clear DMA FIFO */
1120105059Scognet	trm_reg_write8(CLRXFIFO, TRMREG_DMA_CONTROL);
1121105059Scognet	/* Clear SCSI FIFO */
1122105059Scognet	trm_reg_write16(DO_CLRFIFO,TRMREG_SCSI_CONTROL);
1123105059Scognet	trm_ResetDevParam(pACB);
1124105059Scognet	trm_DoingSRB_Done(pACB);
1125105059Scognet	pACB->pActiveDCB = NULL;
1126105059Scognet	pACB->ACBFlag = 0;/* RESET_DETECT, RESET_DONE ,RESET_DEV */
1127105059Scognet	trm_DoWaitingSRB(pACB);
1128105059Scognet	/* Tell the XPT layer that a bus reset occured    */
1129105059Scognet	if (pACB->ppath != NULL)
1130105059Scognet		xpt_async(AC_BUS_RESET, pACB->ppath, NULL);
1131105059Scognet	splx(intflag);
1132105059Scognet    	return;
1133105059Scognet}
1134105059Scognet
1135105059Scognetstatic u_int16_t
1136105059Scognettrm_StartSCSI(PACB pACB, PDCB pDCB, PSRB pSRB)
1137105059Scognet{
1138105059Scognet	u_int16_t	return_code;
1139111158Scognet	u_int8_t	scsicommand, i,command,identify_message;
1140105059Scognet	u_int8_t *	ptr;
1141105059Scognet	union  ccb	*pccb;
1142105059Scognet	struct ccb_scsiio *pcsio;
1143105059Scognet
1144105059Scognet	pccb  = pSRB->pccb;
1145105059Scognet	pcsio = &pccb->csio;
1146105059Scognet
1147105059Scognet	trm_reg_write8(pACB->AdaptSCSIID, TRMREG_SCSI_HOSTID);
1148105059Scognet	trm_reg_write8(pDCB->TargetID, TRMREG_SCSI_TARGETID);
1149105059Scognet	trm_reg_write8(pDCB->SyncPeriod, TRMREG_SCSI_SYNC);
1150105059Scognet	trm_reg_write8(pDCB->SyncOffset, TRMREG_SCSI_OFFSET);
1151105059Scognet	pSRB->ScsiPhase = PH_BUS_FREE;/* initial phase */
1152105059Scognet	/* Flush FIFO */
1153105059Scognet	trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL);
1154105059Scognet
1155105059Scognet	identify_message = pDCB->IdentifyMsg;
1156105059Scognet
1157105059Scognet   	if ((pSRB->CmdBlock[0] == INQUIRY) ||
1158105059Scognet	    (pSRB->CmdBlock[0] == REQUEST_SENSE) ||
1159105059Scognet	    (pSRB->SRBFlag & AUTO_REQSENSE)) {
1160105059Scognet		if (((pDCB->SyncMode & WIDE_NEGO_ENABLE) &&
1161111158Scognet		      !(pDCB->SyncMode & WIDE_NEGO_DONE))
1162105059Scognet		|| ((pDCB->SyncMode & SYNC_NEGO_ENABLE) &&
1163105059Scognet		  !(pDCB->SyncMode & SYNC_NEGO_DONE))) {
1164105059Scognet			if (!(pDCB->IdentifyMsg & 7) ||
1165105059Scognet			    (pSRB->CmdBlock[0] != INQUIRY)) {
1166105059Scognet				scsicommand = SCMD_SEL_ATNSTOP;
1167105059Scognet				pSRB->SRBState = SRB_MSGOUT;
1168105059Scognet				goto polling;
1169105059Scognet			}
1170105059Scognet		}
1171105059Scognet       	/*
1172105059Scognet       	* Send identify message
1173105059Scognet       	*/
1174105059Scognet		trm_reg_write8((identify_message & 0xBF) ,TRMREG_SCSI_FIFO);
1175105059Scognet		scsicommand = SCMD_SEL_ATN;
1176105059Scognet		pSRB->SRBState = SRB_START_;
1177105059Scognet	} else {
1178105059Scognet		/* not inquiry,request sense,auto request sense */
1179105059Scognet		/*
1180105059Scognet		 * Send identify message
1181105059Scognet		 */
1182105059Scognet		trm_reg_write8(identify_message,TRMREG_SCSI_FIFO);
1183105059Scognet		scsicommand = SCMD_SEL_ATN;
1184105059Scognet		pSRB->SRBState = SRB_START_;
1185105059Scognet		if (pDCB->SyncMode & EN_TAG_QUEUING) {
1186105059Scognet		  /* Send Tag message */
1187111158Scognet 			trm_reg_write8(MSG_SIMPLE_QTAG, TRMREG_SCSI_FIFO);
1188111158Scognet			trm_reg_write8(pSRB->TagNumber, TRMREG_SCSI_FIFO);
1189105059Scognet			scsicommand = SCMD_SEL_ATN3;
1190105059Scognet		}
1191105059Scognet	}
1192105059Scognetpolling:
1193105059Scognet	/*
1194105059Scognet	 * 	 Send CDB ..command block .........
1195105059Scognet	 */
1196105059Scognet   	if (pSRB->SRBFlag & AUTO_REQSENSE) {
1197105059Scognet		trm_reg_write8(REQUEST_SENSE, TRMREG_SCSI_FIFO);
1198105059Scognet		trm_reg_write8((pDCB->IdentifyMsg << 5), TRMREG_SCSI_FIFO);
1199105059Scognet		trm_reg_write8(0, TRMREG_SCSI_FIFO);
1200105059Scognet		trm_reg_write8(0, TRMREG_SCSI_FIFO);
1201105059Scognet		trm_reg_write8(pcsio->sense_len, TRMREG_SCSI_FIFO);
1202105059Scognet		trm_reg_write8(0, TRMREG_SCSI_FIFO);
1203105059Scognet	} else {
1204105059Scognet		ptr = (u_int8_t *) pSRB->CmdBlock;
1205105059Scognet		for (i = 0; i < pSRB->ScsiCmdLen ; i++) {
1206105059Scognet			command = *ptr++;
1207105059Scognet			trm_reg_write8(command,TRMREG_SCSI_FIFO);
1208105059Scognet		}
1209105059Scognet	}
1210105059Scognet	if (trm_reg_read16(TRMREG_SCSI_STATUS) & SCSIINTERRUPT) {
1211105059Scognet	    /*
1212105059Scognet	     * If trm_StartSCSI return 1 :
1213105059Scognet	     * current interrupt status is interrupt disreenable
1214105059Scognet	     * It's said that SCSI processor has more one SRB need to do,
1215105059Scognet     	     * SCSI processor has been occupied by one SRB.
1216105059Scognet	     */
1217105059Scognet		pSRB->SRBState = SRB_READY;
1218105059Scognet		return_code = 1;
1219105059Scognet	} else {
1220105059Scognet	  /*
1221105059Scognet	   * If trm_StartSCSI return 0 :
1222105059Scognet	   * current interrupt status is interrupt enable
1223105059Scognet	   * It's said that SCSI processor is unoccupied
1224105059Scognet	   */
1225105059Scognet		pSRB->ScsiPhase  = SCSI_NOP1; /* SCSI bus free Phase */
1226105059Scognet		pACB->pActiveDCB = pDCB;
1227105059Scognet		pDCB->pActiveSRB = pSRB;
1228105059Scognet		return_code = 0;
1229105059Scognet		trm_reg_write16(DO_DATALATCH | DO_HWRESELECT,
1230105059Scognet		    TRMREG_SCSI_CONTROL);/* it's important for atn stop*/
1231105059Scognet		/*
1232105059Scognet		 * SCSI cammand
1233105059Scognet		 */
1234105059Scognet		trm_reg_write8(scsicommand,TRMREG_SCSI_COMMAND);
1235105059Scognet	}
1236105059Scognet	return (return_code);
1237105059Scognet}
1238105059Scognet
1239105059Scognetstatic void
1240105059Scognettrm_Interrupt(vpACB)
1241105059Scognetvoid *vpACB;
1242105059Scognet{
1243105059Scognet	PACB		pACB;
1244105059Scognet	PDCB		pDCB;
1245105059Scognet	PSRB		pSRB;
1246105059Scognet	u_int16_t	phase;
1247111158Scognet	void		(*stateV)(PACB, PSRB, u_int16_t *);
1248111158Scognet	u_int16_t	scsi_status=0;
1249111158Scognet	u_int8_t	scsi_intstatus;
1250105059Scognet
1251105059Scognet	pACB = vpACB;
1252105059Scognet
1253105059Scognet	scsi_status = trm_reg_read16(TRMREG_SCSI_STATUS);
1254105059Scognet	if (!(scsi_status & SCSIINTERRUPT)) {
1255105059Scognet		TRM_DPRINTF("trm_Interrupt: TRMREG_SCSI_STATUS scsi_status = NULL ,return......");
1256105059Scognet	    	return;
1257105059Scognet	}
1258105059Scognet	TRM_DPRINTF("scsi_status=%2x,",scsi_status);
1259105059Scognet
1260105059Scognet    	scsi_intstatus = trm_reg_read8(TRMREG_SCSI_INTSTATUS);
1261105059Scognet
1262105059Scognet	TRM_DPRINTF("scsi_intstatus=%2x,",scsi_intstatus);
1263105059Scognet
1264105059Scognet    	if (scsi_intstatus & (INT_SELTIMEOUT | INT_DISCONNECT)) {
1265105059Scognet		trm_Disconnect(pACB);
1266105059Scognet		return;
1267105059Scognet	}
1268105059Scognet
1269105059Scognet	if (scsi_intstatus & INT_RESELECTED) {
1270105059Scognet		trm_Reselect(pACB);
1271105059Scognet		return;
1272105059Scognet	}
1273105059Scognet	if (scsi_intstatus & INT_SCSIRESET) {
1274105059Scognet		trm_ScsiRstDetect(pACB);
1275105059Scognet		return;
1276105059Scognet	}
1277105059Scognet
1278105059Scognet	if (scsi_intstatus & (INT_BUSSERVICE | INT_CMDDONE)) {
1279105059Scognet		pDCB = pACB->pActiveDCB;
1280126053Scognet		KASSERT(pDCB != NULL, ("no active DCB"));
1281105059Scognet		pSRB = pDCB->pActiveSRB;
1282126053Scognet		if (pDCB->DCBFlag & ABORT_DEV_)
1283105059Scognet				trm_EnableMsgOutAbort1(pACB, pSRB);
1284105059Scognet		phase = (u_int16_t) pSRB->ScsiPhase;  /* phase: */
1285105059Scognet		stateV = (void *) trm_SCSI_phase0[phase];
1286105059Scognet		stateV(pACB, pSRB, &scsi_status);
1287105059Scognet		pSRB->ScsiPhase = scsi_status & PHASEMASK;
1288105059Scognet		/* phase:0,1,2,3,4,5,6,7 */
1289105059Scognet		phase = (u_int16_t) scsi_status & PHASEMASK;
1290105059Scognet		stateV = (void *) trm_SCSI_phase1[phase];
1291105059Scognet		stateV(pACB, pSRB, &scsi_status);
1292105059Scognet	}
1293105059Scognet}
1294105059Scognet
1295105059Scognetstatic void
1296111158Scognettrm_MsgOutPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
1297105059Scognet{
1298105059Scognet
1299105059Scognet	if (pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT))
1300105059Scognet		*pscsi_status = PH_BUS_FREE;
1301105059Scognet	/*.. initial phase*/
1302105059Scognet}
1303105059Scognet
1304105059Scognetstatic void
1305111158Scognettrm_MsgOutPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
1306105059Scognet{
1307105059Scognet	u_int8_t	bval;
1308105059Scognet	u_int16_t	i, cnt;
1309105059Scognet	u_int8_t *	ptr;
1310105059Scognet	PDCB		pDCB;
1311105059Scognet
1312105059Scognet	trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL);
1313105059Scognet	pDCB = pACB->pActiveDCB;
1314105059Scognet	if (!(pSRB->SRBState & SRB_MSGOUT)) {
1315105059Scognet		cnt = pSRB->MsgCnt;
1316105059Scognet		if (cnt) {
1317105059Scognet			ptr = (u_int8_t *) pSRB->MsgOutBuf;
1318105059Scognet			for (i = 0; i < cnt; i++) {
1319105059Scognet				trm_reg_write8(*ptr, TRMREG_SCSI_FIFO);
1320105059Scognet				ptr++;
1321105059Scognet			}
1322105059Scognet			pSRB->MsgCnt = 0;
1323105059Scognet			if ((pDCB->DCBFlag & ABORT_DEV_) &&
1324105059Scognet			    (pSRB->MsgOutBuf[0] == MSG_ABORT)) {
1325105059Scognet				pSRB->SRBState = SRB_ABORT_SENT;
1326105059Scognet			}
1327105059Scognet		} else {
1328105059Scognet			bval = MSG_ABORT;
1329105059Scognet			if ((pSRB->CmdBlock[0] == INQUIRY) ||
1330105059Scognet					(pSRB->CmdBlock[0] == REQUEST_SENSE) ||
1331105059Scognet					(pSRB->SRBFlag & AUTO_REQSENSE)) {
1332105059Scognet				if (pDCB->SyncMode & SYNC_NEGO_ENABLE) {
1333105059Scognet					goto  mop1;
1334105059Scognet				}
1335105059Scognet			}
1336105059Scognet			trm_reg_write8(bval, TRMREG_SCSI_FIFO);
1337105059Scognet		}
1338105059Scognet	} else {
1339105059Scognetmop1:   /* message out phase */
1340105059Scognet		if (!(pSRB->SRBState & SRB_DO_WIDE_NEGO)
1341105059Scognet		    && (pDCB->SyncMode & WIDE_NEGO_ENABLE)) {
1342105059Scognet		  /*
1343105059Scognet	   	   * WIDE DATA TRANSFER REQUEST code (03h)
1344105059Scognet		   */
1345105059Scognet			pDCB->SyncMode &= ~(SYNC_NEGO_DONE | EN_ATN_STOP);
1346105059Scognet			trm_reg_write8((pDCB->IdentifyMsg & 0xBF),
1347105059Scognet			    TRMREG_SCSI_FIFO);
1348105059Scognet			trm_reg_write8(MSG_EXTENDED,TRMREG_SCSI_FIFO);
1349105059Scognet			/* (01h) */
1350105059Scognet			trm_reg_write8(2,TRMREG_SCSI_FIFO);
1351105059Scognet			/* Message length (02h) */
1352105059Scognet			trm_reg_write8(3,TRMREG_SCSI_FIFO);
1353105059Scognet			/* wide data xfer (03h) */
1354105059Scognet			trm_reg_write8(1,TRMREG_SCSI_FIFO);
1355105059Scognet			/* width:0(8bit),1(16bit),2(32bit) */
1356105059Scognet			pSRB->SRBState |= SRB_DO_WIDE_NEGO;
1357105059Scognet		} else if (!(pSRB->SRBState & SRB_DO_SYNC_NEGO)
1358105059Scognet		    && (pDCB->SyncMode & SYNC_NEGO_ENABLE)) {
1359105059Scognet		  /*
1360105059Scognet	   	   * SYNCHRONOUS DATA TRANSFER REQUEST code (01h)
1361105059Scognet		   */
1362105059Scognet			if (!(pDCB->SyncMode & WIDE_NEGO_DONE))
1363105059Scognet				trm_reg_write8((pDCB->IdentifyMsg & 0xBF),
1364105059Scognet						TRMREG_SCSI_FIFO);
1365105059Scognet			trm_reg_write8(MSG_EXTENDED,TRMREG_SCSI_FIFO);
1366105059Scognet		  /* (01h) */
1367105059Scognet			trm_reg_write8(3,TRMREG_SCSI_FIFO);
1368105059Scognet		  /* Message length (03h) */
1369105059Scognet			trm_reg_write8(1,TRMREG_SCSI_FIFO);
1370105059Scognet		  /* SYNCHRONOUS DATA TRANSFER REQUEST code (01h) */
1371105059Scognet			trm_reg_write8(pDCB->MaxNegoPeriod,TRMREG_SCSI_FIFO);
1372105059Scognet		  /* Transfer peeriod factor */
1373111158Scognet			trm_reg_write8((pACB->AdaptType == 1) ? 31 : 15,
1374111158Scognet			    TRMREG_SCSI_FIFO);
1375105059Scognet		  /* REQ/ACK offset */
1376105059Scognet			pSRB->SRBState |= SRB_DO_SYNC_NEGO;
1377105059Scognet		}
1378105059Scognet	}
1379105059Scognet	trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1380105059Scognet	/* it's important for atn stop */
1381105059Scognet	/*
1382105059Scognet	 * SCSI cammand
1383105059Scognet	 */
1384105059Scognet	trm_reg_write8(SCMD_FIFO_OUT, TRMREG_SCSI_COMMAND);
1385105059Scognet}
1386105059Scognet
1387105059Scognetstatic void
1388111158Scognettrm_CommandPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
1389105059Scognet{
1390105059Scognet
1391105059Scognet}
1392105059Scognet
1393105059Scognetstatic void
1394111158Scognettrm_CommandPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
1395105059Scognet{
1396105059Scognet	PDCB			pDCB;
1397105059Scognet	u_int8_t *		ptr;
1398105059Scognet	u_int16_t		i, cnt;
1399105059Scognet	union  ccb		*pccb;
1400105059Scognet	struct ccb_scsiio	*pcsio;
1401105059Scognet
1402105059Scognet	pccb  = pSRB->pccb;
1403105059Scognet	pcsio = &pccb->csio;
1404105059Scognet
1405105059Scognet	trm_reg_write16(DO_CLRATN | DO_CLRFIFO , TRMREG_SCSI_CONTROL);
1406105059Scognet	if (!(pSRB->SRBFlag & AUTO_REQSENSE)) {
1407105059Scognet		cnt = (u_int16_t) pSRB->ScsiCmdLen;
1408105059Scognet		ptr = (u_int8_t *) pSRB->CmdBlock;
1409105059Scognet		for (i = 0; i < cnt; i++) {
1410105059Scognet			trm_reg_write8(*ptr, TRMREG_SCSI_FIFO);
1411105059Scognet			ptr++;
1412105059Scognet		}
1413105059Scognet	} else {
1414105059Scognet		trm_reg_write8(REQUEST_SENSE, TRMREG_SCSI_FIFO);
1415105059Scognet		pDCB = pACB->pActiveDCB;
1416105059Scognet		/* target id */
1417105059Scognet		trm_reg_write8((pDCB->IdentifyMsg << 5), TRMREG_SCSI_FIFO);
1418105059Scognet		trm_reg_write8(0, TRMREG_SCSI_FIFO);
1419105059Scognet		trm_reg_write8(0, TRMREG_SCSI_FIFO);
1420105059Scognet		/* sizeof(struct scsi_sense_data) */
1421105059Scognet		trm_reg_write8(pcsio->sense_len, TRMREG_SCSI_FIFO);
1422105059Scognet		trm_reg_write8(0, TRMREG_SCSI_FIFO);
1423105059Scognet	}
1424105059Scognet	pSRB->SRBState = SRB_COMMAND;
1425105059Scognet	trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1426105059Scognet	/* it's important for atn stop*/
1427105059Scognet	/*
1428105059Scognet	 * SCSI cammand
1429105059Scognet	 */
1430105059Scognet	trm_reg_write8(SCMD_FIFO_OUT, TRMREG_SCSI_COMMAND);
1431105059Scognet}
1432105059Scognet
1433105059Scognetstatic void
1434111158Scognettrm_DataOutPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
1435105059Scognet{
1436105059Scognet	PDCB		pDCB;
1437105059Scognet	u_int8_t	TempDMAstatus,SGIndexTemp;
1438105059Scognet	u_int16_t	scsi_status;
1439105059Scognet	PSEG		pseg;
1440105059Scognet	u_long		TempSRBXferredLength,dLeftCounter=0;
1441105059Scognet
1442105059Scognet	pDCB = pSRB->pSRBDCB;
1443105059Scognet	scsi_status = *pscsi_status;
1444105059Scognet
1445105059Scognet	if (!(pSRB->SRBState & SRB_XFERPAD)) {
1446105059Scognet		if (scsi_status & PARITYERROR)
1447105059Scognet			pSRB->SRBStatus |= PARITY_ERROR;
1448105059Scognet		if (!(scsi_status & SCSIXFERDONE)) {
1449105059Scognet      		  /*
1450105059Scognet		   * when data transfer from DMA FIFO to SCSI FIFO
1451105059Scognet		   * if there was some data left in SCSI FIFO
1452105059Scognet		   */
1453105059Scognet  			dLeftCounter = (u_long)
1454111158Scognet			  (trm_reg_read8(TRMREG_SCSI_FIFOCNT) & 0x3F);
1455105059Scognet			if (pDCB->SyncPeriod & WIDE_SYNC) {
1456105059Scognet			  /*
1457105059Scognet		   	   * if WIDE scsi SCSI FIFOCNT unit is word
1458105059Scognet	   		   * so need to * 2
1459105059Scognet   			   */
1460105059Scognet				dLeftCounter <<= 1;
1461105059Scognet			}
1462105059Scognet		}
1463105059Scognet		/*
1464105059Scognet		 * caculate all the residue data that not yet tranfered
1465105059Scognet		 * SCSI transfer counter + left in SCSI FIFO data
1466105059Scognet		 *
1467105059Scognet		 * .....TRM_SCSI_COUNTER (24bits)
1468105059Scognet		 * The counter always decrement by one for every SCSI byte
1469105059Scognet		 *transfer.
1470105059Scognet		 * .....TRM_SCSI_FIFOCNT (5bits)
1471105059Scognet		 * The counter is SCSI FIFO offset counter
1472105059Scognet		 */
1473105059Scognet		dLeftCounter += trm_reg_read32(TRMREG_SCSI_COUNTER);
1474105059Scognet		if (dLeftCounter == 1) {
1475105059Scognet			dLeftCounter = 0;
1476105059Scognet			trm_reg_write16(DO_CLRFIFO,TRMREG_SCSI_CONTROL);
1477105059Scognet		}
1478105059Scognet		if ((dLeftCounter == 0) ||
1479105059Scognet		    (scsi_status & SCSIXFERCNT_2_ZERO)) {
1480105059Scognet			TempDMAstatus = trm_reg_read8(TRMREG_DMA_STATUS);
1481105059Scognet			while (!(TempDMAstatus & DMAXFERCOMP)) {
1482105059Scognet				TempDMAstatus =
1483105059Scognet				  trm_reg_read8(TRMREG_DMA_STATUS);
1484105059Scognet			}
1485105059Scognet			pSRB->SRBTotalXferLength = 0;
1486105059Scognet		} else {
1487105059Scognet		  /* Update SG list		*/
1488105059Scognet		  /*
1489105059Scognet	   	   * if transfer not yet complete
1490105059Scognet   		   * there were some data residue in SCSI FIFO or
1491105059Scognet		   * SCSI transfer counter not empty
1492105059Scognet		   */
1493105059Scognet			if (pSRB->SRBTotalXferLength != dLeftCounter) {
1494105059Scognet			  /*
1495105059Scognet		  	   * data that had transferred length
1496105059Scognet	   		   */
1497105059Scognet				TempSRBXferredLength =
1498105059Scognet				  pSRB->SRBTotalXferLength - dLeftCounter;
1499105059Scognet				/*
1500105059Scognet				 * next time to be transferred length
1501105059Scognet				 */
1502105059Scognet				pSRB->SRBTotalXferLength = dLeftCounter;
1503105059Scognet				/*
1504105059Scognet				 * parsing from last time disconnect SRBSGIndex
1505105059Scognet				 */
1506105059Scognet				pseg =
1507111158Scognet				  pSRB->pSRBSGL + pSRB->SRBSGIndex;
1508105059Scognet				for (SGIndexTemp = pSRB->SRBSGIndex;
1509105059Scognet				    SGIndexTemp < pSRB->SRBSGCount;
1510105059Scognet				    SGIndexTemp++) {
1511105059Scognet					/*
1512105059Scognet					 * find last time which SG transfer be
1513105059Scognet					 * disconnect
1514105059Scognet					 */
1515105059Scognet					if (TempSRBXferredLength >=
1516105059Scognet					    pseg->length)
1517105059Scognet						TempSRBXferredLength -=
1518105059Scognet						  pseg->length;
1519105059Scognet					else {
1520105059Scognet				  	  /*
1521105059Scognet			   		   * update last time disconnected SG
1522105059Scognet					   * list
1523105059Scognet				   	   */
1524105059Scognet						pseg->length -=
1525105059Scognet						  TempSRBXferredLength;
1526105059Scognet						/* residue data length  */
1527105059Scognet						pseg->address +=
1528105059Scognet						  TempSRBXferredLength;
1529105059Scognet						/* residue data pointer */
1530105059Scognet						pSRB->SRBSGIndex = SGIndexTemp;
1531105059Scognet						break;
1532105059Scognet					}
1533105059Scognet					pseg++;
1534105059Scognet				}
1535105059Scognet			}
1536105059Scognet		}
1537105059Scognet	}
1538105059Scognet	trm_reg_write8(STOPDMAXFER ,TRMREG_DMA_CONTROL);
1539105059Scognet}
1540105059Scognet
1541105059Scognet
1542105059Scognetstatic void
1543111158Scognettrm_DataOutPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
1544105059Scognet{
1545105059Scognet	u_int16_t	ioDir;
1546105059Scognet	/*
1547105059Scognet	 * do prepare befor transfer when data out phase
1548105059Scognet	 */
1549105059Scognet
1550105059Scognet	ioDir = XFERDATAOUT;
1551105059Scognet	trm_DataIO_transfer(pACB, pSRB, ioDir);
1552105059Scognet}
1553105059Scognet
1554105059Scognetstatic void
1555111158Scognettrm_DataInPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
1556105059Scognet{
1557111158Scognet	u_int8_t	TempDMAstatus, SGIndexTemp;
1558105059Scognet	u_int16_t	scsi_status;
1559105059Scognet	PSEG		pseg;
1560105059Scognet	u_long		TempSRBXferredLength,dLeftCounter = 0;
1561105059Scognet
1562105059Scognet    	scsi_status = *pscsi_status;
1563105059Scognet	if (!(pSRB->SRBState & SRB_XFERPAD)) {
1564105059Scognet		if (scsi_status & PARITYERROR)
1565105059Scognet			pSRB->SRBStatus |= PARITY_ERROR;
1566105059Scognet		dLeftCounter += trm_reg_read32(TRMREG_SCSI_COUNTER);
1567105059Scognet		if ((dLeftCounter == 0) || (scsi_status & SCSIXFERCNT_2_ZERO)) {
1568111158Scognet			TempDMAstatus = trm_reg_read8(TRMREG_DMA_STATUS);
1569111158Scognet			while (!(TempDMAstatus & DMAXFERCOMP))
1570111158Scognet				TempDMAstatus = trm_reg_read8(TRMREG_DMA_STATUS);
1571105059Scognet			pSRB->SRBTotalXferLength = 0;
1572105059Scognet		} else {
1573105059Scognet	  	  /*
1574105059Scognet   		   * parsing the case:
1575105059Scognet	   	   * when a transfer not yet complete
1576105059Scognet	   	   * but be disconnected by uper layer
1577105059Scognet	   	   * if transfer not yet complete
1578105059Scognet	   	   * there were some data residue in SCSI FIFO or
1579105059Scognet	   	   * SCSI transfer counter not empty
1580105059Scognet	   	   */
1581105059Scognet		  if (pSRB->SRBTotalXferLength != dLeftCounter) {
1582105059Scognet				/*
1583105059Scognet				 * data that had transferred length
1584105059Scognet				 */
1585105059Scognet		  	TempSRBXferredLength =
1586105059Scognet			  pSRB->SRBTotalXferLength - dLeftCounter;
1587105059Scognet				/*
1588105059Scognet			 	 * next time to be transferred length
1589105059Scognet				 */
1590105059Scognet			pSRB->SRBTotalXferLength = dLeftCounter;
1591105059Scognet				/*
1592105059Scognet				 * parsing from last time disconnect SRBSGIndex
1593105059Scognet				 */
1594111158Scognet			pseg = pSRB->pSRBSGL + pSRB->SRBSGIndex;
1595105059Scognet			for (SGIndexTemp = pSRB->SRBSGIndex;
1596105059Scognet			    SGIndexTemp < pSRB->SRBSGCount;
1597105059Scognet			    SGIndexTemp++) {
1598105059Scognet			  /*
1599105059Scognet	   		   * find last time which SG transfer be disconnect
1600105059Scognet	   		   */
1601105059Scognet	 			if (TempSRBXferredLength >= pseg->length)
1602105059Scognet					TempSRBXferredLength -= pseg->length;
1603105059Scognet				else {
1604105059Scognet		  		  /*
1605105059Scognet   				   * update last time disconnected SG list
1606105059Scognet				   */
1607105059Scognet					pseg->length -= TempSRBXferredLength;
1608105059Scognet					/* residue data length  */
1609105059Scognet					pseg->address += TempSRBXferredLength;
1610105059Scognet					/* residue data pointer */
1611105059Scognet					pSRB->SRBSGIndex = SGIndexTemp;
1612105059Scognet					break;
1613105059Scognet				}
1614105059Scognet				pseg++;
1615105059Scognet			}
1616105059Scognet	  	  }
1617105059Scognet		}
1618105059Scognet	}
1619105059Scognet}
1620105059Scognet
1621105059Scognetstatic void
1622111158Scognettrm_DataInPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
1623105059Scognet{
1624105059Scognet	u_int16_t	ioDir;
1625105059Scognet	/*
1626105059Scognet	 * do prepare befor transfer when data in phase
1627105059Scognet	 */
1628105059Scognet
1629105059Scognet	ioDir = XFERDATAIN;
1630105059Scognet	trm_DataIO_transfer(pACB, pSRB, ioDir);
1631105059Scognet}
1632105059Scognet
1633105059Scognetstatic void
1634105059Scognettrm_DataIO_transfer(PACB pACB, PSRB pSRB, u_int16_t ioDir)
1635105059Scognet{
1636105059Scognet	u_int8_t	bval;
1637105059Scognet	PDCB		pDCB;
1638105059Scognet
1639105059Scognet	pDCB = pSRB->pSRBDCB;
1640105059Scognet	if (pSRB->SRBSGIndex < pSRB->SRBSGCount) {
1641105059Scognet		if (pSRB->SRBTotalXferLength != 0) {
1642105059Scognet			/*
1643105059Scognet			 * load what physical address of Scatter/Gather list
1644105059Scognet			 table want to be transfer
1645105059Scognet			 */
1646111158Scognet			TRM_DPRINTF(" SG->address=%8x \n",pSRB->pSRBSGL->address);
1647111158Scognet			TRM_DPRINTF(" SG->length=%8x \n",pSRB->pSRBSGL->length);
1648111158Scognet			TRM_DPRINTF(" pDCB->SyncPeriod=%x \n",pDCB->SyncPeriod);
1649111158Scognet			TRM_DPRINTF(" pSRB->pSRBSGL=%8x \n",(unsigned int)pSRB->pSRBSGL);
1650111158Scognet			TRM_DPRINTF(" pSRB->SRBSGPhyAddr=%8x \n",pSRB->SRBSGPhyAddr);
1651111158Scognet			TRM_DPRINTF(" pSRB->SRBSGIndex=%d \n",pSRB->SRBSGIndex);
1652111158Scognet			TRM_DPRINTF(" pSRB->SRBSGCount=%d \n",pSRB->SRBSGCount);
1653111158Scognet			TRM_DPRINTF(" pSRB->SRBTotalXferLength=%d \n",pSRB->SRBTotalXferLength);
1654111158Scognet
1655105059Scognet			pSRB->SRBState = SRB_DATA_XFER;
1656105059Scognet			trm_reg_write32(0, TRMREG_DMA_XHIGHADDR);
1657105059Scognet			trm_reg_write32(
1658105059Scognet			    (pSRB->SRBSGPhyAddr +
1659105059Scognet			     ((u_long)pSRB->SRBSGIndex << 3)),
1660105059Scognet			    TRMREG_DMA_XLOWADDR);
1661105059Scognet			/*
1662105059Scognet			 * load how many bytes in the Scatter/Gather
1663105059Scognet			 * list table
1664105059Scognet			 */
1665105059Scognet			trm_reg_write32(
1666105059Scognet			    ((u_long)(pSRB->SRBSGCount - pSRB->SRBSGIndex) << 3),
1667105059Scognet			    TRMREG_DMA_XCNT);
1668105059Scognet			/*
1669105059Scognet			 * load total transfer length (24bits) max value
1670105059Scognet			 * 16Mbyte
1671105059Scognet			 */
1672105059Scognet			trm_reg_write32(pSRB->SRBTotalXferLength,
1673105059Scognet			    TRMREG_SCSI_COUNTER);
1674105059Scognet			/* Start DMA transfer */
1675105059Scognet			trm_reg_write16(ioDir, TRMREG_DMA_COMMAND);
1676105059Scognet			/* Start SCSI transfer */
1677105059Scognet			trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1678105059Scognet			/* it's important for atn stop */
1679105059Scognet			/*
1680105059Scognet			 * SCSI cammand
1681105059Scognet			 */
1682105059Scognet			bval = (ioDir == XFERDATAOUT) ?
1683105059Scognet			  SCMD_DMA_OUT : SCMD_DMA_IN;
1684105059Scognet			trm_reg_write8(bval, TRMREG_SCSI_COMMAND);
1685105059Scognet		} else {
1686105059Scognet		  /* xfer pad */
1687105059Scognet			if (pSRB->SRBSGCount) {
1688105059Scognet				pSRB->AdaptStatus = H_OVER_UNDER_RUN;
1689105059Scognet				pSRB->SRBStatus |= OVER_RUN;
1690105059Scognet			}
1691105059Scognet			if (pDCB->SyncPeriod & WIDE_SYNC)
1692105059Scognet				trm_reg_write32(2,TRMREG_SCSI_COUNTER);
1693105059Scognet			else
1694105059Scognet				trm_reg_write32(1,TRMREG_SCSI_COUNTER);
1695105059Scognet			if (ioDir == XFERDATAOUT)
1696105059Scognet				trm_reg_write16(0, TRMREG_SCSI_FIFO);
1697105059Scognet			else
1698105059Scognet				trm_reg_read16(TRMREG_SCSI_FIFO);
1699105059Scognet			pSRB->SRBState |= SRB_XFERPAD;
1700105059Scognet			trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1701105059Scognet			/* it's important for atn stop */
1702105059Scognet			/*
1703105059Scognet			 * SCSI cammand
1704105059Scognet			 */
1705105059Scognet			bval = (ioDir == XFERDATAOUT) ?
1706105059Scognet			  SCMD_FIFO_OUT : SCMD_FIFO_IN;
1707105059Scognet			trm_reg_write8(bval, TRMREG_SCSI_COMMAND);
1708105059Scognet		}
1709105059Scognet	}
1710105059Scognet}
1711105059Scognet
1712105059Scognetstatic void
1713111158Scognettrm_StatusPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
1714105059Scognet{
1715105059Scognet
1716105059Scognet	pSRB->TargetStatus = trm_reg_read8(TRMREG_SCSI_FIFO);
1717105059Scognet	pSRB->SRBState = SRB_COMPLETED;
1718105059Scognet	*pscsi_status = PH_BUS_FREE;
1719105059Scognet	/*.. initial phase*/
1720105059Scognet	trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1721105059Scognet	/* it's important for atn stop */
1722105059Scognet	/*
1723105059Scognet	 * SCSI cammand
1724105059Scognet	 */
1725105059Scognet	trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
1726105059Scognet}
1727105059Scognet
1728105059Scognet
1729105059Scognet
1730105059Scognetstatic void
1731111158Scognettrm_StatusPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
1732105059Scognet{
1733105059Scognet
1734105059Scognet	if (trm_reg_read16(TRMREG_DMA_COMMAND) & 0x0001) {
1735105059Scognet		if (!(trm_reg_read8(TRMREG_SCSI_FIFOCNT) & 0x40))
1736105059Scognet	       		trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL);
1737105059Scognet		if (!(trm_reg_read16(TRMREG_DMA_FIFOCNT) & 0x8000))
1738105059Scognet			trm_reg_write8(CLRXFIFO, TRMREG_DMA_CONTROL);
1739105059Scognet	} else {
1740105059Scognet		if (!(trm_reg_read16(TRMREG_DMA_FIFOCNT) & 0x8000))
1741105059Scognet			trm_reg_write8(CLRXFIFO, TRMREG_DMA_CONTROL);
1742105059Scognet		if (!(trm_reg_read8(TRMREG_SCSI_FIFOCNT) & 0x40))
1743105059Scognet			trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL);
1744105059Scognet	}
1745105059Scognet	pSRB->SRBState = SRB_STATUS;
1746105059Scognet	trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1747105059Scognet	/* it's important for atn stop */
1748105059Scognet	/*
1749105059Scognet	 * SCSI cammand
1750105059Scognet	 */
1751105059Scognet	trm_reg_write8(SCMD_COMP, TRMREG_SCSI_COMMAND);
1752105059Scognet}
1753105059Scognet
1754105059Scognet/*
1755105059Scognet *scsiiom
1756105059Scognet *       trm_MsgInPhase0: one of trm_SCSI_phase0[] vectors
1757105059Scognet *            stateV = (void *) trm_SCSI_phase0[phase]
1758105059Scognet *		           if phase =7
1759105059Scognet * extended message codes:
1760105059Scognet *
1761105059Scognet *   code        description
1762105059Scognet *
1763105059Scognet *    02h        Reserved
1764105059Scognet *    00h        MODIFY DATA  POINTER
1765105059Scognet *    01h        SYNCHRONOUS DATA TRANSFER REQUEST
1766105059Scognet *    03h        WIDE DATA TRANSFER REQUEST
1767105059Scognet * 04h - 7Fh     Reserved
1768105059Scognet * 80h - FFh     Vendor specific
1769105059Scognet *
1770105059Scognet */
1771105059Scognet
1772105059Scognetstatic void
1773111158Scognettrm_MsgInPhase0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
1774105059Scognet{
1775105059Scognet	u_int8_t	message_in_code,bIndex,message_in_tag_id;
1776105059Scognet	PDCB		pDCB;
1777105059Scognet	PSRB		pSRBTemp;
1778105059Scognet
1779105059Scognet	pDCB = pACB->pActiveDCB;
1780105059Scognet
1781105059Scognet	message_in_code = trm_reg_read8(TRMREG_SCSI_FIFO);
1782105059Scognet	if (!(pSRB->SRBState & SRB_EXTEND_MSGIN)) {
1783105059Scognet		if (message_in_code == MSG_DISCONNECT) {
1784105059Scognet			pSRB->SRBState = SRB_DISCONNECT;
1785111158Scognet			*pscsi_status = PH_BUS_FREE; /* .. initial phase */
1786111158Scognet			/* it's important for atn stop */
1787111158Scognet			trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1788111158Scognet			/*
1789111158Scognet			 * SCSI command
1790111158Scognet			 */
1791111158Scognet			trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
1792111158Scognet			return;
1793105059Scognet		} else if (message_in_code == MSG_SAVE_PTR) {
1794111158Scognet			*pscsi_status = PH_BUS_FREE; /* .. initial phase */
1795111158Scognet			/* it's important for atn stop */
1796111158Scognet			trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1797111158Scognet			/*
1798111158Scognet			 * SCSI command
1799111158Scognet			 */
1800111158Scognet			trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
1801111158Scognet			return;
1802105059Scognet		} else if ((message_in_code == MSG_EXTENDED) ||
1803105059Scognet		    ((message_in_code >= MSG_SIMPLE_QTAG) &&
1804105059Scognet		     (message_in_code <= MSG_ORDER_QTAG))) {
1805105059Scognet			pSRB->SRBState |= SRB_EXTEND_MSGIN;
1806105059Scognet		    	pSRB->MsgInBuf[0] = message_in_code;
1807105059Scognet			/* extended message      (01h) */
1808105059Scognet			pSRB->MsgCnt = 1;
1809105059Scognet			pSRB->pMsgPtr = &pSRB->MsgInBuf[1];
1810105059Scognet			/* extended message length (n) */
1811111158Scognet			*pscsi_status = PH_BUS_FREE; /* .. initial phase */
1812111158Scognet			/* it's important for atn stop */
1813111158Scognet			trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1814111158Scognet			/*
1815111158Scognet			 * SCSI command
1816111158Scognet			 */
1817111158Scognet			trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
1818111158Scognet			return;
1819105059Scognet		} else if (message_in_code == MSG_REJECT_) {
1820105059Scognet			/* Reject message */
1821105059Scognet			if (pDCB->SyncMode & WIDE_NEGO_ENABLE) {
1822105059Scognet			  /* do wide nego reject */
1823105059Scognet				pDCB = pSRB->pSRBDCB;
1824105059Scognet				pDCB->SyncMode |= WIDE_NEGO_DONE;
1825105059Scognet				pDCB->SyncMode &= ~(SYNC_NEGO_DONE |
1826105059Scognet				    EN_ATN_STOP | WIDE_NEGO_ENABLE);
1827105059Scognet				pSRB->SRBState &= ~(SRB_DO_WIDE_NEGO+SRB_MSGIN);
1828105059Scognet				if ((pDCB->SyncMode & SYNC_NEGO_ENABLE)
1829105059Scognet				    && !(pDCB->SyncMode & SYNC_NEGO_DONE)) {
1830105059Scognet				  /* Set ATN, in case ATN was clear */
1831105059Scognet					pSRB->SRBState |= SRB_MSGOUT;
1832105059Scognet					trm_reg_write16(
1833105059Scognet					    DO_SETATN,
1834105059Scognet					    TRMREG_SCSI_CONTROL);
1835105059Scognet				} else {
1836105059Scognet			  	  /* Clear ATN */
1837105059Scognet					trm_reg_write16(
1838105059Scognet					    DO_CLRATN,
1839105059Scognet					    TRMREG_SCSI_CONTROL);
1840105059Scognet				}
1841105059Scognet			} else if (pDCB->SyncMode & SYNC_NEGO_ENABLE) {
1842105059Scognet			  /* do sync nego reject */
1843105059Scognet				trm_reg_write16(DO_CLRATN,TRMREG_SCSI_CONTROL);
1844105059Scognet				if (pSRB->SRBState & SRB_DO_SYNC_NEGO) {
1845105059Scognet					pDCB = pSRB->pSRBDCB;
1846105059Scognet					pDCB->SyncMode &=
1847105059Scognet					  ~(SYNC_NEGO_ENABLE+SYNC_NEGO_DONE);
1848105059Scognet					pDCB->SyncPeriod = 0;
1849105059Scognet					pDCB->SyncOffset = 0;
1850111158Scognet					/*
1851111158Scognet					 *
1852111158Scognet					 *   program SCSI control register
1853111158Scognet					 *
1854111158Scognet					 */
1855111158Scognet					trm_reg_write8(pDCB->SyncPeriod,
1856111158Scognet					    TRMREG_SCSI_SYNC);
1857111158Scognet					trm_reg_write8(pDCB->SyncOffset,
1858111158Scognet					    TRMREG_SCSI_OFFSET);
1859111158Scognet					trm_SetXferRate(pACB,pSRB,pDCB);
1860105059Scognet				}
1861105059Scognet			}
1862111158Scognet			*pscsi_status = PH_BUS_FREE; /* .. initial phase */
1863111158Scognet			/* it's important for atn stop */
1864111158Scognet			trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1865111158Scognet			/*
1866111158Scognet			 * SCSI command
1867111158Scognet			 */
1868111158Scognet			trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
1869111158Scognet			return;
1870105059Scognet		} else if (message_in_code == MSG_IGNOREWIDE) {
1871105059Scognet			trm_reg_write32(1, TRMREG_SCSI_COUNTER);
1872105059Scognet			trm_reg_read8(TRMREG_SCSI_FIFO);
1873111158Scognet			*pscsi_status = PH_BUS_FREE; /* .. initial phase */
1874111158Scognet			/* it's important for atn stop */
1875111158Scognet			trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1876111158Scognet			/*
1877111158Scognet			 * SCSI command
1878111158Scognet			 */
1879111158Scognet			trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
1880111158Scognet			return;
1881105059Scognet		} else {
1882105059Scognet	  	  /* Restore data pointer message */
1883105059Scognet  		  /* Save data pointer message	  */
1884105059Scognet		  /* Completion message		  */
1885105059Scognet		  /* NOP message       	          */
1886111158Scognet			*pscsi_status = PH_BUS_FREE; /* .. initial phase */
1887111158Scognet			/* it's important for atn stop */
1888111158Scognet			trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1889111158Scognet			/*
1890111158Scognet			 * SCSI command
1891111158Scognet			 */
1892111158Scognet			trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
1893111158Scognet			return;
1894105059Scognet		}
1895105059Scognet	} else {
1896105059Scognet	  /*
1897105059Scognet   	   * Parsing incomming extented messages
1898105059Scognet	   */
1899105059Scognet		*pSRB->pMsgPtr = message_in_code;
1900105059Scognet		pSRB->MsgCnt++;
1901105059Scognet		pSRB->pMsgPtr++;
1902105059Scognet		TRM_DPRINTF("pSRB->MsgInBuf[0]=%2x \n ",pSRB->MsgInBuf[0]);
1903105059Scognet		TRM_DPRINTF("pSRB->MsgInBuf[1]=%2x \n ",pSRB->MsgInBuf[1]);
1904105059Scognet		TRM_DPRINTF("pSRB->MsgInBuf[2]=%2x \n ",pSRB->MsgInBuf[2]);
1905105059Scognet		TRM_DPRINTF("pSRB->MsgInBuf[3]=%2x \n ",pSRB->MsgInBuf[3]);
1906105059Scognet		TRM_DPRINTF("pSRB->MsgInBuf[4]=%2x \n ",pSRB->MsgInBuf[4]);
1907105059Scognet	    	if ((pSRB->MsgInBuf[0] >= MSG_SIMPLE_QTAG)
1908105059Scognet		    && (pSRB->MsgInBuf[0] <= MSG_ORDER_QTAG)) {
1909105059Scognet		  /*
1910105059Scognet	   	   * is QUEUE tag message :
1911105059Scognet   		   *
1912105059Scognet	   	   * byte 0:
1913105059Scognet	   	   * HEAD    QUEUE TAG (20h)
1914105059Scognet	   	   * ORDERED QUEUE TAG (21h)
1915105059Scognet	   	   * SIMPLE  QUEUE TAG (22h)
1916105059Scognet	   	   * byte 1:
1917105059Scognet	   	   * Queue tag (00h - FFh)
1918105059Scognet	   	   */
1919105059Scognet			if (pSRB->MsgCnt == 2) {
1920105059Scognet				pSRB->SRBState = 0;
1921105059Scognet				message_in_tag_id = pSRB->MsgInBuf[1];
1922105059Scognet				pSRB = pDCB->pGoingSRB;
1923105059Scognet				pSRBTemp = pDCB->pGoingLastSRB;
1924105059Scognet				if (pSRB) {
1925105059Scognet					for (;;) {
1926105059Scognet						if (pSRB->TagNumber !=
1927105059Scognet						    message_in_tag_id) {
1928105059Scognet							if (pSRB == pSRBTemp) {
1929105059Scognet								goto  mingx0;
1930105059Scognet							}
1931105059Scognet							pSRB = pSRB->pNextSRB;
1932105059Scognet						} else
1933105059Scognet							break;
1934105059Scognet					}
1935105059Scognet					if (pDCB->DCBFlag & ABORT_DEV_) {
1936105059Scognet						pSRB->SRBState = SRB_ABORT_SENT;
1937105059Scognet						trm_EnableMsgOutAbort1(
1938105059Scognet						    pACB, pSRB);
1939105059Scognet					}
1940111158Scognet					if (!(pSRB->SRBState & SRB_DISCONNECT)) {
1941111158Scognet						TRM_DPRINTF("SRB not yet disconnect........ \n ");
1942105059Scognet						goto  mingx0;
1943111158Scognet					}
1944105059Scognet					pDCB->pActiveSRB = pSRB;
1945105059Scognet					pSRB->SRBState = SRB_DATA_XFER;
1946105059Scognet				} else {
1947105059Scognetmingx0:
1948111158Scognet	     				pSRB = &pACB->TmpSRB;
1949105059Scognet					pSRB->SRBState = SRB_UNEXPECT_RESEL;
1950105059Scognet					pDCB->pActiveSRB = pSRB;
1951105059Scognet					pSRB->MsgOutBuf[0] = MSG_ABORT_TAG;
1952105059Scognet					trm_EnableMsgOutAbort2(
1953105059Scognet					    pACB,
1954105059Scognet					    pSRB);
1955105059Scognet				}
1956105059Scognet			}
1957111158Scognet			*pscsi_status = PH_BUS_FREE;
1958111158Scognet			/* .. initial phase */
1959111158Scognet			trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1960111158Scognet			/* it's important for atn stop */
1961111158Scognet			/*
1962111158Scognet			 * SCSI command
1963111158Scognet			 */
1964111158Scognet			trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
1965111158Scognet			return;
1966105059Scognet		} else if ((pSRB->MsgInBuf[0] == MSG_EXTENDED) &&
1967105059Scognet		    (pSRB->MsgInBuf[2] == 3) && (pSRB->MsgCnt == 4)) {
1968105059Scognet		  /*
1969105059Scognet	   	   * is Wide data xfer Extended message :
1970105059Scognet	   	   * ======================================
1971105059Scognet	   	   * WIDE DATA TRANSFER REQUEST
1972105059Scognet   		   * ======================================
1973105059Scognet		   * byte 0 :  Extended message (01h)
1974105059Scognet		   * byte 1 :  Extended message length (02h)
1975105059Scognet		   * byte 2 :  WIDE DATA TRANSFER code (03h)
1976105059Scognet		   * byte 3 :  Transfer width exponent
1977105059Scognet		   */
1978105059Scognet			pDCB = pSRB->pSRBDCB;
1979105059Scognet			pSRB->SRBState &= ~(SRB_EXTEND_MSGIN+SRB_DO_WIDE_NEGO);
1980105059Scognet			if ((pSRB->MsgInBuf[1] != 2)) {
1981105059Scognet			  /* Length is wrong, reject it  */
1982105059Scognet				pDCB->SyncMode &=
1983105059Scognet				  ~(WIDE_NEGO_ENABLE+WIDE_NEGO_DONE);
1984105059Scognet				pSRB->MsgCnt = 1;
1985105059Scognet				pSRB->MsgInBuf[0] = MSG_REJECT_;
1986105059Scognet				trm_reg_write16(DO_SETATN, TRMREG_SCSI_CONTROL);
1987111158Scognet				*pscsi_status = PH_BUS_FREE; /* .. initial phase */
1988111158Scognet				/* it's important for atn stop */
1989111158Scognet				trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
1990111158Scognet				/*
1991111158Scognet				 * SCSI command
1992111158Scognet				 */
1993111158Scognet				trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
1994111158Scognet				return;
1995105059Scognet			}
1996105059Scognet			if (pDCB->SyncMode & WIDE_NEGO_ENABLE) {
1997105059Scognet			  /* Do wide negoniation */
1998105059Scognet				if (pSRB->MsgInBuf[3] > 2) {
1999105059Scognet				  /* > 32 bit	*/
2000105059Scognet				  /* reject_msg: */
2001105059Scognet					pDCB->SyncMode &=
2002105059Scognet					  ~(WIDE_NEGO_ENABLE+WIDE_NEGO_DONE);
2003105059Scognet					pSRB->MsgCnt = 1;
2004105059Scognet					pSRB->MsgInBuf[0] = MSG_REJECT_;
2005105059Scognet					trm_reg_write16(DO_SETATN,
2006105059Scognet					    TRMREG_SCSI_CONTROL);
2007111158Scognet					*pscsi_status = PH_BUS_FREE; /* .. initial phase */
2008111158Scognet					/* it's important for atn stop */
2009111158Scognet					trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
2010111158Scognet					/*
2011111158Scognet					 * SCSI command
2012111158Scognet					 */
2013111158Scognet					trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
2014111158Scognet					return;
2015105059Scognet				}
2016105059Scognet				if (pSRB->MsgInBuf[3] == 2) {
2017105059Scognet					pSRB->MsgInBuf[3] = 1;
2018105059Scognet					/* do 16 bits	*/
2019105059Scognet				} else {
2020105059Scognet					if (!(pDCB->SyncMode
2021105059Scognet					      & WIDE_NEGO_DONE)) {
2022105059Scognet						pSRB->SRBState &=
2023105059Scognet						  ~(SRB_DO_WIDE_NEGO+SRB_MSGIN);
2024105059Scognet						pDCB->SyncMode |=
2025105059Scognet						  WIDE_NEGO_DONE;
2026105059Scognet						pDCB->SyncMode &=
2027105059Scognet						  ~(SYNC_NEGO_DONE |
2028105059Scognet						      EN_ATN_STOP |
2029105059Scognet						      WIDE_NEGO_ENABLE);
2030105059Scognet						if (pSRB->MsgInBuf[3] != 0) {
2031105059Scognet						  /* is Wide data xfer */
2032105059Scognet							pDCB->SyncPeriod |=
2033105059Scognet							  WIDE_SYNC;
2034105059Scognet							pDCB->tinfo.current.width
2035105059Scognet							  = MSG_EXT_WDTR_BUS_16_BIT;
2036105059Scognet							pDCB->tinfo.goal.width
2037105059Scognet							  = MSG_EXT_WDTR_BUS_16_BIT;
2038105059Scognet						}
2039105059Scognet					}
2040105059Scognet				}
2041105059Scognet			} else
2042105059Scognet				pSRB->MsgInBuf[3] = 0;
2043105059Scognet			pSRB->SRBState |= SRB_MSGOUT;
2044105059Scognet			trm_reg_write16(DO_SETATN,TRMREG_SCSI_CONTROL);
2045111158Scognet			*pscsi_status = PH_BUS_FREE; /* .. initial phase */
2046111158Scognet			/* it's important for atn stop */
2047111158Scognet			trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
2048111158Scognet			/*
2049111158Scognet			 * SCSI command
2050111158Scognet			 */
2051111158Scognet			trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
2052111158Scognet			return;
2053105059Scognet		} else if ((pSRB->MsgInBuf[0] == MSG_EXTENDED) &&
2054105059Scognet		    (pSRB->MsgInBuf[2] == 1) && (pSRB->MsgCnt == 5)) {
2055105059Scognet			/*
2056105059Scognet			 * is 8bit transfer Extended message :
2057105059Scognet			 * =================================
2058105059Scognet			 * SYNCHRONOUS DATA TRANSFER REQUEST
2059105059Scognet			 * =================================
2060105059Scognet			 * byte 0 :  Extended message (01h)
2061105059Scognet			 * byte 1 :  Extended message length (03)
2062105059Scognet			 * byte 2 :  SYNCHRONOUS DATA TRANSFER code (01h)
2063105059Scognet			 * byte 3 :  Transfer period factor
2064105059Scognet			 * byte 4 :  REQ/ACK offset
2065105059Scognet			 */
2066105059Scognet			pSRB->SRBState &= ~(SRB_EXTEND_MSGIN+SRB_DO_SYNC_NEGO);
2067105059Scognet			if ((pSRB->MsgInBuf[1] != 3) ||
2068105059Scognet			    (pSRB->MsgInBuf[2] != 1)) {
2069105059Scognet			  /* reject_msg: */
2070105059Scognet				pSRB->MsgCnt = 1;
2071105059Scognet				pSRB->MsgInBuf[0] = MSG_REJECT_;
2072105059Scognet				trm_reg_write16(DO_SETATN, TRMREG_SCSI_CONTROL);
2073111158Scognet				*pscsi_status = PH_BUS_FREE;
2074111158Scognet				/* .. initial phase */
2075111158Scognet				trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
2076111158Scognet				/* it's important for atn stop */
2077111158Scognet				/*
2078111158Scognet				 * SCSI cammand
2079111158Scognet				 */
2080111158Scognet				trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
2081111158Scognet				return;
2082105059Scognet			} else if (!(pSRB->MsgInBuf[3]) || !(pSRB->MsgInBuf[4])) {
2083105059Scognet				/* set async */
2084105059Scognet				pDCB = pSRB->pSRBDCB;
2085105059Scognet				/* disable sync & sync nego */
2086105059Scognet				pDCB->SyncMode &=
2087105059Scognet				  ~(SYNC_NEGO_ENABLE+SYNC_NEGO_DONE);
2088105059Scognet				pDCB->SyncPeriod = 0;
2089105059Scognet				pDCB->SyncOffset = 0;
2090105059Scognet				pDCB->tinfo.goal.period = 0;
2091105059Scognet				pDCB->tinfo.goal.offset = 0;
2092105059Scognet				pDCB->tinfo.current.period = 0;
2093105059Scognet				pDCB->tinfo.current.offset = 0;
2094105059Scognet				pDCB->tinfo.current.width =
2095105059Scognet				  MSG_EXT_WDTR_BUS_8_BIT;
2096111158Scognet				/*
2097111158Scognet				 *
2098111158Scognet				 *   program SCSI control register
2099111158Scognet				 *
2100111158Scognet				 */
2101111158Scognet				trm_reg_write8(pDCB->SyncPeriod,TRMREG_SCSI_SYNC);
2102111158Scognet				trm_reg_write8(pDCB->SyncOffset,TRMREG_SCSI_OFFSET);
2103111158Scognet				trm_SetXferRate(pACB,pSRB,pDCB);
2104111158Scognet				*pscsi_status = PH_BUS_FREE;
2105111158Scognet				/* .. initial phase */
2106111158Scognet				trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
2107111158Scognet				/* it's important for atn stop */
2108111158Scognet				/*
2109111158Scognet				 * SCSI cammand
2110111158Scognet				 */
2111111158Scognet				trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
2112111158Scognet				return;
2113105059Scognet			} else {
2114105059Scognet				/* set sync */
2115105059Scognet				pDCB = pSRB->pSRBDCB;
2116105059Scognet				pDCB->SyncMode |=
2117105059Scognet				  SYNC_NEGO_ENABLE+SYNC_NEGO_DONE;
2118105059Scognet				pDCB->MaxNegoPeriod = pSRB->MsgInBuf[3];
2119105059Scognet				/* Transfer period factor */
2120105059Scognet				pDCB->SyncOffset = pSRB->MsgInBuf[4];
2121105059Scognet				/* REQ/ACK offset */
2122116813Scognet				if (pACB->AdaptType == 1) {
2123111158Scognet					for(bIndex = 0; bIndex < 7; bIndex++) {
2124116813Scognet						if (pSRB->MsgInBuf[3] <=
2125111158Scognet					   dc395u2x_clock_period[bIndex]) {
2126111158Scognet				            pDCB->tinfo.goal.period =
2127111158Scognet						dc395u2x_tinfo_period[bIndex];
2128111158Scognet				            pDCB->tinfo.current.period =
2129111158Scognet						dc395u2x_tinfo_period[bIndex];
2130111158Scognet			                pDCB->tinfo.goal.offset =
2131111158Scognet					    pDCB->SyncOffset;
2132111158Scognet					pDCB->tinfo.current.offset =
2133111158Scognet					    pDCB->SyncOffset;
2134111158Scognet					pDCB->SyncPeriod |= (bIndex|LVDS_SYNC);
2135111158Scognet					break;
2136111158Scognet						}
2137111158Scognet					}
2138111158Scognet				} else {
2139111158Scognet					for(bIndex = 0; bIndex < 7; bIndex++) {
2140116813Scognet						if (pSRB->MsgInBuf[3] <=
2141111158Scognet						 dc395x_clock_period[bIndex]) {
2142111158Scognet						   pDCB->tinfo.goal.period =
2143111158Scognet						dc395x_tinfo_period[bIndex];
2144111158Scognet						   pDCB->tinfo.current.period =
2145111158Scognet						dc395x_tinfo_period[bIndex];
2146111158Scognet						   pDCB->tinfo.goal.offset =
2147111158Scognet						pDCB->SyncOffset;
2148111158Scognet						   pDCB->tinfo.current.offset =
2149111158Scognet					     	       pDCB->SyncOffset;
2150111158Scognet					     	   pDCB->SyncPeriod |=
2151111158Scognet				     		       (bIndex|ALT_SYNC);
2152111158Scognet			     			   break;
2153111158Scognet						}
2154111158Scognet					}
2155105059Scognet				}
2156105059Scognet				/*
2157105059Scognet				 *
2158105059Scognet	 			 *   program SCSI control register
2159105059Scognet	 			 *
2160105059Scognet	 			 */
2161105059Scognet				trm_reg_write8(pDCB->SyncPeriod,
2162105059Scognet				    TRMREG_SCSI_SYNC);
2163105059Scognet				trm_reg_write8(pDCB->SyncOffset,
2164105059Scognet				    TRMREG_SCSI_OFFSET);
2165105059Scognet				trm_SetXferRate(pACB,pSRB,pDCB);
2166111158Scognet				*pscsi_status=PH_BUS_FREE;/*.. initial phase*/
2167111158Scognet				trm_reg_write16(DO_DATALATCH,TRMREG_SCSI_CONTROL);/* it's important for atn stop*/
2168111158Scognet	            /*
2169111158Scognet	            ** SCSI command
2170111158Scognet	            */
2171111158Scognet				trm_reg_write8(SCMD_MSGACCEPT,TRMREG_SCSI_COMMAND);
2172111158Scognet				return;
2173105059Scognet			}
2174105059Scognet		}
2175105059Scognet	*pscsi_status = PH_BUS_FREE;
2176105059Scognet	/* .. initial phase */
2177105059Scognet	trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
2178105059Scognet	/* it's important for atn stop */
2179105059Scognet	/*
2180105059Scognet	 * SCSI cammand
2181105059Scognet	 */
2182105059Scognet	trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
2183111158Scognet	}
2184105059Scognet}
2185105059Scognet
2186105059Scognetstatic void
2187111158Scognettrm_MsgInPhase1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
2188105059Scognet{
2189105059Scognet
2190105059Scognet	trm_reg_write16(DO_CLRFIFO, TRMREG_SCSI_CONTROL);
2191105059Scognet	trm_reg_write32(1,TRMREG_SCSI_COUNTER);
2192105059Scognet	if (!(pSRB->SRBState & SRB_MSGIN)) {
2193105059Scognet		pSRB->SRBState &= SRB_DISCONNECT;
2194105059Scognet		pSRB->SRBState |= SRB_MSGIN;
2195105059Scognet	}
2196105059Scognet	trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
2197105059Scognet	/* it's important for atn stop*/
2198105059Scognet	/*
2199105059Scognet	 * SCSI cammand
2200105059Scognet	 */
2201105059Scognet	trm_reg_write8(SCMD_FIFO_IN, TRMREG_SCSI_COMMAND);
2202105059Scognet}
2203105059Scognet
2204105059Scognetstatic void
2205111158Scognettrm_Nop0(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
2206105059Scognet{
2207105059Scognet
2208105059Scognet}
2209105059Scognet
2210105059Scognetstatic void
2211111158Scognettrm_Nop1(PACB pACB, PSRB pSRB, u_int16_t *pscsi_status)
2212105059Scognet{
2213105059Scognet
2214105059Scognet}
2215105059Scognet
2216105059Scognetstatic void
2217105059Scognettrm_SetXferRate(PACB pACB,PSRB pSRB, PDCB pDCB)
2218105059Scognet{
2219111158Scognet	union ccb	*pccb;
2220111158Scognet	struct ccb_trans_settings neg;
2221105059Scognet	u_int16_t	cnt, i;
2222105059Scognet	u_int8_t	bval;
2223105059Scognet	PDCB		pDCBTemp;
2224105059Scognet
2225105059Scognet	/*
2226105059Scognet	 * set all lun device's  period , offset
2227105059Scognet	 */
2228111158Scognet	TRM_DPRINTF("trm_SetXferRate\n");
2229111158Scognet	pccb = pSRB->pccb;
2230163816Smjacob	memset(&neg, 0, sizeof (neg));
2231163816Smjacob	neg.xport_specific.spi.sync_period = pDCB->tinfo.goal.period;
2232163816Smjacob	neg.xport_specific.spi.sync_offset = pDCB->tinfo.goal.offset;
2233163816Smjacob	neg.xport_specific.spi.valid =
2234163816Smjacob	    CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET;
2235111158Scognet	xpt_setup_ccb(&neg.ccb_h, pccb->ccb_h.path, /* priority */1);
2236111158Scognet	xpt_async(AC_TRANSFER_NEG, pccb->ccb_h.path, &neg);
2237105059Scognet	if (!(pDCB->IdentifyMsg & 0x07)) {
2238111158Scognet		pDCBTemp = pACB->pLinkDCB;
2239111158Scognet		cnt = pACB->DeviceCnt;
2240111158Scognet		bval = pDCB->TargetID;
2241111158Scognet		for (i = 0; i < cnt; i++) {
2242111158Scognet			if (pDCBTemp->TargetID == bval) {
2243111158Scognet				pDCBTemp->SyncPeriod = pDCB->SyncPeriod;
2244111158Scognet				pDCBTemp->SyncOffset = pDCB->SyncOffset;
2245111158Scognet				pDCBTemp->SyncMode = pDCB->SyncMode;
2246105059Scognet			}
2247111158Scognet			pDCBTemp = pDCBTemp->pNextDCB;
2248105059Scognet		}
2249105059Scognet	}
2250105059Scognet	return;
2251105059Scognet}
2252105059Scognet
2253105059Scognet/*
2254105059Scognet * scsiiom
2255105059Scognet *            trm_Interrupt
2256105059Scognet *
2257105059Scognet *
2258105059Scognet *    ---SCSI bus phase
2259105059Scognet *
2260105059Scognet * 	PH_DATA_OUT	        0x00	 Data out phase
2261105059Scognet * 	PH_DATA_IN	        0x01	 Data in phase
2262105059Scognet * 	PH_COMMAND	        0x02	 Command phase
2263105059Scognet * 	PH_STATUS	        0x03	 Status phase
2264105059Scognet *	PH_BUS_FREE	        0x04	 Invalid phase used as bus free
2265105059Scognet * 	PH_BUS_FREE	        0x05	 Invalid phase used as bus free
2266105059Scognet * 	PH_MSG_OUT	        0x06	 Message out phase
2267105059Scognet * 	PH_MSG_IN	        0x07	 Message in phase
2268105059Scognet *
2269105059Scognet */
2270105059Scognetstatic void
2271105059Scognettrm_Disconnect(PACB pACB)
2272105059Scognet{
2273105059Scognet	PDCB		pDCB;
2274105059Scognet	PSRB		pSRB, psrb;
2275105059Scognet	u_int16_t	i,j, cnt;
2276105059Scognet	u_int		target_id,target_lun;
2277105059Scognet
2278105059Scognet	TRM_DPRINTF("trm_Disconnect...............\n ");
2279105059Scognet
2280105059Scognet       	pDCB = pACB->pActiveDCB;
2281105059Scognet	if (!pDCB) {
2282105059Scognet		TRM_DPRINTF(" Exception Disconnect DCB=NULL..............\n ");
2283105059Scognet		j = 400;
2284105059Scognet    		while (--j)
2285105059Scognet			DELAY(1);
2286105059Scognet		/* 1 msec */
2287105059Scognet		trm_reg_write16((DO_CLRFIFO | DO_HWRESELECT),
2288105059Scognet		    TRMREG_SCSI_CONTROL);
2289105059Scognet		return;
2290105059Scognet	}
2291105059Scognet	pSRB = pDCB->pActiveSRB;
2292105059Scognet	/* bug pSRB=0 */
2293105059Scognet	target_id  = pSRB->pccb->ccb_h.target_id;
2294105059Scognet	target_lun = pSRB->pccb->ccb_h.target_lun;
2295105059Scognet	TRM_DPRINTF(":pDCB->pActiveSRB= %8x \n ",(u_int) pDCB->pActiveSRB);
2296105059Scognet	pACB->pActiveDCB = 0;
2297105059Scognet	pSRB->ScsiPhase = PH_BUS_FREE;
2298105059Scognet	/* SCSI bus free Phase */
2299105059Scognet	trm_reg_write16((DO_CLRFIFO | DO_HWRESELECT), TRMREG_SCSI_CONTROL);
2300105059Scognet	if (pSRB->SRBState & SRB_UNEXPECT_RESEL) {
2301105059Scognet		pSRB->SRBState = 0;
2302105059Scognet		trm_DoWaitingSRB(pACB);
2303105059Scognet	} else if (pSRB->SRBState & SRB_ABORT_SENT) {
2304105059Scognet		pDCB->DCBFlag = 0;
2305105059Scognet		cnt = pDCB->GoingSRBCnt;
2306105059Scognet		pDCB->GoingSRBCnt = 0;
2307105059Scognet		pSRB = pDCB->pGoingSRB;
2308105059Scognet		for (i = 0; i < cnt; i++) {
2309105059Scognet			psrb = pSRB->pNextSRB;
2310105059Scognet			pSRB->pNextSRB = pACB->pFreeSRB;
2311105059Scognet			pACB->pFreeSRB = pSRB;
2312105059Scognet			pSRB = psrb;
2313105059Scognet		}
2314105059Scognet		pDCB->pGoingSRB = 0;
2315105059Scognet		trm_DoWaitingSRB(pACB);
2316105059Scognet	} else {
2317105059Scognet		if ((pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
2318105059Scognet		    !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED))) {
2319105059Scognet		  /* Selection time out */
2320111158Scognet			if (!(pACB->scan_devices[target_id][target_lun]) &&
2321111158Scognet			    pSRB->CmdBlock[0] != 0x00 && /* TEST UNIT READY */
2322111158Scognet			    pSRB->CmdBlock[0] != INQUIRY) {
2323105059Scognet				pSRB->SRBState = SRB_READY;
2324105059Scognet				trm_RewaitSRB(pDCB, pSRB);
2325105059Scognet			} else {
2326105059Scognet				pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
2327105059Scognet				goto  disc1;
2328105059Scognet			}
2329105059Scognet		} else if (pSRB->SRBState & SRB_DISCONNECT) {
2330105059Scognet			/*
2331105059Scognet			 * SRB_DISCONNECT
2332105059Scognet			 */
2333105059Scognet			trm_DoWaitingSRB(pACB);
2334105059Scognet		} else if (pSRB->SRBState & SRB_COMPLETED) {
2335105059Scognetdisc1:
2336105059Scognet		  /*
2337105059Scognet		   * SRB_COMPLETED
2338105059Scognet		   */
2339105059Scognet			pDCB->pActiveSRB = 0;
2340105059Scognet			pSRB->SRBState = SRB_FREE;
2341105059Scognet			trm_SRBdone(pACB, pDCB, pSRB);
2342105059Scognet		}
2343105059Scognet	}
2344105059Scognet	return;
2345105059Scognet}
2346105059Scognet
2347105059Scognetstatic void
2348105059Scognettrm_Reselect(PACB pACB)
2349105059Scognet{
2350105059Scognet	PDCB		pDCB;
2351105059Scognet	PSRB		pSRB;
2352105059Scognet	u_int16_t	RselTarLunId;
2353105059Scognet
2354105059Scognet	TRM_DPRINTF("trm_Reselect................. \n");
2355105059Scognet	pDCB = pACB->pActiveDCB;
2356105059Scognet	if (pDCB) {
2357105059Scognet	  /* Arbitration lost but Reselection win */
2358105059Scognet		pSRB = pDCB->pActiveSRB;
2359105059Scognet		pSRB->SRBState = SRB_READY;
2360105059Scognet		trm_RewaitSRB(pDCB, pSRB);
2361105059Scognet	}
2362105059Scognet	/* Read Reselected Target Id and LUN */
2363105059Scognet	RselTarLunId = trm_reg_read16(TRMREG_SCSI_TARGETID) & 0x1FFF;
2364105059Scognet	pDCB = pACB->pLinkDCB;
2365105059Scognet	while (RselTarLunId != *((u_int16_t *) &pDCB->TargetID)) {
2366105059Scognet	  /* get pDCB of the reselect id */
2367105059Scognet		pDCB = pDCB->pNextDCB;
2368105059Scognet	}
2369105059Scognet
2370105059Scognet	pACB->pActiveDCB = pDCB;
2371105059Scognet	if (pDCB->SyncMode & EN_TAG_QUEUING) {
2372111158Scognet		pSRB = &pACB->TmpSRB;
2373105059Scognet		pDCB->pActiveSRB = pSRB;
2374105059Scognet	} else {
2375105059Scognet		pSRB = pDCB->pActiveSRB;
2376105059Scognet		if (!pSRB || !(pSRB->SRBState & SRB_DISCONNECT)) {
2377105059Scognet		  /*
2378105059Scognet	   	   * abort command
2379105059Scognet   		   */
2380111158Scognet			pSRB = &pACB->TmpSRB;
2381105059Scognet			pSRB->SRBState = SRB_UNEXPECT_RESEL;
2382105059Scognet			pDCB->pActiveSRB = pSRB;
2383105059Scognet			trm_EnableMsgOutAbort1(pACB, pSRB);
2384105059Scognet		} else {
2385105059Scognet			if (pDCB->DCBFlag & ABORT_DEV_) {
2386105059Scognet				pSRB->SRBState = SRB_ABORT_SENT;
2387105059Scognet				trm_EnableMsgOutAbort1(pACB, pSRB);
2388105059Scognet			} else
2389105059Scognet				pSRB->SRBState = SRB_DATA_XFER;
2390105059Scognet		}
2391105059Scognet	}
2392105059Scognet	pSRB->ScsiPhase = PH_BUS_FREE;
2393105059Scognet	/* SCSI bus free Phase */
2394105059Scognet	/*
2395105059Scognet	 * Program HA ID, target ID, period and offset
2396105059Scognet	 */
2397105059Scognet	trm_reg_write8((u_int8_t) RselTarLunId,TRMREG_SCSI_TARGETID);
2398105059Scognet	/* target ID */
2399105059Scognet	trm_reg_write8(pACB->AdaptSCSIID,TRMREG_SCSI_HOSTID);
2400105059Scognet	/* host   ID */
2401105059Scognet	trm_reg_write8(pDCB->SyncPeriod,TRMREG_SCSI_SYNC);
2402105059Scognet	/* period    */
2403105059Scognet	trm_reg_write8(pDCB->SyncOffset,TRMREG_SCSI_OFFSET);
2404105059Scognet	/* offset    */
2405105059Scognet	trm_reg_write16(DO_DATALATCH, TRMREG_SCSI_CONTROL);
2406105059Scognet	/* it's important for atn stop*/
2407105059Scognet	/*
2408105059Scognet	 * SCSI cammand
2409105059Scognet	 */
2410105059Scognet	trm_reg_write8(SCMD_MSGACCEPT, TRMREG_SCSI_COMMAND);
2411105059Scognet	/* to rls the /ACK signal */
2412105059Scognet}
2413105059Scognet
2414105059Scognetstatic void
2415105059Scognettrm_SRBdone(PACB pACB, PDCB pDCB, PSRB pSRB)
2416105059Scognet{
2417105059Scognet	PSRB			psrb;
2418105059Scognet	u_int8_t		bval, bval1,status;
2419105059Scognet	union ccb		*pccb;
2420105059Scognet	struct ccb_scsiio	*pcsio;
2421105059Scognet	PSCSI_INQDATA		ptr;
2422105059Scognet	int			intflag;
2423105059Scognet	u_int			target_id,target_lun;
2424105059Scognet	PDCB			pTempDCB;
2425105059Scognet
2426105059Scognet	pccb  = pSRB->pccb;
2427105059Scognet	if (pccb == NULL)
2428105059Scognet		return;
2429105059Scognet	pcsio = &pccb->csio;
2430105059Scognet	target_id  = pSRB->pccb->ccb_h.target_id;
2431105059Scognet	target_lun = pSRB->pccb->ccb_h.target_lun;
2432105059Scognet	if ((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
2433115343Sscottl		bus_dmasync_op_t op;
2434105059Scognet		if ((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
2435105059Scognet			op = BUS_DMASYNC_POSTREAD;
2436105059Scognet		else
2437105059Scognet			op = BUS_DMASYNC_POSTWRITE;
2438105059Scognet		bus_dmamap_sync(pACB->buffer_dmat, pSRB->dmamap, op);
2439105059Scognet		bus_dmamap_unload(pACB->buffer_dmat, pSRB->dmamap);
2440105059Scognet	}
2441105059Scognet    	/*
2442105059Scognet	 *
2443105059Scognet	 * target status
2444105059Scognet	 *
2445105059Scognet	 */
2446105059Scognet	status = pSRB->TargetStatus;
2447105059Scognet	pcsio->scsi_status=SCSI_STAT_GOOD;
2448105059Scognet	pccb->ccb_h.status = CAM_REQ_CMP;
2449105059Scognet	if (pSRB->SRBFlag & AUTO_REQSENSE) {
2450105059Scognet	  /*
2451105059Scognet   	   * status of auto request sense
2452105059Scognet	   */
2453105059Scognet		pSRB->SRBFlag &= ~AUTO_REQSENSE;
2454105059Scognet		pSRB->AdaptStatus = 0;
2455105059Scognet		pSRB->TargetStatus = SCSI_STATUS_CHECK_COND;
2456105059Scognet
2457105059Scognet		if (status == SCSI_STATUS_CHECK_COND) {
2458105059Scognet			pccb->ccb_h.status = CAM_SEL_TIMEOUT;
2459105059Scognet			goto ckc_e;
2460105059Scognet		}
2461105059Scognet		*((u_long *) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
2462105059Scognet		*((u_long *) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1];
2463105059Scognet		pSRB->SRBTotalXferLength = pSRB->Segment1[1];
2464111158Scognet		pSRB->pSRBSGL->address = pSRB->SgSenseTemp.address;
2465111158Scognet		pSRB->pSRBSGL->length = pSRB->SgSenseTemp.length;
2466105059Scognet		pcsio->scsi_status = SCSI_STATUS_CHECK_COND;
2467111158Scognet		bcopy(trm_get_sense_buf(pACB, pSRB), &pcsio->sense_data,
2468111158Scognet		    pcsio->sense_len);
2469111158Scognet		pcsio->ccb_h.status = CAM_SCSI_STATUS_ERROR
2470111158Scognet		    | CAM_AUTOSNS_VALID;
2471105059Scognet		goto ckc_e;
2472105059Scognet	}
2473105059Scognet	/*
2474105059Scognet	 * target status
2475105059Scognet	 */
2476105059Scognet	if (status) {
2477105059Scognet		if (status == SCSI_STATUS_CHECK_COND) {
2478105059Scognet			if ((pcsio->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) {
2479105059Scognet			  TRM_DPRINTF("trm_RequestSense..................\n");
2480105059Scognet			  trm_RequestSense(pACB, pDCB, pSRB);
2481105059Scognet			  return;
2482105059Scognet			}
2483105059Scognet			pcsio->scsi_status = SCSI_STATUS_CHECK_COND;
2484111158Scognet			pccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
2485105059Scognet			goto ckc_e;
2486105059Scognet		} else if (status == SCSI_STAT_QUEUEFULL) {
2487105059Scognet			bval = (u_int8_t) pDCB->GoingSRBCnt;
2488105059Scognet			bval--;
2489111158Scognet			pDCB->MaxActiveCommandCnt = bval;
2490105059Scognet			trm_RewaitSRB(pDCB, pSRB);
2491105059Scognet			pSRB->AdaptStatus = 0;
2492105059Scognet			pSRB->TargetStatus = 0;
2493111158Scognet			return;
2494105059Scognet		} else if (status == SCSI_STAT_SEL_TIMEOUT) {
2495105059Scognet			pSRB->AdaptStatus  = H_SEL_TIMEOUT;
2496105059Scognet			pSRB->TargetStatus = 0;
2497105059Scognet			pcsio->scsi_status = SCSI_STAT_SEL_TIMEOUT;
2498105059Scognet			pccb->ccb_h.status = CAM_SEL_TIMEOUT;
2499105059Scognet		} else if (status == SCSI_STAT_BUSY) {
2500105059Scognet			TRM_DPRINTF("trm: target busy at %s %d\n",
2501105059Scognet				__FILE__, __LINE__);
2502105059Scognet			pcsio->scsi_status = SCSI_STAT_BUSY;
2503105059Scognet			pccb->ccb_h.status = CAM_SCSI_BUSY;
2504111158Scognet			return;
2505105059Scognet		  /* The device busy, try again later?	  */
2506105059Scognet		} else if (status == SCSI_STAT_RESCONFLICT) {
2507105059Scognet			TRM_DPRINTF("trm: target reserved at %s %d\n",
2508105059Scognet				__FILE__, __LINE__);
2509105059Scognet			pcsio->scsi_status = SCSI_STAT_RESCONFLICT;
2510105059Scognet			pccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;	/*XXX*/
2511111158Scognet			return;
2512105059Scognet		} else {
2513105059Scognet			pSRB->AdaptStatus = 0;
2514105059Scognet			if (pSRB->RetryCnt) {
2515105059Scognet				pSRB->RetryCnt--;
2516105059Scognet				pSRB->TargetStatus = 0;
2517105059Scognet				pSRB->SRBSGIndex = 0;
2518105059Scognet				if (trm_StartSCSI(pACB, pDCB, pSRB)) {
2519105059Scognet				  /*
2520105059Scognet				   * If trm_StartSCSI return 1 :
2521105059Scognet				   * current interrupt status is interrupt
2522105059Scognet				   * disreenable
2523105059Scognet				   * It's said that SCSI processor has more
2524105059Scognet				   * one SRB need to do
2525105059Scognet				   */
2526105059Scognet					trm_RewaitSRB(pDCB, pSRB);
2527105059Scognet				}
2528105059Scognet				return;
2529105059Scognet			} else {
2530105059Scognet        			TRM_DPRINTF("trm: driver stuffup at %s %d\n",
2531105059Scognet					__FILE__, __LINE__);
2532105059Scognet		      		pccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
2533105059Scognet			}
2534105059Scognet		}
2535105059Scognet	} else {
2536105059Scognet        /*
2537105059Scognet 	 * process initiator status..........................
2538105059Scognet	 * Adapter (initiator) status
2539105059Scognet	 */
2540105059Scognet		status = pSRB->AdaptStatus;
2541105059Scognet		if (status & H_OVER_UNDER_RUN) {
2542105059Scognet			pSRB->TargetStatus = 0;
2543105059Scognet			pccb->ccb_h.status = CAM_DATA_RUN_ERR;
2544105059Scognet			/* Illegal length (over/under run) */
2545105059Scognet		} else if (pSRB->SRBStatus & PARITY_ERROR) {
2546105059Scognet			TRM_DPRINTF("trm: driver stuffup %s %d\n",
2547105059Scognet				__FILE__, __LINE__);
2548105059Scognet			pDCB->tinfo.goal.period = 0;
2549105059Scognet			pDCB->tinfo.goal.offset = 0;
2550105059Scognet			/* Driver failed to perform operation */
2551105059Scognet			pccb->ccb_h.status = CAM_UNCOR_PARITY;
2552105059Scognet		} else {
2553105059Scognet		  /* no error */
2554105059Scognet			pSRB->AdaptStatus = 0;
2555105059Scognet			pSRB->TargetStatus = 0;
2556105059Scognet			pccb->ccb_h.status = CAM_REQ_CMP;
2557105059Scognet			/* there is no error, (sense is invalid) */
2558105059Scognet		}
2559105059Scognet	}
2560105059Scognetckc_e:
2561105059Scognet	if (pACB->scan_devices[target_id][target_lun]) {
2562105059Scognet	  /*
2563105059Scognet	   *   if SCSI command in "scan devices" duty
2564105059Scognet	   */
2565105059Scognet		if (pSRB->CmdBlock[0] == TEST_UNIT_READY)
2566105059Scognet			pACB->scan_devices[target_id][target_lun] = 0;
2567105059Scognet		/* SCSI command phase :test unit ready */
2568105059Scognet		else if (pSRB->CmdBlock[0] == INQUIRY) {
2569105059Scognet		  /*
2570105059Scognet		   * SCSI command phase :inquiry scsi device data
2571105059Scognet		   * (type,capacity,manufacture....
2572105059Scognet		   */
2573105059Scognet			if (pccb->ccb_h.status == CAM_SEL_TIMEOUT)
2574105059Scognet				goto NO_DEV;
2575105059Scognet			ptr = (PSCSI_INQDATA) pcsio->data_ptr;
2576105059Scognet			/* page fault */
2577105059Scognet			TRM_DPRINTF("trm_SRBdone..PSCSI_INQDATA:%2x \n",
2578105059Scognet			    ptr->DevType);
2579105059Scognet		  	bval1 = ptr->DevType & SCSI_DEVTYPE;
2580105059Scognet			if (bval1 == SCSI_NODEV) {
2581105059ScognetNO_DEV:
2582105059Scognet	  			TRM_DPRINTF("trm_SRBdone NO Device:target_id= %d ,target_lun= %d \n",
2583105059Scognet				    target_id,
2584105059Scognet				    target_lun);
2585105059Scognet		      		intflag = splcam();
2586105059Scognet				pACB->scan_devices[target_id][target_lun] = 0;
2587105059Scognet				/* no device set scan device flag =0*/
2588105059Scognet				/* pDCB Q link */
2589105059Scognet				/* move the head of DCB to tempDCB*/
2590105059Scognet				pTempDCB=pACB->pLinkDCB;
2591105059Scognet				/* search current DCB for pass link */
2592105059Scognet				while (pTempDCB->pNextDCB != pDCB) {
2593105059Scognet					pTempDCB = pTempDCB->pNextDCB;
2594105059Scognet				}
2595105059Scognet				/*
2596105059Scognet				 * when the current DCB found than connect
2597105059Scognet				 * current DCB tail
2598105059Scognet				 */
2599105059Scognet				/* to the DCB tail that before current DCB */
2600105059Scognet				pTempDCB->pNextDCB = pDCB->pNextDCB;
2601105059Scognet				/*
2602105059Scognet				 * if there was only one DCB ,connect his tail
2603105059Scognet				 * to his head
2604105059Scognet				 */
2605105059Scognet				if (pACB->pLinkDCB == pDCB)
2606105059Scognet					pACB->pLinkDCB = pTempDCB->pNextDCB;
2607105059Scognet				if (pACB->pDCBRunRobin == pDCB)
2608105059Scognet					pACB->pDCBRunRobin = pTempDCB->pNextDCB;
2609111158Scognet				pDCB->DCBstatus &= ~DS_IN_QUEUE;
2610105059Scognet				pACB->DeviceCnt--;
2611105059Scognet				if (pACB->DeviceCnt == 0) {
2612105059Scognet					pACB->pLinkDCB = NULL;
2613105059Scognet					pACB->pDCBRunRobin = NULL;
2614105059Scognet				}
2615105059Scognet				splx(intflag);
2616105059Scognet			} else {
2617105059Scognet#ifdef trm_DEBUG1
2618105059Scognet				int j;
2619105059Scognet				for (j = 0; j < 28; j++) {
2620105059Scognet					TRM_DPRINTF("ptr=%2x ",
2621105059Scognet						((u_int8_t *)ptr)[j]);
2622105059Scognet				}
2623105059Scognet#endif
2624105059Scognet	      			pDCB->DevType = bval1;
2625105059Scognet				if (bval1 == SCSI_DASD ||
2626105059Scognet				    bval1 == SCSI_OPTICAL) {
2627105059Scognet					if ((((ptr->Vers & 0x07) >= 2) ||
2628105059Scognet					      ((ptr->RDF & 0x0F) == 2)) &&
2629105059Scognet					    (ptr->Flags & SCSI_INQ_CMDQUEUE) &&
2630105059Scognet					    (pDCB->DevMode & TAG_QUEUING_) &&
2631105059Scognet					    (pDCB->DevMode & EN_DISCONNECT_)) {
2632105059Scognet						if (pDCB->DevMode &
2633105059Scognet						    TAG_QUEUING_) {
2634111158Scognet							pDCB->
2635111158Scognet							    MaxActiveCommandCnt =
2636105059Scognet							  pACB->TagMaxNum;
2637105059Scognet							pDCB->SyncMode |=
2638105059Scognet							  EN_TAG_QUEUING;
2639105059Scognet							pDCB->tinfo.disc_tag |=
2640105059Scognet							  TRM_CUR_TAGENB;
2641105059Scognet						} else {
2642105059Scognet							pDCB->SyncMode |=
2643105059Scognet							  EN_ATN_STOP;
2644105059Scognet							pDCB->tinfo.disc_tag &=
2645105059Scognet							  ~TRM_CUR_TAGENB;
2646105059Scognet						}
2647105059Scognet					}
2648105059Scognet				}
2649105059Scognet			}
2650105059Scognet			/* pSRB->CmdBlock[0] == INQUIRY */
2651105059Scognet		}
2652105059Scognet		/* pACB->scan_devices[target_id][target_lun] */
2653105059Scognet	}
2654105059Scognet    	intflag = splcam();
2655105059Scognet	/*  ReleaseSRB(pDCB, pSRB); */
2656105059Scognet	if (pSRB == pDCB->pGoingSRB)
2657105059Scognet		pDCB->pGoingSRB = pSRB->pNextSRB;
2658105059Scognet	else {
2659105059Scognet		psrb = pDCB->pGoingSRB;
2660105059Scognet		while (psrb->pNextSRB != pSRB) {
2661105059Scognet			psrb = psrb->pNextSRB;
2662105059Scognet		}
2663105059Scognet		psrb->pNextSRB = pSRB->pNextSRB;
2664105059Scognet		if (pSRB == pDCB->pGoingLastSRB) {
2665105059Scognet			pDCB->pGoingLastSRB = psrb;
2666105059Scognet		}
2667105059Scognet	}
2668105059Scognet	pSRB->pNextSRB = pACB->pFreeSRB;
2669105059Scognet	pACB->pFreeSRB = pSRB;
2670105059Scognet	pDCB->GoingSRBCnt--;
2671105059Scognet	trm_DoWaitingSRB(pACB);
2672105059Scognet
2673105059Scognet	splx(intflag);
2674105059Scognet	/*  Notify cmd done */
2675105059Scognet	xpt_done (pccb);
2676105059Scognet}
2677105059Scognet
2678105059Scognetstatic void
2679105059Scognettrm_DoingSRB_Done(PACB pACB)
2680105059Scognet{
2681105059Scognet	PDCB		pDCB, pdcb;
2682105059Scognet	PSRB		psrb, psrb2;
2683105059Scognet	u_int16_t	cnt, i;
2684105059Scognet	union ccb 	*pccb;
2685105059Scognet
2686105059Scognet	pDCB = pACB->pLinkDCB;
2687105059Scognet	if (pDCB == NULL)
2688105059Scognet  		return;
2689105059Scognet	pdcb = pDCB;
2690105059Scognet    	do {
2691105059Scognet		cnt = pdcb->GoingSRBCnt;
2692105059Scognet		psrb = pdcb->pGoingSRB;
2693105059Scognet		for (i = 0; i < cnt; i++) {
2694105059Scognet			psrb2 = psrb->pNextSRB;
2695105059Scognet		    	pccb = psrb->pccb;
2696105059Scognet			pccb->ccb_h.status = CAM_SEL_TIMEOUT;
2697105059Scognet			/*  ReleaseSRB(pDCB, pSRB); */
2698105059Scognet			psrb->pNextSRB = pACB->pFreeSRB;
2699105059Scognet			pACB->pFreeSRB = psrb;
2700105059Scognet			xpt_done(pccb);
2701105059Scognet			psrb  = psrb2;
2702105059Scognet		}
2703201758Smbr		pdcb->GoingSRBCnt = 0;
2704105059Scognet		pdcb->pGoingSRB = NULL;
2705105059Scognet		pdcb = pdcb->pNextDCB;
2706105059Scognet	}
2707105059Scognet	while (pdcb != pDCB);
2708105059Scognet}
2709105059Scognet
2710105059Scognetstatic void
2711105059Scognettrm_ResetSCSIBus(PACB pACB)
2712105059Scognet{
2713105059Scognet	int	intflag;
2714105059Scognet
2715105059Scognet	intflag = splcam();
2716105059Scognet    	pACB->ACBFlag |= RESET_DEV;
2717105059Scognet
2718105059Scognet	trm_reg_write16(DO_RSTSCSI,TRMREG_SCSI_CONTROL);
2719105059Scognet	while (!(trm_reg_read16(TRMREG_SCSI_INTSTATUS) & INT_SCSIRESET));
2720105059Scognet	splx(intflag);
2721105059Scognet	return;
2722105059Scognet}
2723105059Scognet
2724105059Scognetstatic void
2725105059Scognettrm_ScsiRstDetect(PACB pACB)
2726105059Scognet{
2727105059Scognet	int	intflag;
2728105059Scognet	u_long	wlval;
2729105059Scognet
2730105059Scognet	TRM_DPRINTF("trm_ScsiRstDetect \n");
2731105059Scognet	wlval = 1000;
2732105059Scognet	while (--wlval)
2733105059Scognet		DELAY(1000);
2734105059Scognet	intflag = splcam();
2735105059Scognet    	trm_reg_write8(STOPDMAXFER,TRMREG_DMA_CONTROL);
2736105059Scognet
2737105059Scognet	trm_reg_write16(DO_CLRFIFO,TRMREG_SCSI_CONTROL);
2738105059Scognet
2739105059Scognet	if (pACB->ACBFlag & RESET_DEV)
2740105059Scognet		pACB->ACBFlag |= RESET_DONE;
2741105059Scognet	else {
2742105059Scognet		pACB->ACBFlag |= RESET_DETECT;
2743105059Scognet		trm_ResetDevParam(pACB);
2744105059Scognet		/*	trm_DoingSRB_Done(pACB); ???? */
2745105059Scognet		trm_RecoverSRB(pACB);
2746105059Scognet		pACB->pActiveDCB = NULL;
2747105059Scognet		pACB->ACBFlag = 0;
2748105059Scognet		trm_DoWaitingSRB(pACB);
2749105059Scognet	}
2750105059Scognet	splx(intflag);
2751105059Scognet    	return;
2752105059Scognet}
2753105059Scognet
2754105059Scognetstatic void
2755105059Scognettrm_RequestSense(PACB pACB, PDCB pDCB, PSRB pSRB)
2756105059Scognet{
2757105059Scognet	union ccb		*pccb;
2758105059Scognet	struct ccb_scsiio	*pcsio;
2759105059Scognet
2760105059Scognet	pccb  = pSRB->pccb;
2761105059Scognet	pcsio = &pccb->csio;
2762105059Scognet
2763105059Scognet	pSRB->SRBFlag |= AUTO_REQSENSE;
2764105059Scognet	pSRB->Segment0[0] = *((u_long *) &(pSRB->CmdBlock[0]));
2765105059Scognet	pSRB->Segment0[1] = *((u_long *) &(pSRB->CmdBlock[4]));
2766105059Scognet	pSRB->Segment1[0] = (u_long) ((pSRB->ScsiCmdLen << 8) +
2767105059Scognet	    pSRB->SRBSGCount);
2768105059Scognet	pSRB->Segment1[1] = pSRB->SRBTotalXferLength; /* ?????????? */
2769105059Scognet
2770105059Scognet	/* $$$$$$ Status of initiator/target $$$$$$$$ */
2771105059Scognet	pSRB->AdaptStatus = 0;
2772105059Scognet	pSRB->TargetStatus = 0;
2773105059Scognet	/* $$$$$$ Status of initiator/target $$$$$$$$ */
2774105059Scognet
2775105059Scognet	pSRB->SRBTotalXferLength = sizeof(pcsio->sense_data);
2776111158Scognet	pSRB->SgSenseTemp.address = pSRB->pSRBSGL->address;
2777111158Scognet	pSRB->SgSenseTemp.length  = pSRB->pSRBSGL->length;
2778111158Scognet	pSRB->pSRBSGL->address = trm_get_sense_bufaddr(pACB, pSRB);
2779111158Scognet	pSRB->pSRBSGL->length = (u_long) sizeof(struct scsi_sense_data);
2780105059Scognet	pSRB->SRBSGCount = 1;
2781105059Scognet	pSRB->SRBSGIndex = 0;
2782105059Scognet
2783105059Scognet	*((u_long *) &(pSRB->CmdBlock[0])) = 0x00000003;
2784105059Scognet	pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5;
2785105059Scognet	*((u_int16_t *) &(pSRB->CmdBlock[4])) = pcsio->sense_len;
2786105059Scognet	pSRB->ScsiCmdLen = 6;
2787105059Scognet
2788105059Scognet	if (trm_StartSCSI(pACB, pDCB, pSRB))
2789105059Scognet	   /*
2790105059Scognet	    * If trm_StartSCSI return 1 :
2791105059Scognet	    * current interrupt status is interrupt disreenable
2792105059Scognet	    * It's said that SCSI processor has more one SRB need to do
2793105059Scognet	    */
2794105059Scognet		trm_RewaitSRB(pDCB, pSRB);
2795105059Scognet}
2796105059Scognet
2797105059Scognetstatic void
2798105059Scognettrm_EnableMsgOutAbort2(PACB pACB, PSRB pSRB)
2799105059Scognet{
2800105059Scognet
2801105059Scognet	pSRB->MsgCnt = 1;
2802105059Scognet	trm_reg_write16(DO_SETATN, TRMREG_SCSI_CONTROL);
2803105059Scognet}
2804105059Scognet
2805105059Scognetstatic void
2806105059Scognettrm_EnableMsgOutAbort1(PACB pACB, PSRB pSRB)
2807105059Scognet{
2808105059Scognet
2809105059Scognet	pSRB->MsgOutBuf[0] = MSG_ABORT;
2810105059Scognet	trm_EnableMsgOutAbort2(pACB, pSRB);
2811105059Scognet}
2812105059Scognet
2813105059Scognetstatic void
2814105059Scognettrm_initDCB(PACB pACB, PDCB pDCB, u_int16_t unit,u_int32_t i,u_int32_t j)
2815105059Scognet{
2816105059Scognet	PNVRAMTYPE 	pEEpromBuf;
2817105059Scognet	u_int8_t	bval,PeriodIndex;
2818105059Scognet	u_int		target_id,target_lun;
2819105059Scognet	PDCB		pTempDCB;
2820105059Scognet	int		intflag;
2821105059Scognet
2822105059Scognet    	target_id  = i;
2823105059Scognet	target_lun = j;
2824105059Scognet
2825111158Scognet	/*
2826111158Scognet	 *  Using the lun 0 device to init other DCB first, if the device
2827111158Scognet	 *  has been initialized.
2828111158Scognet	 *  I don't want init sync arguments one by one, it is the same.
2829111158Scognet	 */
2830111158Scognet	if (target_lun != 0 &&
2831111158Scognet	    (pACB->DCBarray[target_id][0].DCBstatus & DS_IN_QUEUE))
2832111158Scognet		bcopy(&pACB->DCBarray[target_id][0], pDCB,
2833111158Scognet		    sizeof(TRM_DCB));
2834105059Scognet	intflag = splcam();
2835105059Scognet	if (pACB->pLinkDCB == 0) {
2836105059Scognet		pACB->pLinkDCB = pDCB;
2837105059Scognet		/*
2838105059Scognet		 * RunRobin impersonate the role
2839105059Scognet		 * that let each device had good proportion
2840105059Scognet		 * about SCSI command proceeding
2841105059Scognet		 */
2842105059Scognet		pACB->pDCBRunRobin = pDCB;
2843105059Scognet		pDCB->pNextDCB = pDCB;
2844105059Scognet	} else {
2845105059Scognet		pTempDCB=pACB->pLinkDCB;
2846105059Scognet		/* search the last nod of DCB link */
2847105059Scognet		while (pTempDCB->pNextDCB != pACB->pLinkDCB)
2848105059Scognet			pTempDCB = pTempDCB->pNextDCB;
2849105059Scognet		/* connect current DCB with last DCB tail */
2850105059Scognet		pTempDCB->pNextDCB = pDCB;
2851105059Scognet		/* connect current DCB tail to this DCB Q head */
2852105059Scognet		pDCB->pNextDCB=pACB->pLinkDCB;
2853105059Scognet	}
2854105059Scognet	splx(intflag);
2855105059Scognet
2856105059Scognet	pACB->DeviceCnt++;
2857105059Scognet	pDCB->TargetID = target_id;
2858105059Scognet	pDCB->TargetLUN =  target_lun;
2859105059Scognet	pDCB->pWaitingSRB = NULL;
2860105059Scognet	pDCB->pGoingSRB = NULL;
2861105059Scognet	pDCB->GoingSRBCnt = 0;
2862105059Scognet	pDCB->pActiveSRB = NULL;
2863111158Scognet	pDCB->MaxActiveCommandCnt = 1;
2864105059Scognet	pDCB->DCBFlag = 0;
2865111158Scognet	pDCB->DCBstatus |= DS_IN_QUEUE;
2866105059Scognet	/* $$$$$$$ */
2867105059Scognet	pEEpromBuf = &trm_eepromBuf[unit];
2868105059Scognet	pDCB->DevMode = pEEpromBuf->NvramTarget[target_id].NvmTarCfg0;
2869105059Scognet	pDCB->AdpMode = pEEpromBuf->NvramChannelCfg;
2870105059Scognet	/* $$$$$$$ */
2871105059Scognet	/*
2872105059Scognet	 * disconnect enable ?
2873105059Scognet	 */
2874105059Scognet	if (pDCB->DevMode & NTC_DO_DISCONNECT) {
2875105059Scognet		bval = 0xC0;
2876105059Scognet		pDCB->tinfo.disc_tag |= TRM_USR_DISCENB ;
2877105059Scognet	} else {
2878105059Scognet		bval = 0x80;
2879105059Scognet		pDCB->tinfo.disc_tag &= ~(TRM_USR_DISCENB);
2880105059Scognet	}
2881105059Scognet	bval |= target_lun;
2882105059Scognet	pDCB->IdentifyMsg = bval;
2883111158Scognet	if (target_lun != 0 &&
2884111158Scognet	    (pACB->DCBarray[target_id][0].DCBstatus & DS_IN_QUEUE))
2885111158Scognet		return;
2886105059Scognet	/* $$$$$$$ */
2887105059Scognet	/*
2888105059Scognet	 * tag Qing enable ?
2889105059Scognet	 */
2890105059Scognet	if (pDCB->DevMode & TAG_QUEUING_) {
2891105059Scognet		pDCB->tinfo.disc_tag |= TRM_USR_TAGENB ;
2892105059Scognet	} else
2893105059Scognet		pDCB->tinfo.disc_tag &= ~(TRM_USR_TAGENB);
2894105059Scognet	/* $$$$$$$ */
2895105059Scognet	/*
2896105059Scognet	 * wide nego ,sync nego enable ?
2897105059Scognet	 */
2898105059Scognet	pDCB->SyncPeriod = 0;
2899105059Scognet	pDCB->SyncOffset = 0;
2900105059Scognet	PeriodIndex = pEEpromBuf->NvramTarget[target_id].NvmTarPeriod & 0x07;
2901116813Scognet	if (pACB->AdaptType==1) {/* is U2? */
2902111158Scognet	    pDCB->MaxNegoPeriod=dc395u2x_clock_period[ PeriodIndex ];
2903111158Scognet	    pDCB->tinfo.user.period=pDCB->MaxNegoPeriod;
2904111158Scognet	    pDCB->tinfo.user.offset=(pDCB->SyncMode & SYNC_NEGO_ENABLE) ? 31 : 0;
2905111158Scognet	} else {
2906111158Scognet        pDCB->MaxNegoPeriod=dc395x_clock_period[ PeriodIndex ];
2907111158Scognet	    pDCB->tinfo.user.period=pDCB->MaxNegoPeriod;
2908111158Scognet	    pDCB->tinfo.user.offset=(pDCB->SyncMode & SYNC_NEGO_ENABLE) ? 15 : 0;
2909111158Scognet	}
2910105059Scognet	pDCB->SyncMode = 0;
2911105059Scognet	if ((pDCB->DevMode & NTC_DO_WIDE_NEGO) &&
2912105059Scognet	    (pACB->Config & HCC_WIDE_CARD))
2913105059Scognet		pDCB->SyncMode |= WIDE_NEGO_ENABLE;
2914105059Scognet	/* enable wide nego */
2915105059Scognet   	if (pDCB->DevMode & NTC_DO_SYNC_NEGO)
2916105059Scognet		pDCB->SyncMode |= SYNC_NEGO_ENABLE;
2917105059Scognet	/* enable sync nego */
2918105059Scognet	/* $$$$$$$ */
2919105059Scognet	/*
2920105059Scognet	 *	Fill in tinfo structure.
2921105059Scognet	 */
2922105059Scognet	pDCB->tinfo.user.width  = (pDCB->SyncMode & WIDE_NEGO_ENABLE) ?
2923105059Scognet	  MSG_EXT_WDTR_BUS_16_BIT : MSG_EXT_WDTR_BUS_8_BIT;
2924105059Scognet
2925105059Scognet	pDCB->tinfo.current.period = 0;
2926105059Scognet	pDCB->tinfo.current.offset = 0;
2927105059Scognet	pDCB->tinfo.current.width = MSG_EXT_WDTR_BUS_8_BIT;
2928105059Scognet}
2929105059Scognet
2930111158Scognetstatic void
2931111158Scognettrm_srbmapSG(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2932105059Scognet{
2933111158Scognet	PSRB pSRB;
2934111158Scognet
2935111158Scognet	pSRB=(PSRB) arg;
2936111158Scognet	pSRB->SRBSGPhyAddr=segs->ds_addr;
2937111158Scognet	return;
2938105059Scognet}
2939105059Scognet
2940126725Scognetstatic void
2941126725Scognettrm_destroySRB(PACB pACB)
2942126725Scognet{
2943126725Scognet	PSRB pSRB;
2944126725Scognet
2945126725Scognet	pSRB = pACB->pFreeSRB;
2946126725Scognet	while (pSRB) {
2947126725Scognet		if (pSRB->sg_dmamap) {
2948126725Scognet			bus_dmamap_unload(pACB->sg_dmat, pSRB->sg_dmamap);
2949126725Scognet			bus_dmamem_free(pACB->sg_dmat, pSRB->pSRBSGL,
2950126725Scognet			    pSRB->sg_dmamap);
2951126725Scognet			bus_dmamap_destroy(pACB->sg_dmat, pSRB->sg_dmamap);
2952126725Scognet		}
2953126725Scognet		if (pSRB->dmamap)
2954126725Scognet			bus_dmamap_destroy(pACB->buffer_dmat, pSRB->dmamap);
2955126725Scognet		pSRB = pSRB->pNextSRB;
2956126725Scognet	}
2957126725Scognet}
2958126725Scognet
2959111158Scognetstatic int
2960111158Scognettrm_initSRB(PACB pACB)
2961105059Scognet{
2962116813Scognet    	u_int16_t    i;
2963116813Scognet	PSRB    pSRB;
2964118693Sscottl	int error;
2965105059Scognet
2966116813Scognet	for (i = 0; i < TRM_MAX_SRB_CNT; i++) {
2967116813Scognet	       	pSRB = (PSRB)&pACB->pFreeSRB[i];
2968111158Scognet
2969126725Scognet		if (bus_dmamem_alloc(pACB->sg_dmat, (void **)&pSRB->pSRBSGL,
2970116813Scognet		    BUS_DMA_NOWAIT, &pSRB->sg_dmamap) !=0 ) {
2971116813Scognet			return ENXIO;
2972111158Scognet		}
2973126725Scognet		bus_dmamap_load(pACB->sg_dmat, pSRB->sg_dmamap, pSRB->pSRBSGL,
2974116813Scognet		    TRM_MAX_SG_LISTENTRY * sizeof(SGentry),
2975116813Scognet		    trm_srbmapSG, pSRB, /*flags*/0);
2976116813Scognet		if (i != TRM_MAX_SRB_CNT - 1) {
2977116813Scognet			/*
2978116813Scognet			 * link all SRB
2979116813Scognet			 */
2980116813Scognet			pSRB->pNextSRB = &pACB->pFreeSRB[i+1];
2981116813Scognet		} else {
2982116813Scognet			/*
2983116813Scognet			 * load NULL to NextSRB of the last SRB
2984116813Scognet			 */
2985116813Scognet			pSRB->pNextSRB = NULL;
2986116813Scognet		}
2987116813Scognet		pSRB->TagNumber = i;
2988118693Sscottl
2989118693Sscottl		/*
2990118693Sscottl		 * Create the dmamap.  This is no longer optional!
2991118693Sscottl		 */
2992118693Sscottl		if ((error = bus_dmamap_create(pACB->buffer_dmat, 0,
2993118693Sscottl					       &pSRB->dmamap)) != 0)
2994118693Sscottl			return (error);
2995118693Sscottl
2996105059Scognet	}
2997116813Scognet	return (0);
2998105059Scognet}
2999105059Scognet
3000105059Scognet
3001111158Scognet
3002111158Scognet
3003105059Scognetstatic void
3004111158Scognettrm_initACB(PACB pACB, u_int8_t adaptType, u_int16_t unit)
3005105059Scognet{
3006105059Scognet	PNVRAMTYPE	pEEpromBuf;
3007105059Scognet
3008105059Scognet	pEEpromBuf = &trm_eepromBuf[unit];
3009105059Scognet	pACB->max_id = 15;
3010105059Scognet
3011105059Scognet	if (pEEpromBuf->NvramChannelCfg & NAC_SCANLUN)
3012105059Scognet  		pACB->max_lun = 7;
3013105059Scognet	else
3014105059Scognet		pACB->max_lun = 0;
3015105059Scognet
3016105059Scognet	TRM_DPRINTF("trm: pACB->max_id= %d pACB->max_lun= %d \n",
3017105059Scognet	    pACB->max_id, pACB->max_lun);
3018105059Scognet	pACB->pLinkDCB = NULL;
3019105059Scognet	pACB->pDCBRunRobin = NULL;
3020105059Scognet	pACB->pActiveDCB = NULL;
3021111158Scognet	pACB->AdapterUnit = (u_int8_t)unit;
3022105059Scognet	pACB->AdaptSCSIID = pEEpromBuf->NvramScsiId;
3023105059Scognet	pACB->AdaptSCSILUN = 0;
3024105059Scognet	pACB->DeviceCnt = 0;
3025111158Scognet	pACB->AdaptType = adaptType;
3026111158Scognet	pACB->TagMaxNum = 2 << pEEpromBuf->NvramMaxTag;
3027105059Scognet	pACB->ACBFlag = 0;
3028111158Scognet	return;
3029105059Scognet}
3030105059Scognet
3031105059Scognetstatic void
3032111158ScognetNVRAM_trm_write_all(PNVRAMTYPE pEEpromBuf,PACB pACB)
3033105059Scognet{
3034105059Scognet	u_int8_t	*bpEeprom = (u_int8_t *) pEEpromBuf;
3035105059Scognet	u_int8_t	bAddr;
3036105059Scognet
3037105059Scognet	/* Enable SEEPROM */
3038105059Scognet	trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) | EN_EEPROM),
3039105059Scognet	    TRMREG_GEN_CONTROL);
3040105059Scognet	/*
3041105059Scognet	 * Write enable
3042105059Scognet	 */
3043111158Scognet	NVRAM_trm_write_cmd(pACB, 0x04, 0xFF);
3044105059Scognet	trm_reg_write8(0, TRMREG_GEN_NVRAM);
3045111158Scognet	NVRAM_trm_wait_30us(pACB);
3046105059Scognet	for (bAddr = 0; bAddr < 128; bAddr++, bpEeprom++) {
3047111158Scognet		NVRAM_trm_set_data(pACB, bAddr, *bpEeprom);
3048105059Scognet	}
3049105059Scognet	/*
3050105059Scognet	 * Write disable
3051105059Scognet	 */
3052111158Scognet	NVRAM_trm_write_cmd(pACB, 0x04, 0x00);
3053105059Scognet	trm_reg_write8(0 , TRMREG_GEN_NVRAM);
3054111158Scognet	NVRAM_trm_wait_30us(pACB);
3055105059Scognet	/* Disable SEEPROM */
3056105059Scognet	trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) & ~EN_EEPROM),
3057105059Scognet	    TRMREG_GEN_CONTROL);
3058105059Scognet	return;
3059105059Scognet}
3060105059Scognet
3061105059Scognetstatic void
3062111158ScognetNVRAM_trm_set_data(PACB pACB, u_int8_t bAddr, u_int8_t bData)
3063105059Scognet{
3064105059Scognet	int		i;
3065105059Scognet	u_int8_t	bSendData;
3066105059Scognet	/*
3067105059Scognet	 * Send write command & address
3068105059Scognet	 */
3069105059Scognet
3070111158Scognet	NVRAM_trm_write_cmd(pACB, 0x05, bAddr);
3071105059Scognet	/*
3072105059Scognet	 * Write data
3073105059Scognet	 */
3074105059Scognet	for (i = 0; i < 8; i++, bData <<= 1) {
3075105059Scognet		bSendData = NVR_SELECT;
3076105059Scognet		if (bData & 0x80)
3077105059Scognet		  /* Start from bit 7	*/
3078105059Scognet			bSendData |= NVR_BITOUT;
3079105059Scognet		trm_reg_write8(bSendData , TRMREG_GEN_NVRAM);
3080111158Scognet		NVRAM_trm_wait_30us(pACB);
3081105059Scognet		trm_reg_write8((bSendData | NVR_CLOCK), TRMREG_GEN_NVRAM);
3082111158Scognet		NVRAM_trm_wait_30us(pACB);
3083105059Scognet	}
3084105059Scognet	trm_reg_write8(NVR_SELECT , TRMREG_GEN_NVRAM);
3085111158Scognet	NVRAM_trm_wait_30us(pACB);
3086105059Scognet	/*
3087105059Scognet	 * Disable chip select
3088105059Scognet	 */
3089105059Scognet	trm_reg_write8(0 , TRMREG_GEN_NVRAM);
3090111158Scognet	NVRAM_trm_wait_30us(pACB);
3091105059Scognet	trm_reg_write8(NVR_SELECT ,TRMREG_GEN_NVRAM);
3092111158Scognet	NVRAM_trm_wait_30us(pACB);
3093105059Scognet	/*
3094105059Scognet	 * Wait for write ready
3095105059Scognet	 */
3096105059Scognet	while (1) {
3097105059Scognet		trm_reg_write8((NVR_SELECT | NVR_CLOCK), TRMREG_GEN_NVRAM);
3098111158Scognet		NVRAM_trm_wait_30us(pACB);
3099105059Scognet		trm_reg_write8(NVR_SELECT, TRMREG_GEN_NVRAM);
3100111158Scognet		NVRAM_trm_wait_30us(pACB);
3101105059Scognet		if (trm_reg_read8(TRMREG_GEN_NVRAM) & NVR_BITIN) {
3102105059Scognet			break;
3103105059Scognet		}
3104105059Scognet	}
3105105059Scognet	/*
3106105059Scognet	 * Disable chip select
3107105059Scognet	 */
3108105059Scognet	trm_reg_write8(0, TRMREG_GEN_NVRAM);
3109105059Scognet	return;
3110105059Scognet}
3111105059Scognet
3112105059Scognetstatic void
3113111158ScognetNVRAM_trm_read_all(PNVRAMTYPE pEEpromBuf, PACB pACB)
3114105059Scognet{
3115105059Scognet	u_int8_t	*bpEeprom = (u_int8_t*) pEEpromBuf;
3116105059Scognet	u_int8_t	bAddr;
3117105059Scognet
3118105059Scognet	/*
3119105059Scognet	 * Enable SEEPROM
3120105059Scognet	 */
3121105059Scognet	trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) | EN_EEPROM),
3122105059Scognet	    TRMREG_GEN_CONTROL);
3123105059Scognet	for (bAddr = 0; bAddr < 128; bAddr++, bpEeprom++)
3124111158Scognet		*bpEeprom = NVRAM_trm_get_data(pACB, bAddr);
3125105059Scognet	/*
3126105059Scognet	 * Disable SEEPROM
3127105059Scognet	 */
3128105059Scognet	trm_reg_write8((trm_reg_read8(TRMREG_GEN_CONTROL) & ~EN_EEPROM),
3129105059Scognet	    TRMREG_GEN_CONTROL);
3130105059Scognet	return;
3131105059Scognet}
3132105059Scognet
3133105059Scognetstatic u_int8_t
3134111158ScognetNVRAM_trm_get_data(PACB pACB, u_int8_t bAddr)
3135105059Scognet{
3136105059Scognet	int		i;
3137105059Scognet	u_int8_t	bReadData, bData = 0;
3138105059Scognet	/*
3139105059Scognet	* Send read command & address
3140105059Scognet	*/
3141105059Scognet
3142111158Scognet	NVRAM_trm_write_cmd(pACB, 0x06, bAddr);
3143105059Scognet
3144105059Scognet	for (i = 0; i < 8; i++) {
3145105059Scognet	  /*
3146105059Scognet	   * Read data
3147105059Scognet	   */
3148105059Scognet		trm_reg_write8((NVR_SELECT | NVR_CLOCK) , TRMREG_GEN_NVRAM);
3149111158Scognet		NVRAM_trm_wait_30us(pACB);
3150105059Scognet		trm_reg_write8(NVR_SELECT , TRMREG_GEN_NVRAM);
3151105059Scognet		/*
3152105059Scognet		 * Get data bit while falling edge
3153105059Scognet		 */
3154105059Scognet		bReadData = trm_reg_read8(TRMREG_GEN_NVRAM);
3155105059Scognet		bData <<= 1;
3156105059Scognet		if (bReadData & NVR_BITIN) {
3157105059Scognet			bData |= 1;
3158105059Scognet		}
3159111158Scognet		NVRAM_trm_wait_30us(pACB);
3160105059Scognet	}
3161105059Scognet	/*
3162105059Scognet	 * Disable chip select
3163105059Scognet	 */
3164105059Scognet	trm_reg_write8(0, TRMREG_GEN_NVRAM);
3165105059Scognet	return (bData);
3166105059Scognet}
3167105059Scognet
3168105059Scognetstatic void
3169111158ScognetNVRAM_trm_wait_30us(PACB pACB)
3170105059Scognet{
3171105059Scognet
3172105059Scognet	/*    ScsiPortStallExecution(30);	 wait 30 us	*/
3173105059Scognet	trm_reg_write8(5, TRMREG_GEN_TIMER);
3174105059Scognet	while (!(trm_reg_read8(TRMREG_GEN_STATUS) & GTIMEOUT));
3175105059Scognet	return;
3176105059Scognet}
3177105059Scognet
3178105059Scognetstatic void
3179111158ScognetNVRAM_trm_write_cmd(PACB pACB, u_int8_t bCmd, u_int8_t bAddr)
3180105059Scognet{
3181105059Scognet	int		i;
3182105059Scognet	u_int8_t	bSendData;
3183105059Scognet
3184105059Scognet    	for (i = 0; i < 3; i++, bCmd <<= 1) {
3185105059Scognet	  /*
3186105059Scognet   	   * Program SB+OP code
3187105059Scognet   	   */
3188105059Scognet     		bSendData = NVR_SELECT;
3189105059Scognet		if (bCmd & 0x04)
3190105059Scognet			bSendData |= NVR_BITOUT;
3191105059Scognet		/* start from bit 2 */
3192105059Scognet		trm_reg_write8(bSendData, TRMREG_GEN_NVRAM);
3193111158Scognet		NVRAM_trm_wait_30us(pACB);
3194105059Scognet		trm_reg_write8((bSendData | NVR_CLOCK), TRMREG_GEN_NVRAM);
3195111158Scognet		NVRAM_trm_wait_30us(pACB);
3196105059Scognet	}
3197105059Scognet	for (i = 0; i < 7; i++, bAddr <<= 1) {
3198105059Scognet	  /*
3199105059Scognet	   * Program address
3200105059Scognet	   */
3201105059Scognet		bSendData = NVR_SELECT;
3202105059Scognet		if (bAddr & 0x40)
3203105059Scognet		  /* Start from bit 6	*/
3204105059Scognet			bSendData |= NVR_BITOUT;
3205105059Scognet		trm_reg_write8(bSendData , TRMREG_GEN_NVRAM);
3206111158Scognet		NVRAM_trm_wait_30us(pACB);
3207105059Scognet		trm_reg_write8((bSendData | NVR_CLOCK), TRMREG_GEN_NVRAM);
3208111158Scognet		NVRAM_trm_wait_30us(pACB);
3209105059Scognet	}
3210105059Scognet	trm_reg_write8(NVR_SELECT, TRMREG_GEN_NVRAM);
3211111158Scognet	NVRAM_trm_wait_30us(pACB);
3212105059Scognet}
3213105059Scognet
3214105059Scognetstatic void
3215105059Scognettrm_check_eeprom(PNVRAMTYPE pEEpromBuf, PACB pACB)
3216105059Scognet{
3217105059Scognet	u_int16_t	*wpEeprom = (u_int16_t *) pEEpromBuf;
3218105059Scognet	u_int16_t	wAddr, wCheckSum;
3219105059Scognet	u_long	dAddr, *dpEeprom;
3220105059Scognet
3221111158Scognet	NVRAM_trm_read_all(pEEpromBuf,pACB);
3222105059Scognet	wCheckSum = 0;
3223105059Scognet	for (wAddr = 0, wpEeprom = (u_int16_t *) pEEpromBuf;
3224105059Scognet	    wAddr < 64; wAddr++, wpEeprom++) {
3225105059Scognet		wCheckSum += *wpEeprom;
3226105059Scognet	}
3227105059Scognet	if (wCheckSum != 0x1234) {
3228105059Scognet	  /*
3229105059Scognet   	   * Checksum error, load default
3230105059Scognet	   */
3231105059Scognet		pEEpromBuf->NvramSubVendorID[0]	= (u_int8_t) PCI_Vendor_ID_TEKRAM;
3232105059Scognet		pEEpromBuf->NvramSubVendorID[1]	=
3233105059Scognet		  (u_int8_t) (PCI_Vendor_ID_TEKRAM >> 8);
3234105059Scognet		pEEpromBuf->NvramSubSysID[0] = (u_int8_t) PCI_Device_ID_TRM_S1040;
3235105059Scognet		pEEpromBuf->NvramSubSysID[1] =
3236105059Scognet		  (u_int8_t) (PCI_Device_ID_TRM_S1040 >> 8);
3237105059Scognet		pEEpromBuf->NvramSubClass = 0x00;
3238105059Scognet		pEEpromBuf->NvramVendorID[0] = (u_int8_t) PCI_Vendor_ID_TEKRAM;
3239105059Scognet		pEEpromBuf->NvramVendorID[1] =
3240105059Scognet		  (u_int8_t) (PCI_Vendor_ID_TEKRAM >> 8);
3241105059Scognet		pEEpromBuf->NvramDeviceID[0] = (u_int8_t) PCI_Device_ID_TRM_S1040;
3242105059Scognet		pEEpromBuf->NvramDeviceID[1] =
3243105059Scognet		  (u_int8_t) (PCI_Device_ID_TRM_S1040 >> 8);
3244105059Scognet		pEEpromBuf->NvramReserved = 0x00;
3245105059Scognet
3246105059Scognet		for (dAddr = 0, dpEeprom = (u_long *) pEEpromBuf->NvramTarget;
3247105059Scognet		    dAddr < 16; dAddr++, dpEeprom++) {
3248105059Scognet			*dpEeprom = 0x00000077;
3249105059Scognet			/* NvmTarCfg3,NvmTarCfg2,NvmTarPeriod,NvmTarCfg0 */
3250105059Scognet		}
3251105059Scognet
3252105059Scognet		*dpEeprom++ = 0x04000F07;
3253105059Scognet		/* NvramMaxTag,NvramDelayTime,NvramChannelCfg,NvramScsiId */
3254105059Scognet		*dpEeprom++ = 0x00000015;
3255105059Scognet		/* NvramReserved1,NvramBootLun,NvramBootTarget,NvramReserved0 */
3256105059Scognet		for (dAddr = 0; dAddr < 12; dAddr++, dpEeprom++)
3257105059Scognet			*dpEeprom = 0x00;
3258105059Scognet		pEEpromBuf->NvramCheckSum = 0x00;
3259105059Scognet		for (wAddr = 0, wCheckSum = 0, wpEeprom = (u_int16_t *) pEEpromBuf;
3260105059Scognet		    wAddr < 63; wAddr++, wpEeprom++)
3261105059Scognet	      		wCheckSum += *wpEeprom;
3262105059Scognet		*wpEeprom = 0x1234 - wCheckSum;
3263111158Scognet		NVRAM_trm_write_all(pEEpromBuf,pACB);
3264105059Scognet	}
3265105059Scognet	return;
3266105059Scognet}
3267105059Scognetstatic int
3268111158Scognettrm_initAdapter(PACB pACB, u_int16_t unit)
3269105059Scognet{
3270105059Scognet	PNVRAMTYPE	pEEpromBuf;
3271105059Scognet	u_int16_t	wval;
3272105059Scognet	u_int8_t	bval;
3273105059Scognet
3274105059Scognet	pEEpromBuf = &trm_eepromBuf[unit];
3275105059Scognet
3276105059Scognet	/* 250ms selection timeout */
3277105059Scognet	trm_reg_write8(SEL_TIMEOUT, TRMREG_SCSI_TIMEOUT);
3278105059Scognet	/* Mask all the interrupt */
3279105059Scognet	trm_reg_write8(0x00, TRMREG_DMA_INTEN);
3280105059Scognet	trm_reg_write8(0x00, TRMREG_SCSI_INTEN);
3281105059Scognet	/* Reset SCSI module */
3282105059Scognet	trm_reg_write16(DO_RSTMODULE, TRMREG_SCSI_CONTROL);
3283105059Scognet	/* program configuration 0 */
3284105059Scognet	pACB->Config = HCC_AUTOTERM | HCC_PARITY;
3285105059Scognet	if (trm_reg_read8(TRMREG_GEN_STATUS) & WIDESCSI)
3286105059Scognet		pACB->Config |= HCC_WIDE_CARD;
3287105059Scognet	if (pEEpromBuf->NvramChannelCfg & NAC_POWERON_SCSI_RESET)
3288105059Scognet		pACB->Config |= HCC_SCSI_RESET;
3289105059Scognet	if (pACB->Config & HCC_PARITY)
3290105059Scognet		bval = PHASELATCH | INITIATOR | BLOCKRST | PARITYCHECK;
3291105059Scognet	else
3292105059Scognet		bval = PHASELATCH | INITIATOR | BLOCKRST ;
3293105059Scognet	trm_reg_write8(bval,TRMREG_SCSI_CONFIG0);
3294105059Scognet	/* program configuration 1 */
3295105059Scognet	trm_reg_write8(0x13, TRMREG_SCSI_CONFIG1);
3296105059Scognet	/* program Host ID */
3297105059Scognet	bval = pEEpromBuf->NvramScsiId;
3298105059Scognet	trm_reg_write8(bval, TRMREG_SCSI_HOSTID);
3299105059Scognet	/* set ansynchronous transfer */
3300105059Scognet	trm_reg_write8(0x00, TRMREG_SCSI_OFFSET);
3301105059Scognet	/* Trun LED control off*/
3302105059Scognet	wval = trm_reg_read16(TRMREG_GEN_CONTROL) & 0x7F;
3303105059Scognet	trm_reg_write16(wval, TRMREG_GEN_CONTROL);
3304105059Scognet	/* DMA config */
3305105059Scognet	wval = trm_reg_read16(TRMREG_DMA_CONFIG) | DMA_ENHANCE;
3306105059Scognet	trm_reg_write16(wval, TRMREG_DMA_CONFIG);
3307105059Scognet	/* Clear pending interrupt status */
3308105059Scognet	trm_reg_read8(TRMREG_SCSI_INTSTATUS);
3309105059Scognet	/* Enable SCSI interrupt */
3310105059Scognet	trm_reg_write8(0x7F, TRMREG_SCSI_INTEN);
3311105059Scognet	trm_reg_write8(EN_SCSIINTR, TRMREG_DMA_INTEN);
3312105059Scognet	return (0);
3313105059Scognet}
3314105059Scognet
3315111158Scognetstatic void
3316111158Scognettrm_mapSRB(void *arg, bus_dma_segment_t *segs, int nseg, int error)
3317111158Scognet{
3318111158Scognet	PACB pACB;
3319111158Scognet
3320111158Scognet	pACB = (PACB)arg;
3321111158Scognet	pACB->srb_physbase = segs->ds_addr;
3322111158Scognet}
3323111158Scognet
3324111158Scognetstatic void
3325111158Scognettrm_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
3326111158Scognet{
3327111158Scognet	bus_addr_t *baddr;
3328111158Scognet
3329111158Scognet	baddr = (bus_addr_t *)arg;
3330111158Scognet	*baddr = segs->ds_addr;
3331111158Scognet}
3332111158Scognet
3333105059Scognetstatic PACB
3334111158Scognettrm_init(u_int16_t unit, device_t dev)
3335105059Scognet{
3336105059Scognet	PACB		pACB;
3337119690Sjhb	int		rid = PCIR_BAR(0), i = 0, j = 0;
3338111158Scognet	u_int16_t	adaptType = 0;
3339105059Scognet
3340111158Scognet 	pACB = (PACB) device_get_softc(dev);
3341105059Scognet   	if (!pACB) {
3342105059Scognet		printf("trm%d: cannot allocate ACB !\n", unit);
3343105059Scognet		return (NULL);
3344105059Scognet	}
3345127135Snjl	pACB->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
3346127135Snjl	    &rid, RF_ACTIVE);
3347107928Scognet    	if (pACB->iores == NULL) {
3348105059Scognet		printf("trm_init: bus_alloc_resource failed!\n");
3349105059Scognet		return (NULL);
3350105059Scognet	}
3351111158Scognet	switch (pci_get_devid(dev)) {
3352111158Scognet	case PCI_DEVICEID_TRMS1040:
3353111158Scognet		adaptType = 0;
3354111158Scognet		break;
3355111158Scognet	case PCI_DEVICEID_TRMS2080:
3356111158Scognet		adaptType = 1;
3357111158Scognet		break;
3358111158Scognet	default:
3359111158Scognet		printf("trm_init %d: unknown adapter type!\n", unit);
3360111158Scognet		goto bad;
3361111158Scognet	}
3362111158Scognet	pACB->dev = dev;
3363107928Scognet	pACB->tag = rman_get_bustag(pACB->iores);
3364107928Scognet	pACB->bsh = rman_get_bushandle(pACB->iores);
3365117126Sscottl	if (bus_dma_tag_create(
3366232874Sscottl	/*parent_dmat*/	bus_get_dma_tag(dev),
3367232874Sscottl	/*alignment*/	1,
3368232874Sscottl	/*boundary*/	0,
3369232874Sscottl	/*lowaddr*/	BUS_SPACE_MAXADDR,
3370232874Sscottl	/*highaddr*/	BUS_SPACE_MAXADDR,
3371232874Sscottl	/*filter*/	NULL,
3372232874Sscottl	/*filterarg*/	NULL,
3373232874Sscottl	/*maxsize*/	BUS_SPACE_MAXSIZE_32BIT,
3374232874Sscottl	/*nsegments*/	BUS_SPACE_UNRESTRICTED,
3375232874Sscottl	/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
3376232874Sscottl	/*flags*/	0,
3377232874Sscottl	/*lockfunc*/	NULL,
3378232874Sscottl	/*lockarg*/	NULL,
3379232874Sscottl	/* dmat */	&pACB->parent_dmat) != 0)
3380232874Sscottl		goto bad;
3381232874Sscottl	if (bus_dma_tag_create(
3382117126Sscottl	/*parent_dmat*/	pACB->parent_dmat,
3383117126Sscottl	/*alignment*/	1,
3384117126Sscottl	/*boundary*/	0,
3385117126Sscottl	/*lowaddr*/	BUS_SPACE_MAXADDR,
3386117126Sscottl	/*highaddr*/	BUS_SPACE_MAXADDR,
3387117126Sscottl	/*filter*/	NULL,
3388117126Sscottl	/*filterarg*/	NULL,
3389117126Sscottl	/*maxsize*/	MAXBSIZE,
3390117126Sscottl	/*nsegments*/	TRM_NSEG,
3391117126Sscottl	/*maxsegsz*/	TRM_MAXTRANSFER_SIZE,
3392117126Sscottl	/*flags*/	BUS_DMA_ALLOCNOW,
3393117126Sscottl	/*lockfunc*/	busdma_lock_mutex,
3394117126Sscottl	/*lockarg*/	&Giant,
3395117126Sscottl	/* dmat */	&pACB->buffer_dmat) != 0)
3396107928Scognet		goto bad;
3397111158Scognet	/* DMA tag for our ccb structures */
3398116813Scognet	if (bus_dma_tag_create(
3399111158Scognet	/*parent_dmat*/pACB->parent_dmat,
3400111158Scognet	/*alignment*/  1,
3401111158Scognet	/*boundary*/   0,
3402111158Scognet	/*lowaddr*/    BUS_SPACE_MAXADDR,
3403111158Scognet	/*highaddr*/   BUS_SPACE_MAXADDR,
3404111158Scognet	/*filter*/     NULL,
3405111158Scognet	/*filterarg*/  NULL,
3406111158Scognet	/*maxsize*/    TRM_MAX_SRB_CNT * sizeof(TRM_SRB),
3407111158Scognet	/*nsegments*/  1,
3408111158Scognet	/*maxsegsz*/   TRM_MAXTRANSFER_SIZE,
3409117126Sscottl	/*flags*/      0,
3410117126Sscottl	/*lockfunc*/   busdma_lock_mutex,
3411117126Sscottl	/*lockarg*/    &Giant,
3412111158Scognet	/*dmat*/       &pACB->srb_dmat) != 0) {
3413111158Scognet		printf("trm_init %d: bus_dma_tag_create SRB failure\n", unit);
3414111158Scognet		goto bad;
3415111158Scognet	}
3416111158Scognet	if (bus_dmamem_alloc(pACB->srb_dmat, (void **)&pACB->pFreeSRB,
3417111158Scognet	    BUS_DMA_NOWAIT, &pACB->srb_dmamap) != 0) {
3418111158Scognet		printf("trm_init %d: bus_dmamem_alloc SRB failure\n", unit);
3419111158Scognet		goto bad;
3420111158Scognet	}
3421111158Scognet	bus_dmamap_load(pACB->srb_dmat, pACB->srb_dmamap, pACB->pFreeSRB,
3422111158Scognet	    TRM_MAX_SRB_CNT * sizeof(TRM_SRB), trm_mapSRB, pACB,
3423111158Scognet	    /* flags */0);
3424111158Scognet	/* Create, allocate, and map DMA buffers for autosense data */
3425232874Sscottl	if (bus_dma_tag_create(
3426232874Sscottl	    /*parent_dmat*/pACB->parent_dmat,
3427232874Sscottl	    /*alignment*/1,
3428111158Scognet	    /*boundary*/0,
3429111158Scognet	    /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
3430111158Scognet	    /*highaddr*/BUS_SPACE_MAXADDR,
3431111158Scognet	    /*filter*/NULL, /*filterarg*/NULL,
3432111158Scognet	    sizeof(struct scsi_sense_data) * TRM_MAX_SRB_CNT,
3433111158Scognet	    /*nsegments*/1,
3434111158Scognet	    /*maxsegsz*/TRM_MAXTRANSFER_SIZE,
3435117126Sscottl	    /*flags*/0, /*lockfunc*/busdma_lock_mutex,
3436117126Sscottl	    /*lockarg*/&Giant, &pACB->sense_dmat) != 0) {
3437111158Scognet	  if (bootverbose)
3438111158Scognet	    device_printf(dev, "cannot create sense buffer dmat\n");
3439111158Scognet	  goto bad;
3440111158Scognet	}
3441111158Scognet
3442111158Scognet	if (bus_dmamem_alloc(pACB->sense_dmat, (void **)&pACB->sense_buffers,
3443111158Scognet			     BUS_DMA_NOWAIT, &pACB->sense_dmamap) != 0)
3444111158Scognet		goto bad;
3445111158Scognet
3446111158Scognet	bus_dmamap_load(pACB->sense_dmat, pACB->sense_dmamap,
3447111158Scognet		       pACB->sense_buffers,
3448111158Scognet		       sizeof(struct scsi_sense_data) * TRM_MAX_SRB_CNT,
3449111158Scognet		       trm_dmamap_cb, &pACB->sense_busaddr, /*flags*/0);
3450111158Scognet
3451105059Scognet	trm_check_eeprom(&trm_eepromBuf[unit],pACB);
3452111158Scognet	trm_initACB(pACB, adaptType, unit);
3453111158Scognet	for (i = 0; i < (pACB->max_id + 1); i++) {
3454111158Scognet		if (pACB->AdaptSCSIID == i)
3455111158Scognet			continue;
3456111158Scognet		for(j = 0; j < (pACB->max_lun + 1); j++) {
3457111158Scognet			pACB->scan_devices[i][j] = 1;
3458111158Scognet			/* we assume we need to scan all devices */
3459111158Scognet			trm_initDCB(pACB, &pACB->DCBarray[i][j], unit, i, j);
3460111158Scognet		}
3461111158Scognet	}
3462111158Scognet	bzero(pACB->pFreeSRB, TRM_MAX_SRB_CNT * sizeof(TRM_SRB));
3463126725Scognet	if (bus_dma_tag_create(
3464232874Sscottl		    /*parent_dmat*/pACB->parent_dmat,
3465126725Scognet		    /*alignment*/  1,
3466126725Scognet		    /*boundary*/   0,
3467126725Scognet		    /*lowaddr*/    BUS_SPACE_MAXADDR,
3468126725Scognet		    /*highaddr*/   BUS_SPACE_MAXADDR,
3469126725Scognet		    /*filter*/     NULL,
3470126725Scognet		    /*filterarg*/  NULL,
3471126725Scognet		    /*maxsize*/    TRM_MAX_SG_LISTENTRY * sizeof(SGentry),
3472126725Scognet		    /*nsegments*/  1,
3473126725Scognet		    /*maxsegsz*/   TRM_MAXTRANSFER_SIZE,
3474126725Scognet		    /*flags*/      0,
3475126725Scognet		    /*lockfunc*/   busdma_lock_mutex,
3476126725Scognet		    /*lockarg*/    &Giant,
3477126725Scognet		    /*dmat*/       &pACB->sg_dmat) != 0)
3478126725Scognet		goto bad;
3479126725Scognet
3480111158Scognet	if (trm_initSRB(pACB)) {
3481111158Scognet		printf("trm_initSRB: error\n");
3482111158Scognet		goto bad;
3483111158Scognet	}
3484111158Scognet   	if (trm_initAdapter(pACB, unit)) {
3485105059Scognet		printf("trm_initAdapter: initial ERROR\n");
3486107928Scognet		goto bad;
3487105059Scognet	}
3488105059Scognet	return (pACB);
3489107928Scognetbad:
3490107928Scognet	if (pACB->iores)
3491119690Sjhb		bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0),
3492107928Scognet		    pACB->iores);
3493111158Scognet	if (pACB->sense_dmamap) {
3494111158Scognet		bus_dmamap_unload(pACB->sense_dmat, pACB->sense_dmamap);
3495111158Scognet		bus_dmamem_free(pACB->sense_dmat, pACB->sense_buffers,
3496111158Scognet		    pACB->sense_dmamap);
3497111158Scognet		bus_dmamap_destroy(pACB->sense_dmat, pACB->sense_dmamap);
3498111158Scognet	}
3499111158Scognet	if (pACB->sense_dmat)
3500111158Scognet		bus_dma_tag_destroy(pACB->sense_dmat);
3501126725Scognet	if (pACB->sg_dmat) {
3502126725Scognet		trm_destroySRB(pACB);
3503126725Scognet		bus_dma_tag_destroy(pACB->sg_dmat);
3504126725Scognet	}
3505111158Scognet	if (pACB->srb_dmamap) {
3506111158Scognet		bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap);
3507111158Scognet		bus_dmamem_free(pACB->srb_dmat, pACB->pFreeSRB,
3508111158Scognet		    pACB->srb_dmamap);
3509111158Scognet		bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap);
3510111158Scognet	}
3511111158Scognet	if (pACB->srb_dmat)
3512111158Scognet		bus_dma_tag_destroy(pACB->srb_dmat);
3513107928Scognet	if (pACB->buffer_dmat)
3514107928Scognet		bus_dma_tag_destroy(pACB->buffer_dmat);
3515232874Sscottl	if (pACB->parent_dmat)
3516232874Sscottl		bus_dma_tag_destroy(pACB->parent_dmat);
3517107928Scognet	return (NULL);
3518105059Scognet}
3519105059Scognet
3520105059Scognetstatic int
3521111158Scognettrm_attach(device_t dev)
3522105059Scognet{
3523105059Scognet	struct	cam_devq *device_Q;
3524105059Scognet	u_long	device_id;
3525105059Scognet	PACB	pACB = 0;
3526105059Scognet	int	rid = 0;
3527111158Scognet	int unit = device_get_unit(dev);
3528105059Scognet
3529111158Scognet	device_id = pci_get_devid(dev);
3530105059Scognet	/*
3531105059Scognet	 * These cards do not allow memory mapped accesses
3532105059Scognet	 */
3533111158Scognet	if ((pACB = trm_init((u_int16_t) unit,
3534111158Scognet    	    dev)) == NULL) {
3535111158Scognet		printf("trm%d: trm_init error!\n",unit);
3536105059Scognet		return (ENXIO);
3537111158Scognet	}
3538105059Scognet	/* After setting up the adapter, map our interrupt */
3539105059Scognet	/*
3540105059Scognet	 * Now let the CAM generic SCSI layer find the SCSI devices on the bus
3541105059Scognet	 * start queue to reset to the idle loop.
3542105059Scognet	 * Create device queue of SIM(s)
3543105059Scognet	 * (MAX_START_JOB - 1) : max_sim_transactions
3544105059Scognet	 */
3545127135Snjl	pACB->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
3546127135Snjl	    RF_SHAREABLE | RF_ACTIVE);
3547107928Scognet    	if (pACB->irq == NULL ||
3548111158Scognet	    bus_setup_intr(dev, pACB->irq,
3549166901Spiso	    INTR_TYPE_CAM, NULL, trm_Interrupt, pACB, &pACB->ih)) {
3550105059Scognet		printf("trm%d: register Interrupt handler error!\n", unit);
3551107928Scognet		goto bad;
3552105059Scognet	}
3553111158Scognet	device_Q = cam_simq_alloc(TRM_MAX_START_JOB);
3554105059Scognet	if (device_Q == NULL){
3555105059Scognet		printf("trm%d: device_Q == NULL !\n",unit);
3556107928Scognet		goto bad;
3557105059Scognet	}
3558105059Scognet	/*
3559105059Scognet	 * Now tell the generic SCSI layer
3560105059Scognet	 * about our bus.
3561105059Scognet	 * If this is the xpt layer creating a sim, then it's OK
3562105059Scognet	 * to wait for an allocation.
3563105059Scognet	 * XXX Should we pass in a flag to indicate that wait is OK?
3564105059Scognet	 *
3565105059Scognet	 *                    SIM allocation
3566105059Scognet	 *
3567105059Scognet	 *                 SCSI Interface Modules
3568105059Scognet	 * The sim driver creates a sim for each controller.  The sim device
3569105059Scognet	 * queue is separately created in order to allow resource sharing betwee
3570105059Scognet	 * sims.  For instance, a driver may create one sim for each channel of
3571105059Scognet	 * a multi-channel controller and use the same queue for each channel.
3572105059Scognet	 * In this way, the queue resources are shared across all the channels
3573105059Scognet	 * of the multi-channel controller.
3574105059Scognet	 * trm_action     : sim_action_func
3575105059Scognet	 * trm_poll       : sim_poll_func
3576111119Simp	 * "trm"        : sim_name ,if sim_name =  "xpt" ..M_DEVBUF,M_WAITOK
3577105059Scognet	 * pACB         : *softc    if sim_name <> "xpt" ..M_DEVBUF,M_NOWAIT
3578105059Scognet	 * pACB->unit   : unit
3579105059Scognet	 * 1            : max_dev_transactions
3580105059Scognet	 * MAX_TAGS     : max_tagged_dev_transactions
3581105059Scognet	 *
3582105059Scognet	 *  *******Construct our first channel SIM entry
3583105059Scognet	 */
3584105059Scognet	pACB->psim = cam_sim_alloc(trm_action,
3585105059Scognet	    trm_poll,
3586105059Scognet	    "trm",
3587105059Scognet	    pACB,
3588105059Scognet	    unit,
3589168752Sscottl	    &Giant,
3590105059Scognet	    1,
3591111158Scognet	    TRM_MAX_TAGS_CMD_QUEUE,
3592105059Scognet	    device_Q);
3593105059Scognet	if (pACB->psim == NULL) {
3594105059Scognet		printf("trm%d: SIM allocate fault !\n",unit);
3595105059Scognet		cam_simq_free(device_Q);  /* SIM allocate fault*/
3596107928Scognet		goto bad;
3597105059Scognet	}
3598170872Sscottl	if (xpt_bus_register(pACB->psim, dev, 0) != CAM_SUCCESS)  {
3599105059Scognet		printf("trm%d: xpt_bus_register fault !\n",unit);
3600107928Scognet		goto bad;
3601105059Scognet	}
3602105059Scognet	if (xpt_create_path(&pACB->ppath,
3603105059Scognet	      NULL,
3604105059Scognet	      cam_sim_path(pACB->psim),
3605105059Scognet	      CAM_TARGET_WILDCARD,
3606105059Scognet	      CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
3607105059Scognet		printf("trm%d: xpt_create_path fault !\n",unit);
3608105059Scognet		xpt_bus_deregister(cam_sim_path(pACB->psim));
3609107928Scognet		goto bad;
3610105059Scognet	}
3611105059Scognet	return (0);
3612107928Scognetbad:
3613107928Scognet	if (pACB->iores)
3614119690Sjhb		bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0),
3615107928Scognet		    pACB->iores);
3616126725Scognet	if (pACB->sg_dmat) {
3617126725Scognet		trm_destroySRB(pACB);
3618126725Scognet		bus_dma_tag_destroy(pACB->sg_dmat);
3619126725Scognet	}
3620126725Scognet
3621111158Scognet	if (pACB->srb_dmamap) {
3622111158Scognet		bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap);
3623111158Scognet		bus_dmamem_free(pACB->srb_dmat, pACB->pFreeSRB,
3624111158Scognet		    pACB->srb_dmamap);
3625111158Scognet		bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap);
3626111158Scognet	}
3627111158Scognet	if (pACB->srb_dmat)
3628111158Scognet		bus_dma_tag_destroy(pACB->srb_dmat);
3629111158Scognet	if (pACB->sense_dmamap) {
3630111158Scognet	  	  bus_dmamap_unload(pACB->sense_dmat, pACB->sense_dmamap);
3631111158Scognet		  bus_dmamem_free(pACB->sense_dmat, pACB->sense_buffers,
3632111158Scognet		      pACB->sense_dmamap);
3633111158Scognet		  bus_dmamap_destroy(pACB->sense_dmat, pACB->sense_dmamap);
3634111158Scognet	}
3635111158Scognet	if (pACB->sense_dmat)
3636111158Scognet		bus_dma_tag_destroy(pACB->sense_dmat);
3637107928Scognet	if (pACB->buffer_dmat)
3638107928Scognet		bus_dma_tag_destroy(pACB->buffer_dmat);
3639107928Scognet	if (pACB->ih)
3640111158Scognet		bus_teardown_intr(dev, pACB->irq, pACB->ih);
3641107928Scognet	if (pACB->irq)
3642111158Scognet		bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irq);
3643107928Scognet	if (pACB->psim)
3644107928Scognet		cam_sim_free(pACB->psim, TRUE);
3645107928Scognet
3646107928Scognet	return (ENXIO);
3647107928Scognet
3648105059Scognet}
3649105059Scognet
3650105059Scognet/*
3651105059Scognet*                  pci_device
3652105059Scognet*         trm_probe (device_t tag, pcidi_t type)
3653105059Scognet*
3654105059Scognet*/
3655105059Scognetstatic int
3656111158Scognettrm_probe(device_t dev)
3657105059Scognet{
3658111158Scognet  	switch (pci_get_devid(dev)) {
3659111158Scognet	case PCI_DEVICEID_TRMS1040:
3660111158Scognet		device_set_desc(dev,
3661105059Scognet		    "Tekram DC395U/UW/F DC315/U Fast20 Wide SCSI Adapter");
3662142880Simp		return (BUS_PROBE_DEFAULT);
3663111158Scognet	case PCI_DEVICEID_TRMS2080:
3664111158Scognet		device_set_desc(dev,
3665111158Scognet		    "Tekram DC395U2D/U2W Fast40 Wide SCSI Adapter");
3666142880Simp		return (BUS_PROBE_DEFAULT);
3667111158Scognet	default:
3668105059Scognet		return (ENXIO);
3669111158Scognet	}
3670105059Scognet}
3671105059Scognet
3672105059Scognetstatic int
3673107928Scognettrm_detach(device_t dev)
3674105059Scognet{
3675107928Scognet	PACB pACB = device_get_softc(dev);
3676107928Scognet
3677119690Sjhb	bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), pACB->iores);
3678126725Scognet	trm_destroySRB(pACB);
3679126725Scognet	bus_dma_tag_destroy(pACB->sg_dmat);
3680111158Scognet	bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap);
3681111158Scognet	bus_dmamem_free(pACB->srb_dmat, pACB->pFreeSRB,
3682111158Scognet	    pACB->srb_dmamap);
3683111158Scognet	bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap);
3684111158Scognet	bus_dma_tag_destroy(pACB->srb_dmat);
3685111158Scognet	bus_dmamap_unload(pACB->sense_dmat, pACB->sense_dmamap);
3686111158Scognet	bus_dmamem_free(pACB->sense_dmat, pACB->sense_buffers,
3687111158Scognet	    pACB->sense_dmamap);
3688111158Scognet	bus_dmamap_destroy(pACB->sense_dmat, pACB->sense_dmamap);
3689111158Scognet	bus_dma_tag_destroy(pACB->sense_dmat);
3690111158Scognet	bus_dma_tag_destroy(pACB->buffer_dmat);
3691107928Scognet	bus_teardown_intr(dev, pACB->irq, pACB->ih);
3692107928Scognet	bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irq);
3693105059Scognet	xpt_async(AC_LOST_DEVICE, pACB->ppath, NULL);
3694105059Scognet	xpt_free_path(pACB->ppath);
3695105059Scognet	xpt_bus_deregister(cam_sim_path(pACB->psim));
3696105059Scognet	cam_sim_free(pACB->psim, TRUE);
3697105059Scognet	return (0);
3698105059Scognet}
3699105059Scognetstatic device_method_t trm_methods[] = {
3700105059Scognet	/* Device interface */
3701105059Scognet	DEVMETHOD(device_probe,		trm_probe),
3702105059Scognet	DEVMETHOD(device_attach,	trm_attach),
3703105059Scognet	DEVMETHOD(device_detach,	trm_detach),
3704105059Scognet	{ 0, 0 }
3705105059Scognet};
3706105059Scognet
3707105059Scognetstatic driver_t trm_driver = {
3708105059Scognet	"trm", trm_methods, sizeof(struct _ACB)
3709105059Scognet};
3710105059Scognet
3711105059Scognetstatic devclass_t trm_devclass;
3712105059ScognetDRIVER_MODULE(trm, pci, trm_driver, trm_devclass, 0, 0);
3713165102SmjacobMODULE_DEPEND(trm, pci, 1, 1, 1);
3714124318ScognetMODULE_DEPEND(trm, cam, 1, 1, 1);
3715