1 /**************************************************************************
2  * Initio A100 device driver for Linux.
3  *
4  * Copyright (c) 1994-1998 Initio Corporation
5  * All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; see the file COPYING.  If not, write to
19  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * --------------------------------------------------------------------------
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions, and the following disclaimer,
28  *    without modification, immediately at the beginning of the file.
29  * 2. Redistributions in binary form must reproduce the above copyright
30  *    notice, this list of conditions and the following disclaimer in the
31  *    documentation and/or other materials provided with the distribution.
32  * 3. The name of the author may not be used to endorse or promote products
33  *    derived from this software without specific prior written permission.
34  *
35  * Where this Software is combined with software released under the terms of
36  * the GNU General Public License ("GPL") and the terms of the GPL would require the
37  * combined work to also be released under the terms of the GPL, the terms
38  * and conditions of this License will apply in addition to those of the
39  * GPL with the exception of any terms or conditions of this License that
40  * conflict with, or are expressly prohibited by, the GPL.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
43  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
46  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE.
53  *
54  *************************************************************************
55  *
56  * module: i60uscsi.c
57  * DESCRIPTION:
58  * 	This is the Linux low-level SCSI driver for Initio INIA100 SCSI host
59  * adapters
60  *
61  * 07/02/98 hl	- v.91n Initial drivers.
62  * 09/14/98 hl - v1.01 Support new Kernel.
63  * 09/22/98 hl - v1.01a Support reset.
64  * 09/24/98 hl - v1.01b Fixed reset.
65  * 10/05/98 hl - v1.02 split the source code and release.
66  * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up
67  * 01/31/99 bv - v1.02b Use mdelay instead of waitForPause
68  * 08/08/99 bv - v1.02c Use waitForPause again.
69  **************************************************************************/
70 
71 #include <linux/version.h>
72 #include <linux/sched.h>
73 #include <asm/io.h>
74 #include "i60uscsi.h"
75 
76 #define JIFFIES_TO_MS(t) ((t) * 1000 / HZ)
77 #define MS_TO_JIFFIES(j) ((j * HZ) / 1000)
78 
79 /* ---- INTERNAL FUNCTIONS ---- */
80 static UCHAR waitChipReady(ORC_HCS * hcsp);
81 static UCHAR waitFWReady(ORC_HCS * hcsp);
82 static UCHAR waitFWReady(ORC_HCS * hcsp);
83 static UCHAR waitSCSIRSTdone(ORC_HCS * hcsp);
84 static UCHAR waitHDOoff(ORC_HCS * hcsp);
85 static UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData);
86 static unsigned short get_FW_version(ORC_HCS * hcsp);
87 static UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value);
88 static UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn);
89 static int se2_rd_all(ORC_HCS * hcsp);
90 static void se2_update_all(ORC_HCS * hcsp);	/* setup default pattern        */
91 static void read_eeprom(ORC_HCS * hcsp);
92 static UCHAR load_FW(ORC_HCS * hcsp);
93 static void setup_SCBs(ORC_HCS * hcsp);
94 static void initAFlag(ORC_HCS * hcsp);
95 ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
96 
97 /* ---- EXTERNAL FUNCTIONS ---- */
98 extern void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
99 
100 /* ---- INTERNAL VARIABLES ---- */
101 ORC_HCS orc_hcs[MAX_SUPPORTED_ADAPTERS];
102 static INIA100_ADPT_STRUCT inia100_adpt[MAX_SUPPORTED_ADAPTERS];
103 /* set by inia100_setup according to the command line */
104 int orc_num_scb;
105 
106 NVRAM nvram, *nvramp = &nvram;
107 static UCHAR dftNvRam[64] =
108 {
109 /*----------header -------------*/
110 	0x01,			/* 0x00: Sub System Vendor ID 0 */
111 	0x11,			/* 0x01: Sub System Vendor ID 1 */
112 	0x60,			/* 0x02: Sub System ID 0        */
113 	0x10,			/* 0x03: Sub System ID 1        */
114 	0x00,			/* 0x04: SubClass               */
115 	0x01,			/* 0x05: Vendor ID 0            */
116 	0x11,			/* 0x06: Vendor ID 1            */
117 	0x60,			/* 0x07: Device ID 0            */
118 	0x10,			/* 0x08: Device ID 1            */
119 	0x00,			/* 0x09: Reserved               */
120 	0x00,			/* 0x0A: Reserved               */
121 	0x01,			/* 0x0B: Revision of Data Structure     */
122 				/* -- Host Adapter Structure --- */
123 	0x01,			/* 0x0C: Number Of SCSI Channel */
124 	0x01,			/* 0x0D: BIOS Configuration 1   */
125 	0x00,			/* 0x0E: BIOS Configuration 2   */
126 	0x00,			/* 0x0F: BIOS Configuration 3   */
127 				/* --- SCSI Channel 0 Configuration --- */
128 	0x07,			/* 0x10: H/A ID                 */
129 	0x83,			/* 0x11: Channel Configuration  */
130 	0x20,			/* 0x12: MAX TAG per target     */
131 	0x0A,			/* 0x13: SCSI Reset Recovering time     */
132 	0x00,			/* 0x14: Channel Configuration4 */
133 	0x00,			/* 0x15: Channel Configuration5 */
134 				/* SCSI Channel 0 Target Configuration  */
135 				/* 0x16-0x25                    */
136 	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
137 	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
138 				/* --- SCSI Channel 1 Configuration --- */
139 	0x07,			/* 0x26: H/A ID                 */
140 	0x83,			/* 0x27: Channel Configuration  */
141 	0x20,			/* 0x28: MAX TAG per target     */
142 	0x0A,			/* 0x29: SCSI Reset Recovering time     */
143 	0x00,			/* 0x2A: Channel Configuration4 */
144 	0x00,			/* 0x2B: Channel Configuration5 */
145 				/* SCSI Channel 1 Target Configuration  */
146 				/* 0x2C-0x3B                    */
147 	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
148 	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
149 	0x00,			/* 0x3C: Reserved               */
150 	0x00,			/* 0x3D: Reserved               */
151 	0x00,			/* 0x3E: Reserved               */
152 	0x00			/* 0x3F: Checksum               */
153 };
154 
155 
156 /***************************************************************************/
waitForPause(unsigned amount)157 static void waitForPause(unsigned amount)
158 {
159 	ULONG the_time = jiffies + MS_TO_JIFFIES(amount);
160 	while (time_before_eq(jiffies, the_time))
161 		cpu_relax();
162 }
163 
164 /***************************************************************************/
waitChipReady(ORC_HCS * hcsp)165 UCHAR waitChipReady(ORC_HCS * hcsp)
166 {
167 	int i;
168 
169 	for (i = 0; i < 10; i++) {	/* Wait 1 second for report timeout     */
170 		if (ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HOSTSTOP)	/* Wait HOSTSTOP set */
171 			return (TRUE);
172 		waitForPause(100);	/* wait 100ms before try again  */
173 	}
174 	return (FALSE);
175 }
176 
177 /***************************************************************************/
waitFWReady(ORC_HCS * hcsp)178 UCHAR waitFWReady(ORC_HCS * hcsp)
179 {
180 	int i;
181 
182 	for (i = 0; i < 10; i++) {	/* Wait 1 second for report timeout     */
183 		if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY)		/* Wait READY set */
184 			return (TRUE);
185 		waitForPause(100);	/* wait 100ms before try again  */
186 	}
187 	return (FALSE);
188 }
189 
190 /***************************************************************************/
waitSCSIRSTdone(ORC_HCS * hcsp)191 UCHAR waitSCSIRSTdone(ORC_HCS * hcsp)
192 {
193 	int i;
194 
195 	for (i = 0; i < 10; i++) {	/* Wait 1 second for report timeout     */
196 		if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & SCSIRST))	/* Wait SCSIRST done */
197 			return (TRUE);
198 		waitForPause(100);	/* wait 100ms before try again  */
199 	}
200 	return (FALSE);
201 }
202 
203 /***************************************************************************/
waitHDOoff(ORC_HCS * hcsp)204 UCHAR waitHDOoff(ORC_HCS * hcsp)
205 {
206 	int i;
207 
208 	for (i = 0; i < 10; i++) {	/* Wait 1 second for report timeout     */
209 		if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HDO))		/* Wait HDO off */
210 			return (TRUE);
211 		waitForPause(100);	/* wait 100ms before try again  */
212 	}
213 	return (FALSE);
214 }
215 
216 /***************************************************************************/
waitHDIset(ORC_HCS * hcsp,UCHAR * pData)217 UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData)
218 {
219 	int i;
220 
221 	for (i = 0; i < 10; i++) {	/* Wait 1 second for report timeout     */
222 		if ((*pData = ORC_RD(hcsp->HCS_Base, ORC_HSTUS)) & HDI)
223 			return (TRUE);	/* Wait HDI set */
224 		waitForPause(100);	/* wait 100ms before try again  */
225 	}
226 	return (FALSE);
227 }
228 
229 /***************************************************************************/
get_FW_version(ORC_HCS * hcsp)230 unsigned short get_FW_version(ORC_HCS * hcsp)
231 {
232 	UCHAR bData;
233 	union {
234 		unsigned short sVersion;
235 		unsigned char cVersion[2];
236 	} Version;
237 
238 	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_VERSION);
239 	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
240 	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
241 		return (FALSE);
242 
243 	if (waitHDIset(hcsp, &bData) == FALSE)	/* Wait HDI set   */
244 		return (FALSE);
245 	Version.cVersion[0] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
246 	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI            */
247 
248 	if (waitHDIset(hcsp, &bData) == FALSE)	/* Wait HDI set   */
249 		return (FALSE);
250 	Version.cVersion[1] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
251 	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI            */
252 
253 	return (Version.sVersion);
254 }
255 
256 /***************************************************************************/
set_NVRAM(ORC_HCS * hcsp,unsigned char address,unsigned char value)257 UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value)
258 {
259 	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_SET_NVM);	/* Write command */
260 	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
261 	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
262 		return (FALSE);
263 
264 	ORC_WR(hcsp->HCS_Base + ORC_HDATA, address);	/* Write address */
265 	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
266 	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
267 		return (FALSE);
268 
269 	ORC_WR(hcsp->HCS_Base + ORC_HDATA, value);	/* Write value  */
270 	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
271 	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
272 		return (FALSE);
273 
274 	return (TRUE);
275 }
276 
277 /***************************************************************************/
get_NVRAM(ORC_HCS * hcsp,unsigned char address,unsigned char * pDataIn)278 UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn)
279 {
280 	unsigned char bData;
281 
282 	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_GET_NVM);	/* Write command */
283 	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
284 	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
285 		return (FALSE);
286 
287 	ORC_WR(hcsp->HCS_Base + ORC_HDATA, address);	/* Write address */
288 	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
289 	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
290 		return (FALSE);
291 
292 	if (waitHDIset(hcsp, &bData) == FALSE)	/* Wait HDI set   */
293 		return (FALSE);
294 	*pDataIn = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
295 	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI    */
296 
297 	return (TRUE);
298 }
299 
300 /***************************************************************************/
orc_exec_scb(ORC_HCS * hcsp,ORC_SCB * scbp)301 void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
302 {
303 	scbp->SCB_Status = SCB_POST;
304 	ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx);
305 	return;
306 }
307 
308 
309 /***********************************************************************
310  Read SCSI H/A configuration parameters from serial EEPROM
311 ************************************************************************/
se2_rd_all(ORC_HCS * hcsp)312 int se2_rd_all(ORC_HCS * hcsp)
313 {
314 	int i;
315 	UCHAR *np, chksum = 0;
316 
317 	np = (UCHAR *) nvramp;
318 	for (i = 0; i < 64; i++, np++) {	/* <01> */
319 		if (get_NVRAM(hcsp, (unsigned char) i, np) == FALSE)
320 			return -1;
321 //      *np++ = get_NVRAM(hcsp, (unsigned char ) i);
322 	}
323 
324 /*------ Is ckecksum ok ? ------*/
325 	np = (UCHAR *) nvramp;
326 	for (i = 0; i < 63; i++)
327 		chksum += *np++;
328 
329 	if (nvramp->CheckSum != (UCHAR) chksum)
330 		return -1;
331 	return 1;
332 }
333 
334 /************************************************************************
335  Update SCSI H/A configuration parameters from serial EEPROM
336 *************************************************************************/
se2_update_all(ORC_HCS * hcsp)337 void se2_update_all(ORC_HCS * hcsp)
338 {				/* setup default pattern  */
339 	int i;
340 	UCHAR *np, *np1, chksum = 0;
341 
342 	/* Calculate checksum first   */
343 	np = (UCHAR *) dftNvRam;
344 	for (i = 0; i < 63; i++)
345 		chksum += *np++;
346 	*np = chksum;
347 
348 	np = (UCHAR *) dftNvRam;
349 	np1 = (UCHAR *) nvramp;
350 	for (i = 0; i < 64; i++, np++, np1++) {
351 		if (*np != *np1) {
352 			set_NVRAM(hcsp, (unsigned char) i, *np);
353 		}
354 	}
355 	return;
356 }
357 
358 /*************************************************************************
359  Function name  : read_eeprom
360 **************************************************************************/
read_eeprom(ORC_HCS * hcsp)361 void read_eeprom(ORC_HCS * hcsp)
362 {
363 	if (se2_rd_all(hcsp) != 1) {
364 		se2_update_all(hcsp);	/* setup default pattern        */
365 		se2_rd_all(hcsp);	/* load again                   */
366 	}
367 }
368 
369 
370 /***************************************************************************/
load_FW(ORC_HCS * hcsp)371 UCHAR load_FW(ORC_HCS * hcsp)
372 {
373 	U32 dData;
374 	USHORT wBIOSAddress;
375 	USHORT i;
376 	UCHAR *pData, bData;
377 
378 
379 	bData = ORC_RD(hcsp->HCS_Base, ORC_GCFG);
380 	ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData | EEPRG);	/* Enable EEPROM programming */
381 	ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, 0x00);
382 	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x00);
383 	if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0x55) {
384 		ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/* Disable EEPROM programming */
385 		return (FALSE);
386 	}
387 	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x01);
388 	if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0xAA) {
389 		ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/* Disable EEPROM programming */
390 		return (FALSE);
391 	}
392 	ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);	/* Enable SRAM programming */
393 	pData = (UCHAR *) & dData;
394 	dData = 0;		/* Initial FW address to 0 */
395 	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x10);
396 	*pData = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);		/* Read from BIOS */
397 	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x11);
398 	*(pData + 1) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
399 	ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x12);
400 	*(pData + 2) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
401 	ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, *(pData + 2));
402 	ORC_WRLONG(hcsp->HCS_Base + ORC_FWBASEADR, dData);	/* Write FW address */
403 
404 	wBIOSAddress = (USHORT) dData;	/* FW code locate at BIOS address + ? */
405 	for (i = 0, pData = (UCHAR *) & dData;	/* Download the code    */
406 	     i < 0x1000;	/* Firmware code size = 4K      */
407 	     i++, wBIOSAddress++) {
408 		ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
409 		*pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
410 		if ((i % 4) == 3) {
411 			ORC_WRLONG(hcsp->HCS_Base + ORC_RISCRAM, dData);	/* Write every 4 bytes */
412 			pData = (UCHAR *) & dData;
413 		}
414 	}
415 
416 	ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);	/* Reset program count 0 */
417 	wBIOSAddress -= 0x1000;	/* Reset the BIOS adddress      */
418 	for (i = 0, pData = (UCHAR *) & dData;	/* Check the code       */
419 	     i < 0x1000;	/* Firmware code size = 4K      */
420 	     i++, wBIOSAddress++) {
421 		ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
422 		*pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);	/* Read from BIOS */
423 		if ((i % 4) == 3) {
424 			if (ORC_RDLONG(hcsp->HCS_Base, ORC_RISCRAM) != dData) {
425 				ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);	/* Reset program to 0 */
426 				ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/*Disable EEPROM programming */
427 				return (FALSE);
428 			}
429 			pData = (UCHAR *) & dData;
430 		}
431 	}
432 	ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);	/* Reset program to 0   */
433 	ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);	/* Disable EEPROM programming */
434 	return (TRUE);
435 }
436 
437 /***************************************************************************/
setup_SCBs(ORC_HCS * hcsp)438 void setup_SCBs(ORC_HCS * hcsp)
439 {
440 	ORC_SCB *pVirScb;
441 	int i;
442 	UCHAR j;
443 	ESCB *pVirEscb;
444 	PVOID pPhysEscb;
445 	PVOID tPhysEscb;
446 
447 	j = 0;
448 	pVirScb = NULL;
449 	tPhysEscb = (PVOID) NULL;
450 	pPhysEscb = (PVOID) NULL;
451 	/* Setup SCB HCS_Base and SCB Size registers */
452 	ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, orc_num_scb);	/* Total number of SCBs */
453 	/* SCB HCS_Base address 0      */
454 	ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray);
455 	/* SCB HCS_Base address 1      */
456 	ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE1, hcsp->HCS_physScbArray);
457 
458 	/* setup scatter list address with one buffer */
459 	pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
460 	pVirEscb = (ESCB *) hcsp->HCS_virEscbArray;
461 
462 	for (i = 0; i < orc_num_scb; i++) {
463 		pPhysEscb = (PVOID) (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i));
464 		pVirScb->SCB_SGPAddr = (U32) pPhysEscb;
465 		pVirScb->SCB_SensePAddr = (U32) pPhysEscb;
466 		pVirScb->SCB_EScb = pVirEscb;
467 		pVirScb->SCB_ScbIdx = i;
468 		pVirScb++;
469 		pVirEscb++;
470 	}
471 
472 	return;
473 }
474 
475 /***************************************************************************/
initAFlag(ORC_HCS * hcsp)476 static void initAFlag(ORC_HCS * hcsp)
477 {
478 	UCHAR i, j;
479 
480 	for (i = 0; i < MAX_CHANNELS; i++) {
481 		for (j = 0; j < 8; j++) {
482 			hcsp->BitAllocFlag[i][j] = 0xffffffff;
483 		}
484 	}
485 }
486 
487 /***************************************************************************/
init_orchid(ORC_HCS * hcsp)488 int init_orchid(ORC_HCS * hcsp)
489 {
490 	UBYTE *readBytep;
491 	USHORT revision;
492 	UCHAR i;
493 
494 	initAFlag(hcsp);
495 	ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFF);	/* Disable all interrupt        */
496 	if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) {	/* Orchid is ready              */
497 		revision = get_FW_version(hcsp);
498 		if (revision == 0xFFFF) {
499 			ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);	/* Reset Host Adapter   */
500 			if (waitChipReady(hcsp) == FALSE)
501 				return (-1);
502 			load_FW(hcsp);	/* Download FW                  */
503 			setup_SCBs(hcsp);	/* Setup SCB HCS_Base and SCB Size registers */
504 			ORC_WR(hcsp->HCS_Base + ORC_HCTRL, 0);	/* clear HOSTSTOP       */
505 			if (waitFWReady(hcsp) == FALSE)
506 				return (-1);
507 			/* Wait for firmware ready     */
508 		} else {
509 			setup_SCBs(hcsp);	/* Setup SCB HCS_Base and SCB Size registers */
510 		}
511 	} else {		/* Orchid is not Ready          */
512 		ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);	/* Reset Host Adapter   */
513 		if (waitChipReady(hcsp) == FALSE)
514 			return (-1);
515 		load_FW(hcsp);	/* Download FW                  */
516 		setup_SCBs(hcsp);	/* Setup SCB HCS_Base and SCB Size registers */
517 		ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);	/* Do Hardware Reset &  */
518 
519 		/*     clear HOSTSTOP  */
520 		if (waitFWReady(hcsp) == FALSE)		/* Wait for firmware ready      */
521 			return (-1);
522 	}
523 
524 /*------------- get serial EEProm settting -------*/
525 
526 	read_eeprom(hcsp);
527 
528 	if (nvramp->Revision != 1)
529 		return (-1);
530 
531 	hcsp->HCS_SCSI_ID = nvramp->SCSI0Id;
532 	hcsp->HCS_BIOS = nvramp->BIOSConfig1;
533 	hcsp->HCS_MaxTar = MAX_TARGETS;
534 	readBytep = (UCHAR *) & (nvramp->Target00Config);
535 	for (i = 0; i < 16; readBytep++, i++) {
536 		hcsp->TargetFlag[i] = *readBytep;
537 		hcsp->MaximumTags[i] = orc_num_scb;
538 	}			/* for                          */
539 
540 	if (nvramp->SCSI0Config & NCC_BUSRESET) {	/* Reset SCSI bus               */
541 		hcsp->HCS_Flags |= HCF_SCSI_RESET;
542 	}
543 	ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFB);	/* enable RP FIFO interrupt     */
544 	return (0);
545 }
546 
547 /*****************************************************************************
548  Function name  : orc_reset_scsi_bus
549  Description    : Reset registers, reset a hanging bus and
550                   kill active and disconnected commands for target w/o soft reset
551  Input          : pHCB  -       Pointer to host adapter structure
552  Output         : None.
553  Return         : pSRB  -       Pointer to SCSI request block.
554 *****************************************************************************/
orc_reset_scsi_bus(ORC_HCS * pHCB)555 int orc_reset_scsi_bus(ORC_HCS * pHCB)
556 {				/* I need Host Control Block Information */
557 	ULONG flags;
558 
559 	spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
560 
561 	initAFlag(pHCB);
562 	/* reset scsi bus */
563 	ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST);
564 	if (waitSCSIRSTdone(pHCB) == FALSE) {
565 		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
566 		return (SCSI_RESET_ERROR);
567 	} else {
568 		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
569 		return (SCSI_RESET_SUCCESS);
570 	}
571 }
572 
573 /*****************************************************************************
574  Function name  : orc_device_reset
575  Description    : Reset registers, reset a hanging bus and
576                   kill active and disconnected commands for target w/o soft reset
577  Input          : pHCB  -       Pointer to host adapter structure
578  Output         : None.
579  Return         : pSRB  -       Pointer to SCSI request block.
580 *****************************************************************************/
orc_device_reset(ORC_HCS * pHCB,ULONG SCpnt,unsigned int target,unsigned int ResetFlags)581 int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned int ResetFlags)
582 {				/* I need Host Control Block Information */
583 	ORC_SCB *pScb;
584 	ESCB *pVirEscb;
585 	ORC_SCB *pVirScb;
586 	UCHAR i;
587 	ULONG flags;
588 
589 	spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
590 	pScb = (ORC_SCB *) NULL;
591 	pVirEscb = (ESCB *) NULL;
592 
593 	/* setup scatter list address with one buffer */
594 	pVirScb = (ORC_SCB *) pHCB->HCS_virScbArray;
595 
596 	initAFlag(pHCB);
597 	/* device reset */
598 	for (i = 0; i < orc_num_scb; i++) {
599 		pVirEscb = pVirScb->SCB_EScb;
600 		if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt))
601 			break;
602 		pVirScb++;
603 	}
604 
605 	if (i == orc_num_scb) {
606 		printk("Unable to Reset - No SCB Found\n");
607 		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
608 		return (SCSI_RESET_NOT_RUNNING);
609 	}
610 	if ((pScb = orc_alloc_scb(pHCB)) == NULL) {
611 		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
612 		return (SCSI_RESET_NOT_RUNNING);
613 	}
614 	pScb->SCB_Opcode = ORC_BUSDEVRST;
615 	pScb->SCB_Target = target;
616 	pScb->SCB_HaStat = 0;
617 	pScb->SCB_TaStat = 0;
618 	pScb->SCB_Status = 0x0;
619 	pScb->SCB_Link = 0xFF;
620 	pScb->SCB_Reserved0 = 0;
621 	pScb->SCB_Reserved1 = 0;
622 	pScb->SCB_XferLen = 0;
623 	pScb->SCB_SGLen = 0;
624 
625 	pVirEscb->SCB_Srb = 0;
626 	if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
627 		pVirEscb->SCB_Srb = (unsigned char *) SCpnt;
628 	}
629 	orc_exec_scb(pHCB, pScb);	/* Start execute SCB            */
630 	spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
631 	return SCSI_RESET_PENDING;
632 }
633 
634 
635 /***************************************************************************/
__orc_alloc_scb(ORC_HCS * hcsp)636 ORC_SCB *__orc_alloc_scb(ORC_HCS * hcsp)
637 {
638 	ORC_SCB *pTmpScb;
639 	UCHAR Ch;
640 	ULONG idx;
641 	UCHAR index;
642 	UCHAR i;
643 
644 	Ch = hcsp->HCS_Index;
645 	for (i = 0; i < 8; i++) {
646 		for (index = 0; index < 32; index++) {
647 			if ((hcsp->BitAllocFlag[Ch][i] >> index) & 0x01) {
648 				hcsp->BitAllocFlag[Ch][i] &= ~(1 << index);
649 				break;
650 			}
651 		}
652 		idx = index + 32 * i;
653 		pTmpScb = (PVOID) ((ULONG) hcsp->HCS_virScbArray + (idx * sizeof(ORC_SCB)));
654 		return (pTmpScb);
655 	}
656 	return (NULL);
657 }
658 
orc_alloc_scb(ORC_HCS * hcsp)659 ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp)
660 {
661 	ORC_SCB *pTmpScb;
662 	ULONG flags;
663 
664 	spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
665 	pTmpScb = __orc_alloc_scb(hcsp);
666 	spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
667 	return (pTmpScb);
668 }
669 
670 
671 /***************************************************************************/
orc_release_scb(ORC_HCS * hcsp,ORC_SCB * scbp)672 void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
673 {
674 	ULONG flags;
675 	UCHAR Index;
676 	UCHAR i;
677 	UCHAR Ch;
678 
679 	spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
680 	Ch = hcsp->HCS_Index;
681 	Index = scbp->SCB_ScbIdx;
682 	i = Index / 32;
683 	Index %= 32;
684 	hcsp->BitAllocFlag[Ch][i] |= (1 << Index);
685 	spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
686 }
687 
688 
689 /*****************************************************************************
690  Function name	: Addinia100_into_Adapter_table
691  Description	: This function will scan PCI bus to get all Orchid card
692  Input		: None.
693  Output		: None.
694  Return		: SUCCESSFUL	- Successful scan
695  ohterwise	- No drives founded
696 *****************************************************************************/
Addinia100_into_Adapter_table(WORD wBIOS,WORD wBASE,BYTE bInterrupt,BYTE bBus,BYTE bDevice)697 int Addinia100_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
698 				  BYTE bBus, BYTE bDevice)
699 {
700 	unsigned int i, j;
701 
702 	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
703 		if (inia100_adpt[i].ADPT_BIOS < wBIOS)
704 			continue;
705 		if (inia100_adpt[i].ADPT_BIOS == wBIOS) {
706 			if (inia100_adpt[i].ADPT_BASE == wBASE) {
707 				if (inia100_adpt[i].ADPT_Bus != 0xFF)
708 					return (FAILURE);
709 			} else if (inia100_adpt[i].ADPT_BASE < wBASE)
710 				continue;
711 		}
712 		for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
713 			inia100_adpt[j].ADPT_BASE = inia100_adpt[j - 1].ADPT_BASE;
714 			inia100_adpt[j].ADPT_INTR = inia100_adpt[j - 1].ADPT_INTR;
715 			inia100_adpt[j].ADPT_BIOS = inia100_adpt[j - 1].ADPT_BIOS;
716 			inia100_adpt[j].ADPT_Bus = inia100_adpt[j - 1].ADPT_Bus;
717 			inia100_adpt[j].ADPT_Device = inia100_adpt[j - 1].ADPT_Device;
718 		}
719 		inia100_adpt[i].ADPT_BASE = wBASE;
720 		inia100_adpt[i].ADPT_INTR = bInterrupt;
721 		inia100_adpt[i].ADPT_BIOS = wBIOS;
722 		inia100_adpt[i].ADPT_Bus = bBus;
723 		inia100_adpt[i].ADPT_Device = bDevice;
724 		return (SUCCESSFUL);
725 	}
726 	return (FAILURE);
727 }
728 
729 
730 /*****************************************************************************
731  Function name	: init_inia100Adapter_table
732  Description	: This function will scan PCI bus to get all Orchid card
733  Input		: None.
734  Output		: None.
735  Return		: SUCCESSFUL	- Successful scan
736  ohterwise	- No drives founded
737 *****************************************************************************/
init_inia100Adapter_table(void)738 void init_inia100Adapter_table(void)
739 {
740 	int i;
741 
742 	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {	/* Initialize adapter structure */
743 		inia100_adpt[i].ADPT_BIOS = 0xffff;
744 		inia100_adpt[i].ADPT_BASE = 0xffff;
745 		inia100_adpt[i].ADPT_INTR = 0xff;
746 		inia100_adpt[i].ADPT_Bus = 0xff;
747 		inia100_adpt[i].ADPT_Device = 0xff;
748 	}
749 }
750 
751 /*****************************************************************************
752  Function name  : get_orcPCIConfig
753  Description    :
754  Input          : pHCB  -       Pointer to host adapter structure
755  Output         : None.
756  Return         : pSRB  -       Pointer to SCSI request block.
757 *****************************************************************************/
get_orcPCIConfig(ORC_HCS * pCurHcb,int ch_idx)758 void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx)
759 {
760 	pCurHcb->HCS_Base = inia100_adpt[ch_idx].ADPT_BASE;	/* Supply base address  */
761 	pCurHcb->HCS_BIOS = inia100_adpt[ch_idx].ADPT_BIOS;	/* Supply BIOS address  */
762 	pCurHcb->HCS_Intr = inia100_adpt[ch_idx].ADPT_INTR;	/* Supply interrupt line */
763 	return;
764 }
765 
766 
767 /*****************************************************************************
768  Function name  : abort_SCB
769  Description    : Abort a queued command.
770 	                 (commands that are on the bus can't be aborted easily)
771  Input          : pHCB  -       Pointer to host adapter structure
772  Output         : None.
773  Return         : pSRB  -       Pointer to SCSI request block.
774 *****************************************************************************/
abort_SCB(ORC_HCS * hcsp,ORC_SCB * pScb)775 int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb)
776 {
777 	unsigned char bData, bStatus;
778 
779 	ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_ABORT_SCB);	/* Write command */
780 	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
781 	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
782 		return (FALSE);
783 
784 	ORC_WR(hcsp->HCS_Base + ORC_HDATA, pScb->SCB_ScbIdx);	/* Write address */
785 	ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
786 	if (waitHDOoff(hcsp) == FALSE)	/* Wait HDO off   */
787 		return (FALSE);
788 
789 	if (waitHDIset(hcsp, &bData) == FALSE)	/* Wait HDI set   */
790 		return (FALSE);
791 	bStatus = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
792 	ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);	/* Clear HDI    */
793 
794 	if (bStatus == 1)	/* 0 - Successfully               */
795 		return (FALSE);	/* 1 - Fail                     */
796 	return (TRUE);
797 }
798 
799 /*****************************************************************************
800  Function name  : inia100_abort
801  Description    : Abort a queued command.
802 	                 (commands that are on the bus can't be aborted easily)
803  Input          : pHCB  -       Pointer to host adapter structure
804  Output         : None.
805  Return         : pSRB  -       Pointer to SCSI request block.
806 *****************************************************************************/
orc_abort_srb(ORC_HCS * hcsp,ULONG SCpnt)807 int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt)
808 {
809 	ESCB *pVirEscb;
810 	ORC_SCB *pVirScb;
811 	UCHAR i;
812 	ULONG flags;
813 
814 	spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
815 
816 	pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
817 
818 	for (i = 0; i < orc_num_scb; i++, pVirScb++) {
819 		pVirEscb = pVirScb->SCB_EScb;
820 		if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt)) {
821 			if (pVirScb->SCB_TagMsg == 0) {
822 				spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
823 				return (SCSI_ABORT_BUSY);
824 			} else {
825 				if (abort_SCB(hcsp, pVirScb)) {
826 					pVirEscb->SCB_Srb = NULL;
827 					spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
828 					return (SCSI_ABORT_SUCCESS);
829 				} else {
830 					spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
831 					return (SCSI_ABORT_NOT_RUNNING);
832 				}
833 			}
834 		}
835 	}
836 	spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
837 	return (SCSI_ABORT_NOT_RUNNING);
838 }
839 
840 /***********************************************************************
841  Routine Description:
842 	  This is the interrupt service routine for the Orchid SCSI adapter.
843 	  It reads the interrupt register to determine if the adapter is indeed
844 	  the source of the interrupt and clears the interrupt at the device.
845  Arguments:
846 	  HwDeviceExtension - HBA miniport driver's adapter data storage
847  Return Value:
848 ***********************************************************************/
orc_interrupt(ORC_HCS * hcsp)849 void orc_interrupt(
850 			  ORC_HCS * hcsp
851 )
852 {
853 	BYTE bScbIdx;
854 	ORC_SCB *pScb;
855 
856 	if (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT) == 0) {
857 		return;		// (FALSE);
858 
859 	}
860 	do {
861 		bScbIdx = ORC_RD(hcsp->HCS_Base, ORC_RQUEUE);
862 
863 		pScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (ULONG) (sizeof(ORC_SCB) * bScbIdx));
864 		pScb->SCB_Status = 0x0;
865 
866 		inia100SCBPost((BYTE *) hcsp, (BYTE *) pScb);
867 	} while (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT));
868 	return;			//(TRUE);
869 
870 }				/* End of I1060Interrupt() */
871