ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.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  * 06/25/02 Doug Ledford <dledford@redhat.com> - v1.02d
70  *          - Remove limit on number of controllers
71  *          - Port to DMA mapping API
72  *          - Clean up interrupt handler registration
73  *          - Fix memory leaks
74  *          - Fix allocation of scsi host structs and private data
75  **************************************************************************/
76
77 #include <linux/module.h>
78 #include <asm/irq.h>
79 #include <linux/pci.h>
80 #include <linux/delay.h>
81 #include <asm/io.h>
82 #include <linux/blkdev.h>
83 #include "scsi.h"
84 #include "hosts.h"
85 #include "inia100.h"
86
87 #define JIFFIES_TO_MS(t) ((t) * 1000 / HZ)
88 #define MS_TO_JIFFIES(j) ((j * HZ) / 1000)
89
90 /* ---- INTERNAL FUNCTIONS ---- */
91 static UCHAR waitChipReady(ORC_HCS * hcsp);
92 static UCHAR waitFWReady(ORC_HCS * hcsp);
93 static UCHAR waitFWReady(ORC_HCS * hcsp);
94 static UCHAR waitSCSIRSTdone(ORC_HCS * hcsp);
95 static UCHAR waitHDOoff(ORC_HCS * hcsp);
96 static UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData);
97 static unsigned short get_FW_version(ORC_HCS * hcsp);
98 static UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value);
99 static UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn);
100 static int se2_rd_all(ORC_HCS * hcsp);
101 static void se2_update_all(ORC_HCS * hcsp);     /* setup default pattern        */
102 static void read_eeprom(ORC_HCS * hcsp);
103 static UCHAR load_FW(ORC_HCS * hcsp);
104 static void setup_SCBs(ORC_HCS * hcsp);
105 static void initAFlag(ORC_HCS * hcsp);
106 ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
107
108 /* ---- EXTERNAL FUNCTIONS ---- */
109 extern void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
110
111 NVRAM nvram, *nvramp = &nvram;
112 static UCHAR dftNvRam[64] =
113 {
114 /*----------header -------------*/
115         0x01,                   /* 0x00: Sub System Vendor ID 0 */
116         0x11,                   /* 0x01: Sub System Vendor ID 1 */
117         0x60,                   /* 0x02: Sub System ID 0        */
118         0x10,                   /* 0x03: Sub System ID 1        */
119         0x00,                   /* 0x04: SubClass               */
120         0x01,                   /* 0x05: Vendor ID 0            */
121         0x11,                   /* 0x06: Vendor ID 1            */
122         0x60,                   /* 0x07: Device ID 0            */
123         0x10,                   /* 0x08: Device ID 1            */
124         0x00,                   /* 0x09: Reserved               */
125         0x00,                   /* 0x0A: Reserved               */
126         0x01,                   /* 0x0B: Revision of Data Structure     */
127                                 /* -- Host Adapter Structure --- */
128         0x01,                   /* 0x0C: Number Of SCSI Channel */
129         0x01,                   /* 0x0D: BIOS Configuration 1   */
130         0x00,                   /* 0x0E: BIOS Configuration 2   */
131         0x00,                   /* 0x0F: BIOS Configuration 3   */
132                                 /* --- SCSI Channel 0 Configuration --- */
133         0x07,                   /* 0x10: H/A ID                 */
134         0x83,                   /* 0x11: Channel Configuration  */
135         0x20,                   /* 0x12: MAX TAG per target     */
136         0x0A,                   /* 0x13: SCSI Reset Recovering time     */
137         0x00,                   /* 0x14: Channel Configuration4 */
138         0x00,                   /* 0x15: Channel Configuration5 */
139                                 /* SCSI Channel 0 Target Configuration  */
140                                 /* 0x16-0x25                    */
141         0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
142         0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
143                                 /* --- SCSI Channel 1 Configuration --- */
144         0x07,                   /* 0x26: H/A ID                 */
145         0x83,                   /* 0x27: Channel Configuration  */
146         0x20,                   /* 0x28: MAX TAG per target     */
147         0x0A,                   /* 0x29: SCSI Reset Recovering time     */
148         0x00,                   /* 0x2A: Channel Configuration4 */
149         0x00,                   /* 0x2B: Channel Configuration5 */
150                                 /* SCSI Channel 1 Target Configuration  */
151                                 /* 0x2C-0x3B                    */
152         0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
153         0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
154         0x00,                   /* 0x3C: Reserved               */
155         0x00,                   /* 0x3D: Reserved               */
156         0x00,                   /* 0x3E: Reserved               */
157         0x00                    /* 0x3F: Checksum               */
158 };
159
160
161 /***************************************************************************/
162 static void waitForPause(unsigned amount)
163 {
164         ULONG the_time = jiffies + MS_TO_JIFFIES(amount);
165         while (time_before_eq(jiffies, the_time))
166                 cpu_relax();
167 }
168
169 /***************************************************************************/
170 UCHAR waitChipReady(ORC_HCS * hcsp)
171 {
172         int i;
173
174         for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
175                 if (ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HOSTSTOP)       /* Wait HOSTSTOP set */
176                         return (TRUE);
177                 waitForPause(100);      /* wait 100ms before try again  */
178         }
179         return (FALSE);
180 }
181
182 /***************************************************************************/
183 UCHAR waitFWReady(ORC_HCS * hcsp)
184 {
185         int i;
186
187         for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
188                 if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY)         /* Wait READY set */
189                         return (TRUE);
190                 waitForPause(100);      /* wait 100ms before try again  */
191         }
192         return (FALSE);
193 }
194
195 /***************************************************************************/
196 UCHAR waitSCSIRSTdone(ORC_HCS * hcsp)
197 {
198         int i;
199
200         for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
201                 if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & SCSIRST))     /* Wait SCSIRST done */
202                         return (TRUE);
203                 waitForPause(100);      /* wait 100ms before try again  */
204         }
205         return (FALSE);
206 }
207
208 /***************************************************************************/
209 UCHAR waitHDOoff(ORC_HCS * hcsp)
210 {
211         int i;
212
213         for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
214                 if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HDO))         /* Wait HDO off */
215                         return (TRUE);
216                 waitForPause(100);      /* wait 100ms before try again  */
217         }
218         return (FALSE);
219 }
220
221 /***************************************************************************/
222 UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData)
223 {
224         int i;
225
226         for (i = 0; i < 10; i++) {      /* Wait 1 second for report timeout     */
227                 if ((*pData = ORC_RD(hcsp->HCS_Base, ORC_HSTUS)) & HDI)
228                         return (TRUE);  /* Wait HDI set */
229                 waitForPause(100);      /* wait 100ms before try again  */
230         }
231         return (FALSE);
232 }
233
234 /***************************************************************************/
235 unsigned short get_FW_version(ORC_HCS * hcsp)
236 {
237         UCHAR bData;
238         union {
239                 unsigned short sVersion;
240                 unsigned char cVersion[2];
241         } Version;
242
243         ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_VERSION);
244         ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
245         if (waitHDOoff(hcsp) == FALSE)  /* Wait HDO off   */
246                 return (FALSE);
247
248         if (waitHDIset(hcsp, &bData) == FALSE)  /* Wait HDI set   */
249                 return (FALSE);
250         Version.cVersion[0] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
251         ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI            */
252
253         if (waitHDIset(hcsp, &bData) == FALSE)  /* Wait HDI set   */
254                 return (FALSE);
255         Version.cVersion[1] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
256         ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI            */
257
258         return (Version.sVersion);
259 }
260
261 /***************************************************************************/
262 UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value)
263 {
264         ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_SET_NVM);    /* Write command */
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, address);    /* Write address */
270         ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
271         if (waitHDOoff(hcsp) == FALSE)  /* Wait HDO off   */
272                 return (FALSE);
273
274         ORC_WR(hcsp->HCS_Base + ORC_HDATA, value);      /* Write value  */
275         ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
276         if (waitHDOoff(hcsp) == FALSE)  /* Wait HDO off   */
277                 return (FALSE);
278
279         return (TRUE);
280 }
281
282 /***************************************************************************/
283 UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn)
284 {
285         unsigned char bData;
286
287         ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_GET_NVM);    /* Write command */
288         ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
289         if (waitHDOoff(hcsp) == FALSE)  /* Wait HDO off   */
290                 return (FALSE);
291
292         ORC_WR(hcsp->HCS_Base + ORC_HDATA, address);    /* Write address */
293         ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
294         if (waitHDOoff(hcsp) == FALSE)  /* Wait HDO off   */
295                 return (FALSE);
296
297         if (waitHDIset(hcsp, &bData) == FALSE)  /* Wait HDI set   */
298                 return (FALSE);
299         *pDataIn = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
300         ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI    */
301
302         return (TRUE);
303 }
304
305 /***************************************************************************/
306 void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
307 {
308         scbp->SCB_Status = ORCSCB_POST;
309         ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx);
310         return;
311 }
312
313
314 /***********************************************************************
315  Read SCSI H/A configuration parameters from serial EEPROM
316 ************************************************************************/
317 int se2_rd_all(ORC_HCS * hcsp)
318 {
319         int i;
320         UCHAR *np, chksum = 0;
321
322         np = (UCHAR *) nvramp;
323         for (i = 0; i < 64; i++, np++) {        /* <01> */
324                 if (get_NVRAM(hcsp, (unsigned char) i, np) == FALSE)
325                         return -1;
326 //      *np++ = get_NVRAM(hcsp, (unsigned char ) i);
327         }
328
329 /*------ Is ckecksum ok ? ------*/
330         np = (UCHAR *) nvramp;
331         for (i = 0; i < 63; i++)
332                 chksum += *np++;
333
334         if (nvramp->CheckSum != (UCHAR) chksum)
335                 return -1;
336         return 1;
337 }
338
339 /************************************************************************
340  Update SCSI H/A configuration parameters from serial EEPROM
341 *************************************************************************/
342 void se2_update_all(ORC_HCS * hcsp)
343 {                               /* setup default pattern  */
344         int i;
345         UCHAR *np, *np1, chksum = 0;
346
347         /* Calculate checksum first   */
348         np = (UCHAR *) dftNvRam;
349         for (i = 0; i < 63; i++)
350                 chksum += *np++;
351         *np = chksum;
352
353         np = (UCHAR *) dftNvRam;
354         np1 = (UCHAR *) nvramp;
355         for (i = 0; i < 64; i++, np++, np1++) {
356                 if (*np != *np1) {
357                         set_NVRAM(hcsp, (unsigned char) i, *np);
358                 }
359         }
360         return;
361 }
362
363 /*************************************************************************
364  Function name  : read_eeprom
365 **************************************************************************/
366 void read_eeprom(ORC_HCS * hcsp)
367 {
368         if (se2_rd_all(hcsp) != 1) {
369                 se2_update_all(hcsp);   /* setup default pattern        */
370                 se2_rd_all(hcsp);       /* load again                   */
371         }
372 }
373
374
375 /***************************************************************************/
376 UCHAR load_FW(ORC_HCS * hcsp)
377 {
378         U32 dData;
379         USHORT wBIOSAddress;
380         USHORT i;
381         UCHAR *pData, bData;
382
383
384         bData = ORC_RD(hcsp->HCS_Base, ORC_GCFG);
385         ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData | EEPRG);       /* Enable EEPROM programming */
386         ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, 0x00);
387         ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x00);
388         if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0x55) {
389                 ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /* Disable EEPROM programming */
390                 return (FALSE);
391         }
392         ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x01);
393         if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0xAA) {
394                 ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /* Disable EEPROM programming */
395                 return (FALSE);
396         }
397         ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);       /* Enable SRAM programming */
398         pData = (UCHAR *) & dData;
399         dData = 0;              /* Initial FW address to 0 */
400         ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x10);
401         *pData = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);         /* Read from BIOS */
402         ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x11);
403         *(pData + 1) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);   /* Read from BIOS */
404         ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x12);
405         *(pData + 2) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);   /* Read from BIOS */
406         ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, *(pData + 2));
407         ORC_WRLONG(hcsp->HCS_Base + ORC_FWBASEADR, dData);      /* Write FW address */
408
409         wBIOSAddress = (USHORT) dData;  /* FW code locate at BIOS address + ? */
410         for (i = 0, pData = (UCHAR *) & dData;  /* Download the code    */
411              i < 0x1000;        /* Firmware code size = 4K      */
412              i++, wBIOSAddress++) {
413                 ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
414                 *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);       /* Read from BIOS */
415                 if ((i % 4) == 3) {
416                         ORC_WRLONG(hcsp->HCS_Base + ORC_RISCRAM, dData);        /* Write every 4 bytes */
417                         pData = (UCHAR *) & dData;
418                 }
419         }
420
421         ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD);       /* Reset program count 0 */
422         wBIOSAddress -= 0x1000; /* Reset the BIOS adddress      */
423         for (i = 0, pData = (UCHAR *) & dData;  /* Check the code       */
424              i < 0x1000;        /* Firmware code size = 4K      */
425              i++, wBIOSAddress++) {
426                 ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
427                 *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA);       /* Read from BIOS */
428                 if ((i % 4) == 3) {
429                         if (ORC_RDLONG(hcsp->HCS_Base, ORC_RISCRAM) != dData) {
430                                 ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);  /* Reset program to 0 */
431                                 ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /*Disable EEPROM programming */
432                                 return (FALSE);
433                         }
434                         pData = (UCHAR *) & dData;
435                 }
436         }
437         ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST);  /* Reset program to 0   */
438         ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData);       /* Disable EEPROM programming */
439         return (TRUE);
440 }
441
442 /***************************************************************************/
443 void setup_SCBs(ORC_HCS * hcsp)
444 {
445         ORC_SCB *pVirScb;
446         int i;
447         ESCB *pVirEscb;
448         dma_addr_t pPhysEscb;
449
450         /* Setup SCB HCS_Base and SCB Size registers */
451         ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, ORC_MAXQUEUE);     /* Total number of SCBs */
452         /* SCB HCS_Base address 0      */
453         ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray);
454         /* SCB HCS_Base address 1      */
455         ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE1, hcsp->HCS_physScbArray);
456
457         /* setup scatter list address with one buffer */
458         pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
459         pVirEscb = (ESCB *) hcsp->HCS_virEscbArray;
460
461         for (i = 0; i < ORC_MAXQUEUE; i++) {
462                 pPhysEscb = (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i));
463                 pVirScb->SCB_SGPAddr = (U32) pPhysEscb;
464                 pVirScb->SCB_SensePAddr = (U32) pPhysEscb;
465                 pVirScb->SCB_EScb = pVirEscb;
466                 pVirScb->SCB_ScbIdx = i;
467                 pVirScb++;
468                 pVirEscb++;
469         }
470
471         return;
472 }
473
474 /***************************************************************************/
475 static void initAFlag(ORC_HCS * hcsp)
476 {
477         UCHAR i, j;
478
479         for (i = 0; i < MAX_CHANNELS; i++) {
480                 for (j = 0; j < 8; j++) {
481                         hcsp->BitAllocFlag[i][j] = 0xffffffff;
482                 }
483         }
484 }
485
486 /***************************************************************************/
487 int init_orchid(ORC_HCS * hcsp)
488 {
489         UBYTE *readBytep;
490         USHORT revision;
491         UCHAR i;
492
493         initAFlag(hcsp);
494         ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFF);       /* Disable all interrupt        */
495         if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) {       /* Orchid is ready              */
496                 revision = get_FW_version(hcsp);
497                 if (revision == 0xFFFF) {
498                         ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);     /* Reset Host Adapter   */
499                         if (waitChipReady(hcsp) == FALSE)
500                                 return (-1);
501                         load_FW(hcsp);  /* Download FW                  */
502                         setup_SCBs(hcsp);       /* Setup SCB HCS_Base and SCB Size registers */
503                         ORC_WR(hcsp->HCS_Base + ORC_HCTRL, 0);  /* clear HOSTSTOP       */
504                         if (waitFWReady(hcsp) == FALSE)
505                                 return (-1);
506                         /* Wait for firmware ready     */
507                 } else {
508                         setup_SCBs(hcsp);       /* Setup SCB HCS_Base and SCB Size registers */
509                 }
510         } else {                /* Orchid is not Ready          */
511                 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST);     /* Reset Host Adapter   */
512                 if (waitChipReady(hcsp) == FALSE)
513                         return (-1);
514                 load_FW(hcsp);  /* Download FW                  */
515                 setup_SCBs(hcsp);       /* Setup SCB HCS_Base and SCB Size registers */
516                 ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);        /* Do Hardware Reset &  */
517
518                 /*     clear HOSTSTOP  */
519                 if (waitFWReady(hcsp) == FALSE)         /* Wait for firmware ready      */
520                         return (-1);
521         }
522
523 /*------------- get serial EEProm settting -------*/
524
525         read_eeprom(hcsp);
526
527         if (nvramp->Revision != 1)
528                 return (-1);
529
530         hcsp->HCS_SCSI_ID = nvramp->SCSI0Id;
531         hcsp->HCS_BIOS = nvramp->BIOSConfig1;
532         hcsp->HCS_MaxTar = MAX_TARGETS;
533         readBytep = (UCHAR *) & (nvramp->Target00Config);
534         for (i = 0; i < 16; readBytep++, i++) {
535                 hcsp->TargetFlag[i] = *readBytep;
536                 hcsp->MaximumTags[i] = ORC_MAXTAGS;
537         }                       /* for                          */
538
539         if (nvramp->SCSI0Config & NCC_BUSRESET) {       /* Reset SCSI bus               */
540                 hcsp->HCS_Flags |= HCF_SCSI_RESET;
541         }
542         ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFB);       /* enable RP FIFO interrupt     */
543         return (0);
544 }
545
546 /*****************************************************************************
547  Function name  : orc_reset_scsi_bus
548  Description    : Reset registers, reset a hanging bus and
549                   kill active and disconnected commands for target w/o soft reset
550  Input          : pHCB  -       Pointer to host adapter structure
551  Output         : None.
552  Return         : pSRB  -       Pointer to SCSI request block.
553 *****************************************************************************/
554 int orc_reset_scsi_bus(ORC_HCS * pHCB)
555 {                               /* I need Host Control Block Information */
556         ULONG flags;
557
558         spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
559
560         initAFlag(pHCB);
561         /* reset scsi bus */
562         ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST);
563         if (waitSCSIRSTdone(pHCB) == FALSE) {
564                 spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
565                 return FAILED;
566         } else {
567                 spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
568                 return SUCCESS;
569         }
570 }
571
572 /*****************************************************************************
573  Function name  : orc_device_reset
574  Description    : Reset registers, reset a hanging bus and
575                   kill active and disconnected commands for target w/o soft reset
576  Input          : pHCB  -       Pointer to host adapter structure
577  Output         : None.
578  Return         : pSRB  -       Pointer to SCSI request block.
579 *****************************************************************************/
580 int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target)
581 {                               /* I need Host Control Block Information */
582         ORC_SCB *pScb;
583         ESCB *pVirEscb;
584         ORC_SCB *pVirScb;
585         UCHAR i;
586         ULONG flags;
587
588         spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
589         pScb = (ORC_SCB *) NULL;
590         pVirEscb = (ESCB *) NULL;
591
592         /* setup scatter list address with one buffer */
593         pVirScb = (ORC_SCB *) pHCB->HCS_virScbArray;
594
595         initAFlag(pHCB);
596         /* device reset */
597         for (i = 0; i < ORC_MAXQUEUE; i++) {
598                 pVirEscb = pVirScb->SCB_EScb;
599                 if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt))
600                         break;
601                 pVirScb++;
602         }
603
604         if (i == ORC_MAXQUEUE) {
605                 printk("Unable to Reset - No SCB Found\n");
606                 spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
607                 return FAILED;
608         }
609         if ((pScb = orc_alloc_scb(pHCB)) == NULL) {
610                 spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
611                 return FAILED;
612         }
613         pScb->SCB_Opcode = ORC_BUSDEVRST;
614         pScb->SCB_Target = target;
615         pScb->SCB_HaStat = 0;
616         pScb->SCB_TaStat = 0;
617         pScb->SCB_Status = 0x0;
618         pScb->SCB_Link = 0xFF;
619         pScb->SCB_Reserved0 = 0;
620         pScb->SCB_Reserved1 = 0;
621         pScb->SCB_XferLen = 0;
622         pScb->SCB_SGLen = 0;
623
624         pVirEscb->SCB_Srb = 0;
625         pVirEscb->SCB_Srb = SCpnt;
626         orc_exec_scb(pHCB, pScb);       /* Start execute SCB            */
627         spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
628         return SUCCESS;
629 }
630
631
632 /***************************************************************************/
633 ORC_SCB *__orc_alloc_scb(ORC_HCS * hcsp)
634 {
635         ORC_SCB *pTmpScb;
636         UCHAR Ch;
637         ULONG idx;
638         UCHAR index;
639         UCHAR i;
640
641         Ch = hcsp->HCS_Index;
642         for (i = 0; i < 8; i++) {
643                 for (index = 0; index < 32; index++) {
644                         if ((hcsp->BitAllocFlag[Ch][i] >> index) & 0x01) {
645                                 hcsp->BitAllocFlag[Ch][i] &= ~(1 << index);
646                                 break;
647                         }
648                 }
649                 idx = index + 32 * i;
650                 pTmpScb = (PVOID) ((ULONG) hcsp->HCS_virScbArray + (idx * sizeof(ORC_SCB)));
651                 return (pTmpScb);
652         }
653         return (NULL);
654 }
655
656 ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp)
657 {
658         ORC_SCB *pTmpScb;
659         ULONG flags;
660
661         spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
662         pTmpScb = __orc_alloc_scb(hcsp);
663         spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
664         return (pTmpScb);
665 }
666
667
668 /***************************************************************************/
669 void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
670 {
671         ULONG flags;
672         UCHAR Index;
673         UCHAR i;
674         UCHAR Ch;
675
676         spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
677         Ch = hcsp->HCS_Index;
678         Index = scbp->SCB_ScbIdx;
679         i = Index / 32;
680         Index %= 32;
681         hcsp->BitAllocFlag[Ch][i] |= (1 << Index);
682         spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
683 }
684
685
686 /***************************************************************************/
687 void orc_release_dma(ORC_HCS * hcsp, Scsi_Cmnd * SCpnt)
688 {
689         struct scatterlist *pSrbSG;
690
691         if (SCpnt->use_sg) {
692                 pSrbSG = (struct scatterlist *)SCpnt->request_buffer;
693                 pci_unmap_sg(hcsp->pdev, pSrbSG, SCpnt->use_sg,
694                         scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
695         } else if (SCpnt->request_bufflen != 0) {
696                 pci_unmap_single(hcsp->pdev, (U32)SCpnt->host_scribble,
697                         SCpnt->request_bufflen,
698                         scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
699         }
700 }
701
702 /*****************************************************************************
703  Function name  : abort_SCB
704  Description    : Abort a queued command.
705                          (commands that are on the bus can't be aborted easily)
706  Input          : pHCB  -       Pointer to host adapter structure
707  Output         : None.
708  Return         : pSRB  -       Pointer to SCSI request block.
709 *****************************************************************************/
710 int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb)
711 {
712         unsigned char bData, bStatus;
713
714         ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_ABORT_SCB);  /* Write command */
715         ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
716         if (waitHDOoff(hcsp) == FALSE)  /* Wait HDO off   */
717                 return (FALSE);
718
719         ORC_WR(hcsp->HCS_Base + ORC_HDATA, pScb->SCB_ScbIdx);   /* Write address */
720         ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
721         if (waitHDOoff(hcsp) == FALSE)  /* Wait HDO off   */
722                 return (FALSE);
723
724         if (waitHDIset(hcsp, &bData) == FALSE)  /* Wait HDI set   */
725                 return (FALSE);
726         bStatus = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
727         ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData);      /* Clear HDI    */
728
729         if (bStatus == 1)       /* 0 - Successfully               */
730                 return (FALSE); /* 1 - Fail                     */
731         return (TRUE);
732 }
733
734 /*****************************************************************************
735  Function name  : inia100_abort
736  Description    : Abort a queued command.
737                          (commands that are on the bus can't be aborted easily)
738  Input          : pHCB  -       Pointer to host adapter structure
739  Output         : None.
740  Return         : pSRB  -       Pointer to SCSI request block.
741 *****************************************************************************/
742 int orc_abort_srb(ORC_HCS * hcsp, Scsi_Cmnd *SCpnt)
743 {
744         ESCB *pVirEscb;
745         ORC_SCB *pVirScb;
746         UCHAR i;
747         ULONG flags;
748
749         spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
750
751         pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
752
753         for (i = 0; i < ORC_MAXQUEUE; i++, pVirScb++) {
754                 pVirEscb = pVirScb->SCB_EScb;
755                 if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt)) {
756                         if (pVirScb->SCB_TagMsg == 0) {
757                                 spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
758                                 return FAILED;
759                         } else {
760                                 if (abort_SCB(hcsp, pVirScb)) {
761                                         pVirEscb->SCB_Srb = NULL;
762                                         spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
763                                         return SUCCESS;
764                                 } else {
765                                         spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
766                                         return FAILED;
767                                 }
768                         }
769                 }
770         }
771         spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
772         return FAILED;
773 }
774
775 /***********************************************************************
776  Routine Description:
777           This is the interrupt service routine for the Orchid SCSI adapter.
778           It reads the interrupt register to determine if the adapter is indeed
779           the source of the interrupt and clears the interrupt at the device.
780  Arguments:
781           HwDeviceExtension - HBA miniport driver's adapter data storage
782  Return Value:
783 ***********************************************************************/
784 void orc_interrupt(
785                           ORC_HCS * hcsp
786 )
787 {
788         BYTE bScbIdx;
789         ORC_SCB *pScb;
790
791         if (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT) == 0) {
792                 return;         // (FALSE);
793
794         }
795         do {
796                 bScbIdx = ORC_RD(hcsp->HCS_Base, ORC_RQUEUE);
797
798                 pScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (ULONG) (sizeof(ORC_SCB) * bScbIdx));
799                 pScb->SCB_Status = 0x0;
800
801                 inia100SCBPost((BYTE *) hcsp, (BYTE *) pScb);
802         } while (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT));
803         return;                 //(TRUE);
804
805 }                               /* End of I1060Interrupt() */