1 /**************************************************************************
2 * Initio A100 device driver for Linux.
4 * Copyright (c) 1994-1998 Initio Corporation
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)
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.
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.
21 * --------------------------------------------------------------------------
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
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.
35 * Where this Software is combined with software released under the terms of
36 * the GNU 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.
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
54 **************************************************************************
58 * This is the Linux low-level SCSI driver for Initio INIA100 SCSI host
60 * 09/24/98 hl - v1.02 initial production release.
61 * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up.
62 **************************************************************************/
64 #define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)
66 #ifndef LINUX_VERSION_CODE
67 #include <linux/version.h>
71 #include <linux/module.h>
74 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
78 #include <linux/string.h>
79 #include <linux/errno.h>
80 #include <linux/kernel.h>
81 #include <linux/ioport.h>
82 #include <linux/delay.h>
83 #include <linux/sched.h>
84 #if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92)
85 #include <linux/bios32.h>
87 #include <linux/pci.h>
88 #include <linux/proc_fs.h>
89 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23)
90 #include <linux/init.h>
92 #include <linux/blk.h>
93 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
94 #include <linux/spinlock.h>
100 #include <linux/stat.h>
101 #include <linux/malloc.h>
102 #include <linux/config.h>
107 #include <linux/kernel.h>
108 #include <linux/head.h>
109 #include <linux/types.h>
110 #include <linux/string.h>
111 #include <linux/ioport.h>
113 #include <linux/sched.h>
114 #include <linux/proc_fs.h>
115 #include <asm/system.h>
117 #include "../block/blk.h"
121 #include <linux/malloc.h>
126 Scsi_Host_Template driver_template
= INIA100
;
127 #include "scsi_module.c"
130 #define ORC_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
132 char *inia100_Copyright
= "Copyright (C) 1998-99";
133 char *inia100_InitioName
= "by Initio Corporation";
134 char *inia100_ProductName
= "INI-A100U2W";
135 char *inia100_Version
= "v1.02c";
137 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
138 struct proc_dir_entry proc_scsi_inia100
=
140 PROC_SCSI_INIA100
, 7, "INIA100",
141 S_IFDIR
| S_IRUGO
| S_IXUGO
, 2,
142 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
146 /* set by inia100_setup according to the command line */
147 static int setup_called
= 0;
148 static int orc_num_ch
= MAX_SUPPORTED_ADAPTERS
; /* Maximum 4 adapters */
150 /* ---- INTERNAL VARIABLES ---- */
151 #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
152 static char *setup_str
= (char *) NULL
;
154 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
155 static void inia100_intr0(int irq
, void *dev_id
, struct pt_regs
*);
156 static void inia100_intr1(int irq
, void *dev_id
, struct pt_regs
*);
157 static void inia100_intr2(int irq
, void *dev_id
, struct pt_regs
*);
158 static void inia100_intr3(int irq
, void *dev_id
, struct pt_regs
*);
159 static void inia100_intr4(int irq
, void *dev_id
, struct pt_regs
*);
160 static void inia100_intr5(int irq
, void *dev_id
, struct pt_regs
*);
161 static void inia100_intr6(int irq
, void *dev_id
, struct pt_regs
*);
162 static void inia100_intr7(int irq
, void *dev_id
, struct pt_regs
*);
164 static void inia100_intr0(int irq
, struct pt_regs
*);
165 static void inia100_intr1(int irq
, struct pt_regs
*);
166 static void inia100_intr2(int irq
, struct pt_regs
*);
167 static void inia100_intr3(int irq
, struct pt_regs
*);
168 static void inia100_intr4(int irq
, struct pt_regs
*);
169 static void inia100_intr5(int irq
, struct pt_regs
*);
170 static void inia100_intr6(int irq
, struct pt_regs
*);
171 static void inia100_intr7(int irq
, struct pt_regs
*);
174 static void inia100_panic(char *msg
);
175 void inia100SCBPost(BYTE
* pHcb
, BYTE
* pScb
);
177 /* ---- EXTERNAL VARIABLES ---- */
178 extern int Addinia100_into_Adapter_table(WORD
, WORD
, BYTE
, BYTE
, BYTE
);
179 extern void init_inia100Adapter_table(void);
180 extern ORC_SCB
*orc_alloc_scb(ORC_HCS
* hcsp
);
181 extern void orc_exec_scb(ORC_HCS
* hcsp
, ORC_SCB
* scbp
);
182 extern void orc_release_scb(ORC_HCS
* hcsp
, ORC_SCB
* scbp
);
183 extern void orc_interrupt(ORC_HCS
* hcsp
);
184 extern int orc_device_reset(ORC_HCS
* pHCB
, ULONG SCpnt
, unsigned int target
, unsigned int ResetFlags
);
185 extern int orc_reset_scsi_bus(ORC_HCS
* pHCB
);
186 extern int abort_SCB(ORC_HCS
* hcsp
, ORC_SCB
* pScb
);
187 extern int orc_abort_srb(ORC_HCS
* hcsp
, ULONG SCpnt
);
188 extern void get_orcPCIConfig(ORC_HCS
* pCurHcb
, int ch_idx
);
189 extern int init_orchid(ORC_HCS
* hcsp
);
191 extern int orc_num_scb
;
192 extern ORC_HCS orc_hcs
[];
194 /*****************************************************************************
195 Function name : inia100AppendSRBToQueue
196 Description : This function will push current request into save list
197 Input : pSRB - Pointer to SCSI request block.
198 pHCB - Pointer to host adapter structure
201 *****************************************************************************/
202 static void inia100AppendSRBToQueue(ORC_HCS
* pHCB
, Scsi_Cmnd
* pSRB
)
206 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
207 spin_lock_irqsave(&(pHCB
->pSRB_lock
), flags
);
213 pSRB
->next
= NULL
; /* Pointer to next */
214 if (pHCB
->pSRB_head
== NULL
)
215 pHCB
->pSRB_head
= pSRB
;
217 pHCB
->pSRB_tail
->next
= pSRB
; /* Pointer to next */
218 pHCB
->pSRB_tail
= pSRB
;
219 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
220 spin_unlock_irqrestore(&(pHCB
->pSRB_lock
), flags
);
222 restore_flags(flags
);
227 /*****************************************************************************
228 Function name : inia100PopSRBFromQueue
229 Description : This function will pop current request from save list
230 Input : pHCB - Pointer to host adapter structure
232 Return : pSRB - Pointer to SCSI request block.
233 *****************************************************************************/
234 static Scsi_Cmnd
*inia100PopSRBFromQueue(ORC_HCS
* pHCB
)
238 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
239 spin_lock_irqsave(&(pHCB
->pSRB_lock
), flags
);
245 if ((pSRB
= (Scsi_Cmnd
*) pHCB
->pSRB_head
) != NULL
) {
246 pHCB
->pSRB_head
= pHCB
->pSRB_head
->next
;
249 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
250 spin_unlock_irqrestore(&(pHCB
->pSRB_lock
), flags
);
252 restore_flags(flags
);
257 /*****************************************************************************
258 Function name : inia100_setup
260 Input : pHCB - Pointer to host adapter structure
262 Return : pSRB - Pointer to SCSI request block.
263 *****************************************************************************/
264 void inia100_setup(char *str
, int *ints
)
267 inia100_panic("inia100: inia100_setup called twice.\n");
269 setup_called
= ints
[0];
273 /*****************************************************************************
274 Function name : orc_ReturnNumberOfAdapters
275 Description : This function will scan PCI bus to get all Orchid card
278 Return : SUCCESSFUL - Successful scan
279 ohterwise - No drives founded
280 *****************************************************************************/
281 int orc_ReturnNumberOfAdapters(void)
283 unsigned int i
, iAdapters
;
289 if (pcibios_present()) {
291 unsigned short vendor_id
;
292 unsigned short device_id
;
293 } const inia100_pci_devices
[] =
295 {ORC_VENDOR_ID
, I920_DEVICE_ID
},
296 {ORC_VENDOR_ID
, ORC_DEVICE_ID
}
299 unsigned int dRegValue
;
300 unsigned short command
;
302 BYTE bPCIBusNum
, bInterrupt
, bPCIDeviceNum
;
305 unsigned long page_offset
, base
;
308 #if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
309 struct pci_dev
*pdev
= NULL
;
312 unsigned char pci_bus
, pci_devfn
;
317 init_inia100Adapter_table();
318 for (i
= 0; i
< NUMBER(inia100_pci_devices
); i
++) {
319 #if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
321 while ((pdev
= pci_find_device(inia100_pci_devices
[i
].vendor_id
,
322 inia100_pci_devices
[i
].device_id
,
326 while (!(pcibios_find_device(inia100_pci_devices
[i
].vendor_id
,
327 inia100_pci_devices
[i
].device_id
,
328 index
++, &pci_bus
, &pci_devfn
)))
331 if (iAdapters
>= MAX_SUPPORTED_ADAPTERS
)
332 break; /* Never greater than maximum */
336 printk("inia100: The RAID controller is not supported by\n");
337 printk("inia100: this driver, we are ignoring it.\n");
341 * Read sundry information from PCI BIOS.
343 #if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
344 bPCIBusNum
= pdev
->bus
->number
;
345 bPCIDeviceNum
= pdev
->devfn
;
346 dRegValue
= pdev
->resource
[0].start
;
347 if (dRegValue
== -1) { /* Check return code */
348 printk("\n\rinia100: orchid read configuration error.\n");
349 return (0); /* Read configuration space error */
351 /* <02> read from base address + 0x50 offset to get the wBIOS balue. */
352 wBASE
= (WORD
) dRegValue
;
354 /* Now read the interrupt line */
355 dRegValue
= pdev
->irq
;
356 bInterrupt
= dRegValue
& 0xFF; /* Assign interrupt line */
357 pci_read_config_word(pdev
, PCI_COMMAND
, &command
);
358 pci_write_config_word(pdev
, PCI_COMMAND
,
359 command
| PCI_COMMAND_MASTER
| PCI_COMMAND_IO
);
362 bPCIBusNum
= pci_bus
;
363 bPCIDeviceNum
= pci_devfn
;
364 pcibios_read_config_dword(pci_bus
, pci_devfn
, PCI_BASE_ADDRESS_0
,
366 if (dRegValue
== -1) { /* Check return code */
367 printk("\n\rinia100: Orchid read configuration error.\n");
368 return (0); /* Read configuration space error */
370 /* <02> read from base address + 0x50 offset to get the wBIOS balue. */
371 wBASE
= (WORD
) dRegValue
;
373 /* Now read the interrupt line */
374 pcibios_read_config_dword(pci_bus
, pci_devfn
, PCI_INTERRUPT_LINE
,
376 bInterrupt
= dRegValue
& 0xFF; /* Assign interrupt line */
377 pcibios_read_config_word(pci_bus
, pci_devfn
, PCI_COMMAND
, &command
);
378 pcibios_write_config_word(pci_bus
, pci_devfn
, PCI_COMMAND
,
379 command
| PCI_COMMAND_MASTER
| PCI_COMMAND_IO
);
381 wBASE
&= PCI_BASE_ADDRESS_IO_MASK
;
382 wBIOS
= ORC_RDWORD(wBASE
, 0x50);
385 base
= wBASE
& PAGE_MASK
;
386 page_offset
= wBASE
- base
;
389 * replace the next line with this one if you are using 2.1.x:
390 * temp_p->maddr = ioremap(base, page_offset + 256);
392 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,0)
393 wBASE
= ioremap(base
, page_offset
+ 256);
395 wBASE
= (WORD
) vremap(base
, page_offset
+ 256);
398 wBASE
+= page_offset
;
402 if (Addinia100_into_Adapter_table(wBIOS
, wBASE
, bInterrupt
, bPCIBusNum
,
403 bPCIDeviceNum
) == SUCCESSFUL
)
406 } /* while(pdev=....) */
407 } /* for PCI_DEVICES */
408 } /* PCI BIOS present */
412 /*****************************************************************************
413 Function name : inia100_detect
415 Input : pHCB - Pointer to host adapter structure
417 Return : pSRB - Pointer to SCSI request block.
418 *****************************************************************************/
419 int inia100_detect(Scsi_Host_Template
* tpnt
)
422 struct Scsi_Host
*hreg
;
424 U32 i
; /* 01/14/98 */
425 int ok
= 0, iAdapters
;
429 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
430 tpnt
->proc_dir
= &proc_scsi_inia100
;
433 /* Setup by inia100_setup */
434 printk("inia100: processing commandline: ");
436 /* Get total number of adapters in the motherboard */
437 iAdapters
= orc_ReturnNumberOfAdapters();
439 /* printk("inia100: Total Initio Adapters = %d\n", iAdapters); */
440 if (iAdapters
== 0) /* If no orc founded, return */
443 orc_num_ch
= (iAdapters
> orc_num_ch
) ? orc_num_ch
: iAdapters
;
444 orc_num_scb
= ORC_MAXQUEUE
;
446 /* clear the memory needed for HCS */
447 i
= orc_num_ch
* sizeof(ORC_HCS
);
448 memset((unsigned char *) &orc_hcs
[0], 0, i
); /* Initialize orc_hcs 0 */
451 printk("orc_num_scb= %x orc_num_ch= %x hcsize= %x scbsize= %x escbsize= %x\n",
452 orc_num_scb
, orc_num_ch
, sizeof(ORC_HCS
), sizeof(ORC_SCB
), sizeof(ESCB
));
455 for (i
= 0, pHCB
= &orc_hcs
[0]; /* Get pointer for control block */
459 pHCB
->pSRB_head
= NULL
; /* Initial SRB save queue */
460 pHCB
->pSRB_tail
= NULL
; /* Initial SRB save queue */
461 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
462 pHCB
->pSRB_lock
= SPIN_LOCK_UNLOCKED
; /* SRB save queue lock */
464 /* Get total memory needed for SCB */
465 sz
= orc_num_scb
* sizeof(ORC_SCB
);
466 if ((pHCB
->HCS_virScbArray
= (PVOID
) kmalloc(sz
, GFP_ATOMIC
| GFP_DMA
)) == NULL
) {
467 printk("inia100: SCB memory allocation error\n");
470 memset((unsigned char *) pHCB
->HCS_virScbArray
, 0, sz
);
471 pHCB
->HCS_physScbArray
= (U32
) VIRT_TO_BUS(pHCB
->HCS_virScbArray
);
473 /* Get total memory needed for ESCB */
474 sz
= orc_num_scb
* sizeof(ESCB
);
475 if ((pHCB
->HCS_virEscbArray
= (PVOID
) kmalloc(sz
, GFP_ATOMIC
| GFP_DMA
)) == NULL
) {
476 printk("inia100: ESCB memory allocation error\n");
479 memset((unsigned char *) pHCB
->HCS_virEscbArray
, 0, sz
);
480 pHCB
->HCS_physEscbArray
= (U32
) VIRT_TO_BUS(pHCB
->HCS_virEscbArray
);
482 request_region(pHCB
->HCS_Base
, 0x100, "inia100"); /* Register */
483 get_orcPCIConfig(pHCB
, i
);
485 dBiosAdr
= pHCB
->HCS_BIOS
;
486 dBiosAdr
= (dBiosAdr
<< 4);
488 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
489 pbBiosAdr
= phys_to_virt(dBiosAdr
);
492 if (init_orchid(pHCB
)) { /* Initial orchid chip */
493 printk("inia100: initial orchid fail!!\n");
496 hreg
= scsi_register(tpnt
, sizeof(ORC_HCS
));
498 printk("Invalid scsi_register pointer.\n");
500 hreg
->io_port
= pHCB
->HCS_Base
;
501 hreg
->n_io_port
= 0xff;
502 hreg
->can_queue
= orc_num_scb
; /* 03/05/98 */
504 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
505 hreg
->unique_id
= pHCB
->HCS_Base
;
506 hreg
->max_id
= pHCB
->HCS_MaxTar
;
509 hreg
->max_lun
= 32; /* 10/21/97 */
512 hreg->max_channel = 1;
514 hreg
->irq
= pHCB
->HCS_Intr
;
515 hreg
->this_id
= pHCB
->HCS_SCSI_ID
; /* Assign HCS index */
516 hreg
->base
= (UCHAR
*) pHCB
;
519 hreg
->sg_tablesize
= TOTAL_SG_ENTRY
; /* Maximun support is 32 */
521 hreg
->sg_tablesize
= SG_NONE
; /* No SG */
524 /* Initial orc chip */
526 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
528 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr0
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", NULL
);
531 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr1
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", NULL
);
534 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr2
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", NULL
);
537 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr3
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", NULL
);
540 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr4
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", NULL
);
543 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr5
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", NULL
);
546 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr6
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", NULL
);
549 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr7
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", NULL
);
552 inia100_panic("inia100: Too many host adapters\n");
558 printk("inia100: bad IRQ %d.\n", pHCB
->HCS_Intr
);
559 printk(" Contact author.\n");
562 printk("inia100: IRQ %d already in use. Configure another.\n", pHCB
->HCS_Intr
);
564 printk("\ninia100: Unexpected error code on requesting IRQ %d.\n",
566 printk(" Contact author.\n");
569 inia100_panic("inia100: driver needs an IRQ.\n");
579 /*****************************************************************************
580 Function name : inia100BuildSCB
582 Input : pHCB - Pointer to host adapter structure
584 Return : pSRB - Pointer to SCSI request block.
585 *****************************************************************************/
586 static void inia100BuildSCB(ORC_HCS
* pHCB
, ORC_SCB
* pSCB
, Scsi_Cmnd
* SCpnt
)
587 { /* Create corresponding SCB */
588 struct scatterlist
*pSrbSG
;
589 ORC_SG
*pSG
; /* Pointer to SG list */
594 pEScb
= pSCB
->SCB_EScb
;
595 pEScb
->SCB_Srb
= SCpnt
;
598 pSCB
->SCB_Opcode
= ORC_EXECSCSI
;
599 pSCB
->SCB_Flags
= SCF_NO_DCHK
; /* Clear done bit */
600 pSCB
->SCB_Target
= SCpnt
->target
;
601 pSCB
->SCB_Lun
= SCpnt
->lun
;
602 pSCB
->SCB_Reserved0
= 0;
603 pSCB
->SCB_Reserved1
= 0;
606 if ((pSCB
->SCB_XferLen
= (U32
) SCpnt
->request_bufflen
)) {
607 pSG
= (ORC_SG
*) & pEScb
->ESCB_SGList
[0];
610 pSCB
->SCB_SGLen
= (U32
) (SCpnt
->use_sg
* 8);
611 pSrbSG
= (struct scatterlist
*) SCpnt
->request_buffer
;
612 for (i
= 0; i
< SCpnt
->use_sg
; i
++, pSG
++, pSrbSG
++) {
613 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
614 pSG
->SG_Ptr
= (U32
) (VIRT_TO_BUS(pSrbSG
->address
));
616 pSG
->SG_Ptr
= (U32
) pSrbSG
->address
;
618 pSG
->SG_Len
= (U32
) pSrbSG
->length
;
619 TotalLen
+= (U32
) pSrbSG
->length
;
621 } else { /* Non SG */
622 pSCB
->SCB_SGLen
= 0x8;
623 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
624 pSG
->SG_Ptr
= (U32
) (VIRT_TO_BUS(SCpnt
->request_buffer
));
626 pSG
->SG_PTR
= (U32
) SCpnt
->request_buffer
;
628 pSG
->SG_Len
= (U32
) SCpnt
->request_bufflen
;
631 pSCB
->SCB_SGPAddr
= (U32
) pSCB
->SCB_SensePAddr
;
632 pSCB
->SCB_HaStat
= 0;
633 pSCB
->SCB_TaStat
= 0;
634 pSCB
->SCB_Link
= 0xFF;
635 pSCB
->SCB_SenseLen
= SENSE_SIZE
;
636 pSCB
->SCB_CDBLen
= SCpnt
->cmd_len
;
637 if (pSCB
->SCB_CDBLen
>= IMAX_CDB
) {
638 printk("max cdb length= %x\b", SCpnt
->cmd_len
);
639 pSCB
->SCB_CDBLen
= IMAX_CDB
;
641 pSCB
->SCB_Ident
= SCpnt
->lun
| DISC_ALLOW
;
642 if (SCpnt
->device
->tagged_supported
) { /* Tag Support */
643 pSCB
->SCB_TagMsg
= SIMPLE_QUEUE_TAG
; /* Do simple tag only */
645 pSCB
->SCB_TagMsg
= 0; /* No tag support */
647 memcpy(&pSCB
->SCB_CDB
[0], &SCpnt
->cmnd
, pSCB
->SCB_CDBLen
);
651 /*****************************************************************************
652 Function name : inia100_queue
653 Description : Queue a command and setup interrupts for a free bus.
654 Input : pHCB - Pointer to host adapter structure
656 Return : pSRB - Pointer to SCSI request block.
657 *****************************************************************************/
658 int inia100_queue(Scsi_Cmnd
* SCpnt
, void (*done
) (Scsi_Cmnd
*))
660 register ORC_SCB
*pSCB
;
661 ORC_HCS
*pHCB
; /* Point to Host adapter control block */
663 if (SCpnt
->lun
> 16) {
664 SCpnt
->result
= (DID_TIME_OUT
<< 16);
665 done(SCpnt
); /* Notify system DONE */
668 pHCB
= (ORC_HCS
*) SCpnt
->host
->base
;
669 SCpnt
->scsi_done
= done
;
670 /* Get free SCSI control block */
671 if ((pSCB
= orc_alloc_scb(pHCB
)) == NULL
) {
672 inia100AppendSRBToQueue(pHCB
, SCpnt
); /* Buffer this request */
673 /* printk("inia100_entry: can't allocate SCB\n"); */
676 inia100BuildSCB(pHCB
, pSCB
, SCpnt
);
677 orc_exec_scb(pHCB
, pSCB
); /* Start execute SCB */
682 /*****************************************************************************
683 Function name : inia100_command
684 Description : We only support command in interrupt-driven fashion
685 Input : pHCB - Pointer to host adapter structure
687 Return : pSRB - Pointer to SCSI request block.
688 *****************************************************************************/
689 int inia100_command(Scsi_Cmnd
* SCpnt
)
691 printk("inia100: interrupt driven driver; use inia100_queue()\n");
695 /*****************************************************************************
696 Function name : inia100_abort
697 Description : Abort a queued command.
698 (commands that are on the bus can't be aborted easily)
699 Input : pHCB - Pointer to host adapter structure
701 Return : pSRB - Pointer to SCSI request block.
702 *****************************************************************************/
703 int inia100_abort(Scsi_Cmnd
* SCpnt
)
707 hcsp
= (ORC_HCS
*) SCpnt
->host
->base
;
708 return orc_abort_srb(hcsp
, (ULONG
) SCpnt
);
711 /*****************************************************************************
712 Function name : inia100_reset
713 Description : Reset registers, reset a hanging bus and
714 kill active and disconnected commands for target w/o soft reset
715 Input : pHCB - Pointer to host adapter structure
717 Return : pSRB - Pointer to SCSI request block.
718 *****************************************************************************/
719 int inia100_reset(Scsi_Cmnd
* SCpnt
, unsigned int reset_flags
)
720 { /* I need Host Control Block Information */
722 pHCB
= (ORC_HCS
*) SCpnt
->host
->base
;
724 if (reset_flags
& (SCSI_RESET_SUGGEST_BUS_RESET
| SCSI_RESET_SUGGEST_HOST_RESET
))
725 return orc_reset_scsi_bus(pHCB
);
727 return orc_device_reset(pHCB
, (ULONG
) SCpnt
, SCpnt
->target
, reset_flags
);
731 /*****************************************************************************
732 Function name : inia100SCBPost
733 Description : This is callback routine be called when orc finish one
735 Input : pHCB - Pointer to host adapter control block.
736 pSCB - Pointer to SCSI control block.
739 *****************************************************************************/
740 void inia100SCBPost(BYTE
* pHcb
, BYTE
* pScb
)
742 Scsi_Cmnd
*pSRB
; /* Pointer to SCSI request block */
747 pHCB
= (ORC_HCS
*) pHcb
;
748 pSCB
= (ORC_SCB
*) pScb
;
749 pEScb
= pSCB
->SCB_EScb
;
750 if ((pSRB
= (Scsi_Cmnd
*) pEScb
->SCB_Srb
) == 0) {
751 printk("inia100SCBPost: SRB pointer is empty\n");
752 orc_release_scb(pHCB
, pSCB
); /* Release SCB for current channel */
755 pEScb
->SCB_Srb
= NULL
;
757 switch (pSCB
->SCB_HaStat
) {
759 case 0xa: /* Linked command complete without error and linked normally */
760 case 0xb: /* Linked command complete without error interrupt generated */
761 pSCB
->SCB_HaStat
= 0;
764 case 0x11: /* Selection time out-The initiator selection or target
765 reselection was not complete within the SCSI Time out period */
766 pSCB
->SCB_HaStat
= DID_TIME_OUT
;
769 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
770 phase sequence was requested by the target. The host adapter
771 will generate a SCSI Reset Condition, notifying the host with
773 pSCB
->SCB_HaStat
= DID_RESET
;
776 case 0x1a: /* SCB Aborted. 07/21/98 */
777 pSCB
->SCB_HaStat
= DID_ABORT
;
780 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
781 than was allocated by the Data Length field or the sum of the
782 Scatter / Gather Data Length fields. */
783 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
784 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid. */
787 printk("inia100: %x %x\n", pSCB
->SCB_HaStat
, pSCB
->SCB_TaStat
);
788 pSCB
->SCB_HaStat
= DID_ERROR
; /* Couldn't find any better */
792 if (pSCB
->SCB_TaStat
== 2) { /* Check condition */
793 memcpy((unsigned char *) &pSRB
->sense_buffer
[0],
794 (unsigned char *) &pEScb
->ESCB_SGList
[0], SENSE_SIZE
);
796 pSRB
->result
= pSCB
->SCB_TaStat
| (pSCB
->SCB_HaStat
<< 16);
797 pSRB
->scsi_done(pSRB
); /* Notify system DONE */
799 /* Find the next pending SRB */
800 if ((pSRB
= inia100PopSRBFromQueue(pHCB
)) != NULL
) { /* Assume resend will success */
802 inia100BuildSCB(pHCB
, pSCB
, pSRB
); /* Create corresponding SCB */
803 orc_exec_scb(pHCB
, pSCB
); /* Start execute SCB */
804 } else { /* No Pending SRB */
805 orc_release_scb(pHCB
, pSCB
); /* Release SCB for current channel */
810 /*****************************************************************************
811 Function name : inia100_biosparam
812 Description : Return the "logical geometry"
813 Input : pHCB - Pointer to host adapter structure
815 Return : pSRB - Pointer to SCSI request block.
816 *****************************************************************************/
817 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
818 int inia100_biosparam(Scsi_Disk
* disk
, kdev_t dev
, int *info_array
)
820 int inia100_biosparam(Scsi_Disk
* disk
, int dev
, int *info_array
)
823 ORC_HCS
*pHcb
; /* Point to Host adapter control block */
826 pHcb
= (ORC_HCS
*) disk
->device
->host
->base
;
827 pTcb
= &pHcb
->HCS_Tcs
[disk
->device
->id
];
829 if (pTcb
->TCS_DrvHead
) {
830 info_array
[0] = pTcb
->TCS_DrvHead
;
831 info_array
[1] = pTcb
->TCS_DrvSector
;
832 info_array
[2] = disk
->capacity
/ pTcb
->TCS_DrvHead
/ pTcb
->TCS_DrvSector
;
834 if (pTcb
->TCS_DrvFlags
& TCF_DRV_255_63
) {
837 info_array
[2] = disk
->capacity
/ 255 / 63;
841 info_array
[2] = disk
->capacity
>> 11;
848 static void subIntr(ORC_HCS
* pHCB
, int irqno
)
850 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
853 spin_lock_irqsave(&io_request_lock
, flags
);
856 if (pHCB
->HCS_Intr
!= irqno
) {
857 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
858 spin_unlock_irqrestore(&io_request_lock
, flags
);
864 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
865 spin_unlock_irqrestore(&io_request_lock
, flags
);
870 * Interrupts handler (main routine of the driver)
872 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
873 static void inia100_intr0(int irqno
, void *dev_id
, struct pt_regs
*regs
)
875 static void inia100_intr0(int irqno
, struct pt_regs
*regs
)
878 subIntr(&orc_hcs
[0], irqno
);
881 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
882 static void inia100_intr1(int irqno
, void *dev_id
, struct pt_regs
*regs
)
884 static void inia100_intr1(int irqno
, struct pt_regs
*regs
)
887 subIntr(&orc_hcs
[1], irqno
);
890 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
891 static void inia100_intr2(int irqno
, void *dev_id
, struct pt_regs
*regs
)
893 static void inia100_intr2(int irqno
, struct pt_regs
*regs
)
896 subIntr(&orc_hcs
[2], irqno
);
899 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
900 static void inia100_intr3(int irqno
, void *dev_id
, struct pt_regs
*regs
)
902 static void inia100_intr3(int irqno
, struct pt_regs
*regs
)
905 subIntr(&orc_hcs
[3], irqno
);
908 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
909 static void inia100_intr4(int irqno
, void *dev_id
, struct pt_regs
*regs
)
911 static void inia100_intr4(int irqno
, struct pt_regs
*regs
)
914 subIntr(&orc_hcs
[4], irqno
);
917 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
918 static void inia100_intr5(int irqno
, void *dev_id
, struct pt_regs
*regs
)
920 static void inia100_intr5(int irqno
, struct pt_regs
*regs
)
923 subIntr(&orc_hcs
[5], irqno
);
926 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
927 static void inia100_intr6(int irqno
, void *dev_id
, struct pt_regs
*regs
)
929 static void inia100_intr6(int irqno
, struct pt_regs
*regs
)
932 subIntr(&orc_hcs
[6], irqno
);
935 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
936 static void inia100_intr7(int irqno
, void *dev_id
, struct pt_regs
*regs
)
938 static void inia100_intr7(int irqno
, struct pt_regs
*regs
)
941 subIntr(&orc_hcs
[7], irqno
);
945 * Dump the current driver status and panic...
947 static void inia100_panic(char *msg
)
949 printk("\ninia100_panic: %s\n", msg
);
950 panic("inia100 panic");
953 /*#include "inia100scsi.c" */