added mtd driver
[linux-2.4.git] / drivers / scsi / i60uscsi.c
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 /***************************************************************************/
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 /***************************************************************************/
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 /***************************************************************************/
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 /***************************************************************************/
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 /***************************************************************************/
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 /***************************************************************************/
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 /***************************************************************************/
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 /***************************************************************************/
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 /***************************************************************************/
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 /***************************************************************************/
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 ************************************************************************/
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 *************************************************************************/
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 **************************************************************************/
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 /***************************************************************************/
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 /***************************************************************************/
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 /***************************************************************************/
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 /***************************************************************************/
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 *****************************************************************************/
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 *****************************************************************************/
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 /***************************************************************************/
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
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 /***************************************************************************/
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 *****************************************************************************/
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 *****************************************************************************/
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 *****************************************************************************/
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 *****************************************************************************/
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 *****************************************************************************/
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 ***********************************************************************/
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() */