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>
76 #include <linux/errno.h>
77 #include <linux/delay.h>
78 #include <linux/pci.h>
79 #include <linux/init.h>
80 #include <linux/blk.h>
81 #include <linux/spinlock.h>
82 #include <linux/stat.h>
83 #include <linux/kernel.h>
84 #include <linux/string.h>
85 #include <linux/ioport.h>
86 #include <linux/sched.h>
87 #include <linux/proc_fs.h>
92 #include <linux/malloc.h>
96 Scsi_Host_Template driver_template
= INIA100
;
97 #include "scsi_module.c"
100 #define ORC_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
102 char *inia100_Copyright
= "Copyright (C) 1998-99";
103 char *inia100_InitioName
= "by Initio Corporation";
104 char *inia100_ProductName
= "INI-A100U2W";
105 char *inia100_Version
= "v1.02c";
107 /* set by inia100_setup according to the command line */
108 static int setup_called
= 0;
109 static int orc_num_ch
= MAX_SUPPORTED_ADAPTERS
; /* Maximum 4 adapters */
111 /* ---- INTERNAL VARIABLES ---- */
112 #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
113 static char *setup_str
= (char *) NULL
;
115 static void inia100_intr0(int irq
, void *dev_id
, struct pt_regs
*);
116 static void inia100_intr1(int irq
, void *dev_id
, struct pt_regs
*);
117 static void inia100_intr2(int irq
, void *dev_id
, struct pt_regs
*);
118 static void inia100_intr3(int irq
, void *dev_id
, struct pt_regs
*);
119 static void inia100_intr4(int irq
, void *dev_id
, struct pt_regs
*);
120 static void inia100_intr5(int irq
, void *dev_id
, struct pt_regs
*);
121 static void inia100_intr6(int irq
, void *dev_id
, struct pt_regs
*);
122 static void inia100_intr7(int irq
, void *dev_id
, struct pt_regs
*);
124 static void inia100_panic(char *msg
);
125 void inia100SCBPost(BYTE
* pHcb
, BYTE
* pScb
);
127 /* ---- EXTERNAL VARIABLES ---- */
128 extern int Addinia100_into_Adapter_table(WORD
, WORD
, BYTE
, BYTE
, BYTE
);
129 extern void init_inia100Adapter_table(void);
130 extern ORC_SCB
*orc_alloc_scb(ORC_HCS
* hcsp
);
131 extern void orc_exec_scb(ORC_HCS
* hcsp
, ORC_SCB
* scbp
);
132 extern void orc_release_scb(ORC_HCS
* hcsp
, ORC_SCB
* scbp
);
133 extern void orc_interrupt(ORC_HCS
* hcsp
);
134 extern int orc_device_reset(ORC_HCS
* pHCB
, ULONG SCpnt
, unsigned int target
, unsigned int ResetFlags
);
135 extern int orc_reset_scsi_bus(ORC_HCS
* pHCB
);
136 extern int abort_SCB(ORC_HCS
* hcsp
, ORC_SCB
* pScb
);
137 extern int orc_abort_srb(ORC_HCS
* hcsp
, ULONG SCpnt
);
138 extern void get_orcPCIConfig(ORC_HCS
* pCurHcb
, int ch_idx
);
139 extern int init_orchid(ORC_HCS
* hcsp
);
141 extern int orc_num_scb
;
142 extern ORC_HCS orc_hcs
[];
144 /*****************************************************************************
145 Function name : inia100AppendSRBToQueue
146 Description : This function will push current request into save list
147 Input : pSRB - Pointer to SCSI request block.
148 pHCB - Pointer to host adapter structure
151 *****************************************************************************/
152 static void inia100AppendSRBToQueue(ORC_HCS
* pHCB
, Scsi_Cmnd
* pSRB
)
156 spin_lock_irqsave(&(pHCB
->pSRB_lock
), flags
);
158 pSRB
->next
= NULL
; /* Pointer to next */
159 if (pHCB
->pSRB_head
== NULL
)
160 pHCB
->pSRB_head
= pSRB
;
162 pHCB
->pSRB_tail
->next
= pSRB
; /* Pointer to next */
163 pHCB
->pSRB_tail
= pSRB
;
164 spin_unlock_irqrestore(&(pHCB
->pSRB_lock
), flags
);
168 /*****************************************************************************
169 Function name : inia100PopSRBFromQueue
170 Description : This function will pop current request from save list
171 Input : pHCB - Pointer to host adapter structure
173 Return : pSRB - Pointer to SCSI request block.
174 *****************************************************************************/
175 static Scsi_Cmnd
*inia100PopSRBFromQueue(ORC_HCS
* pHCB
)
179 spin_lock_irqsave(&(pHCB
->pSRB_lock
), flags
);
180 if ((pSRB
= (Scsi_Cmnd
*) pHCB
->pSRB_head
) != NULL
) {
181 pHCB
->pSRB_head
= pHCB
->pSRB_head
->next
;
184 spin_unlock_irqrestore(&(pHCB
->pSRB_lock
), flags
);
188 /*****************************************************************************
189 Function name : inia100_setup
191 Input : pHCB - Pointer to host adapter structure
193 Return : pSRB - Pointer to SCSI request block.
194 *****************************************************************************/
195 void inia100_setup(char *str
, int *ints
)
198 inia100_panic("inia100: inia100_setup called twice.\n");
200 setup_called
= ints
[0];
204 /*****************************************************************************
205 Function name : orc_ReturnNumberOfAdapters
206 Description : This function will scan PCI bus to get all Orchid card
209 Return : SUCCESSFUL - Successful scan
210 ohterwise - No drives founded
211 *****************************************************************************/
212 int orc_ReturnNumberOfAdapters(void)
214 unsigned int i
, iAdapters
;
220 if (pcibios_present()) {
222 unsigned short vendor_id
;
223 unsigned short device_id
;
224 } const inia100_pci_devices
[] =
226 {ORC_VENDOR_ID
, I920_DEVICE_ID
},
227 {ORC_VENDOR_ID
, ORC_DEVICE_ID
}
230 unsigned int dRegValue
;
232 BYTE bPCIBusNum
, bInterrupt
, bPCIDeviceNum
;
235 unsigned long page_offset
, base
;
238 struct pci_dev
*pdev
= NULL
;
242 init_inia100Adapter_table();
243 for (i
= 0; i
< NUMBER(inia100_pci_devices
); i
++) {
245 while ((pdev
= pci_find_device(inia100_pci_devices
[i
].vendor_id
,
246 inia100_pci_devices
[i
].device_id
,
249 if (pci_enable_device(pdev
))
251 if (iAdapters
>= MAX_SUPPORTED_ADAPTERS
)
252 break; /* Never greater than maximum */
256 printk("inia100: The RAID controller is not supported by\n");
257 printk("inia100: this driver, we are ignoring it.\n");
261 * Read sundry information from PCI BIOS.
263 bPCIBusNum
= pdev
->bus
->number
;
264 bPCIDeviceNum
= pdev
->devfn
;
265 dRegValue
= pci_resource_start(pdev
, 0);
266 if (dRegValue
== -1) { /* Check return code */
267 printk("\n\rinia100: orchid read configuration error.\n");
268 return (0); /* Read configuration space error */
271 /* <02> read from base address + 0x50 offset to get the wBIOS balue. */
272 wBASE
= (WORD
) dRegValue
;
274 /* Now read the interrupt line value */
275 dRegValue
= pdev
->irq
;
276 bInterrupt
= dRegValue
; /* Assign interrupt line */
278 wBIOS
= ORC_RDWORD(wBASE
, 0x50);
280 pci_set_master(pdev
);
283 base
= wBASE
& PAGE_MASK
;
284 page_offset
= wBASE
- base
;
287 * replace the next line with this one if you are using 2.1.x:
288 * temp_p->maddr = ioremap(base, page_offset + 256);
290 wBASE
= ioremap(base
, page_offset
+ 256);
292 wBASE
+= page_offset
;
296 if (Addinia100_into_Adapter_table(wBIOS
, wBASE
, bInterrupt
, bPCIBusNum
,
297 bPCIDeviceNum
) == SUCCESSFUL
)
300 } /* while(pdev=....) */
301 } /* for PCI_DEVICES */
302 } /* PCI BIOS present */
306 /*****************************************************************************
307 Function name : inia100_detect
309 Input : pHCB - Pointer to host adapter structure
311 Return : pSRB - Pointer to SCSI request block.
312 *****************************************************************************/
313 int inia100_detect(Scsi_Host_Template
* tpnt
)
316 struct Scsi_Host
*hreg
;
318 U32 i
; /* 01/14/98 */
319 int ok
= 0, iAdapters
;
323 tpnt
->proc_name
= "INIA100";
325 /* Setup by inia100_setup */
326 printk("inia100: processing commandline: ");
328 /* Get total number of adapters in the motherboard */
329 iAdapters
= orc_ReturnNumberOfAdapters();
331 /* printk("inia100: Total Initio Adapters = %d\n", iAdapters); */
332 if (iAdapters
== 0) /* If no orc founded, return */
335 orc_num_ch
= (iAdapters
> orc_num_ch
) ? orc_num_ch
: iAdapters
;
336 orc_num_scb
= ORC_MAXQUEUE
;
338 /* clear the memory needed for HCS */
339 i
= orc_num_ch
* sizeof(ORC_HCS
);
340 memset((unsigned char *) &orc_hcs
[0], 0, i
); /* Initialize orc_hcs 0 */
343 printk("orc_num_scb= %x orc_num_ch= %x hcsize= %x scbsize= %x escbsize= %x\n",
344 orc_num_scb
, orc_num_ch
, sizeof(ORC_HCS
), sizeof(ORC_SCB
), sizeof(ESCB
));
347 for (i
= 0, pHCB
= &orc_hcs
[0]; /* Get pointer for control block */
351 pHCB
->pSRB_head
= NULL
; /* Initial SRB save queue */
352 pHCB
->pSRB_tail
= NULL
; /* Initial SRB save queue */
353 pHCB
->pSRB_lock
= SPIN_LOCK_UNLOCKED
; /* SRB save queue lock */
354 pHCB
->BitAllocFlagLock
= SPIN_LOCK_UNLOCKED
;
355 /* Get total memory needed for SCB */
356 sz
= orc_num_scb
* sizeof(ORC_SCB
);
357 if ((pHCB
->HCS_virScbArray
= (PVOID
) kmalloc(sz
, GFP_ATOMIC
| GFP_DMA
)) == NULL
) {
358 printk("inia100: SCB memory allocation error\n");
361 memset((unsigned char *) pHCB
->HCS_virScbArray
, 0, sz
);
362 pHCB
->HCS_physScbArray
= (U32
) VIRT_TO_BUS(pHCB
->HCS_virScbArray
);
364 /* Get total memory needed for ESCB */
365 sz
= orc_num_scb
* sizeof(ESCB
);
366 if ((pHCB
->HCS_virEscbArray
= (PVOID
) kmalloc(sz
, GFP_ATOMIC
| GFP_DMA
)) == NULL
) {
367 printk("inia100: ESCB memory allocation error\n");
370 memset((unsigned char *) pHCB
->HCS_virEscbArray
, 0, sz
);
371 pHCB
->HCS_physEscbArray
= (U32
) VIRT_TO_BUS(pHCB
->HCS_virEscbArray
);
373 get_orcPCIConfig(pHCB
, i
);
375 dBiosAdr
= pHCB
->HCS_BIOS
;
376 dBiosAdr
= (dBiosAdr
<< 4);
378 pbBiosAdr
= phys_to_virt(dBiosAdr
);
380 if (init_orchid(pHCB
)) { /* Initial orchid chip */
381 printk("inia100: initial orchid fail!!\n");
384 request_region(pHCB
->HCS_Base
, 256, "inia100"); /* Register */
386 hreg
= scsi_register(tpnt
, sizeof(ORC_HCS
));
388 printk("Invalid scsi_register pointer.\n");
390 hreg
->io_port
= pHCB
->HCS_Base
;
391 hreg
->n_io_port
= 0xff;
392 hreg
->can_queue
= orc_num_scb
; /* 03/05/98 */
394 hreg
->unique_id
= pHCB
->HCS_Base
;
395 hreg
->max_id
= pHCB
->HCS_MaxTar
;
397 hreg
->max_lun
= 32; /* 10/21/97 */
400 hreg->max_channel = 1;
402 hreg
->irq
= pHCB
->HCS_Intr
;
403 hreg
->this_id
= pHCB
->HCS_SCSI_ID
; /* Assign HCS index */
404 hreg
->base
= (unsigned long)pHCB
;
407 hreg
->sg_tablesize
= TOTAL_SG_ENTRY
; /* Maximun support is 32 */
409 hreg
->sg_tablesize
= SG_NONE
; /* No SG */
412 /* Initial orc chip */
415 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr0
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", hreg
);
418 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr1
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", hreg
);
421 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr2
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", hreg
);
424 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr3
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", hreg
);
427 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr4
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", hreg
);
430 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr5
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", hreg
);
433 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr6
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", hreg
);
436 ok
= request_irq(pHCB
->HCS_Intr
, inia100_intr7
, SA_INTERRUPT
| SA_SHIRQ
, "inia100", hreg
);
439 inia100_panic("inia100: Too many host adapters\n");
445 printk("inia100: bad IRQ %d.\n", pHCB
->HCS_Intr
);
446 printk(" Contact author.\n");
449 printk("inia100: IRQ %d already in use. Configure another.\n", pHCB
->HCS_Intr
);
451 printk("\ninia100: Unexpected error code on requesting IRQ %d.\n",
453 printk(" Contact author.\n");
456 inia100_panic("inia100: driver needs an IRQ.\n");
465 /*****************************************************************************
466 Function name : inia100BuildSCB
468 Input : pHCB - Pointer to host adapter structure
470 Return : pSRB - Pointer to SCSI request block.
471 *****************************************************************************/
472 static void inia100BuildSCB(ORC_HCS
* pHCB
, ORC_SCB
* pSCB
, Scsi_Cmnd
* SCpnt
)
473 { /* Create corresponding SCB */
474 struct scatterlist
*pSrbSG
;
475 ORC_SG
*pSG
; /* Pointer to SG list */
480 pEScb
= pSCB
->SCB_EScb
;
481 pEScb
->SCB_Srb
= SCpnt
;
484 pSCB
->SCB_Opcode
= ORC_EXECSCSI
;
485 pSCB
->SCB_Flags
= SCF_NO_DCHK
; /* Clear done bit */
486 pSCB
->SCB_Target
= SCpnt
->target
;
487 pSCB
->SCB_Lun
= SCpnt
->lun
;
488 pSCB
->SCB_Reserved0
= 0;
489 pSCB
->SCB_Reserved1
= 0;
492 if ((pSCB
->SCB_XferLen
= (U32
) SCpnt
->request_bufflen
)) {
493 pSG
= (ORC_SG
*) & pEScb
->ESCB_SGList
[0];
496 pSCB
->SCB_SGLen
= (U32
) (SCpnt
->use_sg
* 8);
497 pSrbSG
= (struct scatterlist
*) SCpnt
->request_buffer
;
498 for (i
= 0; i
< SCpnt
->use_sg
; i
++, pSG
++, pSrbSG
++) {
499 pSG
->SG_Ptr
= (U32
) (VIRT_TO_BUS(pSrbSG
->address
));
500 pSG
->SG_Len
= (U32
) pSrbSG
->length
;
501 TotalLen
+= (U32
) pSrbSG
->length
;
503 } else { /* Non SG */
504 pSCB
->SCB_SGLen
= 0x8;
505 pSG
->SG_Ptr
= (U32
) (VIRT_TO_BUS(SCpnt
->request_buffer
));
506 pSG
->SG_Len
= (U32
) SCpnt
->request_bufflen
;
509 pSCB
->SCB_SGPAddr
= (U32
) pSCB
->SCB_SensePAddr
;
510 pSCB
->SCB_HaStat
= 0;
511 pSCB
->SCB_TaStat
= 0;
512 pSCB
->SCB_Link
= 0xFF;
513 pSCB
->SCB_SenseLen
= SENSE_SIZE
;
514 pSCB
->SCB_CDBLen
= SCpnt
->cmd_len
;
515 if (pSCB
->SCB_CDBLen
>= IMAX_CDB
) {
516 printk("max cdb length= %x\b", SCpnt
->cmd_len
);
517 pSCB
->SCB_CDBLen
= IMAX_CDB
;
519 pSCB
->SCB_Ident
= SCpnt
->lun
| DISC_ALLOW
;
520 if (SCpnt
->device
->tagged_supported
) { /* Tag Support */
521 pSCB
->SCB_TagMsg
= SIMPLE_QUEUE_TAG
; /* Do simple tag only */
523 pSCB
->SCB_TagMsg
= 0; /* No tag support */
525 memcpy(&pSCB
->SCB_CDB
[0], &SCpnt
->cmnd
, pSCB
->SCB_CDBLen
);
529 /*****************************************************************************
530 Function name : inia100_queue
531 Description : Queue a command and setup interrupts for a free bus.
532 Input : pHCB - Pointer to host adapter structure
534 Return : pSRB - Pointer to SCSI request block.
535 *****************************************************************************/
536 int inia100_queue(Scsi_Cmnd
* SCpnt
, void (*done
) (Scsi_Cmnd
*))
538 register ORC_SCB
*pSCB
;
539 ORC_HCS
*pHCB
; /* Point to Host adapter control block */
541 if (SCpnt
->lun
> 16) {
542 SCpnt
->result
= (DID_TIME_OUT
<< 16);
543 done(SCpnt
); /* Notify system DONE */
546 pHCB
= (ORC_HCS
*) SCpnt
->host
->base
;
547 SCpnt
->scsi_done
= done
;
548 /* Get free SCSI control block */
549 if ((pSCB
= orc_alloc_scb(pHCB
)) == NULL
) {
550 inia100AppendSRBToQueue(pHCB
, SCpnt
); /* Buffer this request */
551 /* printk("inia100_entry: can't allocate SCB\n"); */
554 inia100BuildSCB(pHCB
, pSCB
, SCpnt
);
555 orc_exec_scb(pHCB
, pSCB
); /* Start execute SCB */
560 /*****************************************************************************
561 Function name : inia100_command
562 Description : We only support command in interrupt-driven fashion
563 Input : pHCB - Pointer to host adapter structure
565 Return : pSRB - Pointer to SCSI request block.
566 *****************************************************************************/
567 int inia100_command(Scsi_Cmnd
* SCpnt
)
569 printk("inia100: interrupt driven driver; use inia100_queue()\n");
573 /*****************************************************************************
574 Function name : inia100_abort
575 Description : Abort a queued command.
576 (commands that are on the bus can't be aborted easily)
577 Input : pHCB - Pointer to host adapter structure
579 Return : pSRB - Pointer to SCSI request block.
580 *****************************************************************************/
581 int inia100_abort(Scsi_Cmnd
* SCpnt
)
585 hcsp
= (ORC_HCS
*) SCpnt
->host
->base
;
586 return orc_abort_srb(hcsp
, (ULONG
) SCpnt
);
589 /*****************************************************************************
590 Function name : inia100_reset
591 Description : Reset registers, reset a hanging bus and
592 kill active and disconnected commands for target w/o soft reset
593 Input : pHCB - Pointer to host adapter structure
595 Return : pSRB - Pointer to SCSI request block.
596 *****************************************************************************/
597 int inia100_reset(Scsi_Cmnd
* SCpnt
, unsigned int reset_flags
)
598 { /* I need Host Control Block Information */
600 pHCB
= (ORC_HCS
*) SCpnt
->host
->base
;
602 if (reset_flags
& (SCSI_RESET_SUGGEST_BUS_RESET
| SCSI_RESET_SUGGEST_HOST_RESET
))
603 return orc_reset_scsi_bus(pHCB
);
605 return orc_device_reset(pHCB
, (ULONG
) SCpnt
, SCpnt
->target
, reset_flags
);
609 /*****************************************************************************
610 Function name : inia100SCBPost
611 Description : This is callback routine be called when orc finish one
613 Input : pHCB - Pointer to host adapter control block.
614 pSCB - Pointer to SCSI control block.
617 *****************************************************************************/
618 void inia100SCBPost(BYTE
* pHcb
, BYTE
* pScb
)
620 Scsi_Cmnd
*pSRB
; /* Pointer to SCSI request block */
625 pHCB
= (ORC_HCS
*) pHcb
;
626 pSCB
= (ORC_SCB
*) pScb
;
627 pEScb
= pSCB
->SCB_EScb
;
628 if ((pSRB
= (Scsi_Cmnd
*) pEScb
->SCB_Srb
) == 0) {
629 printk("inia100SCBPost: SRB pointer is empty\n");
630 orc_release_scb(pHCB
, pSCB
); /* Release SCB for current channel */
633 pEScb
->SCB_Srb
= NULL
;
635 switch (pSCB
->SCB_HaStat
) {
637 case 0xa: /* Linked command complete without error and linked normally */
638 case 0xb: /* Linked command complete without error interrupt generated */
639 pSCB
->SCB_HaStat
= 0;
642 case 0x11: /* Selection time out-The initiator selection or target
643 reselection was not complete within the SCSI Time out period */
644 pSCB
->SCB_HaStat
= DID_TIME_OUT
;
647 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
648 phase sequence was requested by the target. The host adapter
649 will generate a SCSI Reset Condition, notifying the host with
651 pSCB
->SCB_HaStat
= DID_RESET
;
654 case 0x1a: /* SCB Aborted. 07/21/98 */
655 pSCB
->SCB_HaStat
= DID_ABORT
;
658 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
659 than was allocated by the Data Length field or the sum of the
660 Scatter / Gather Data Length fields. */
661 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
662 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid. */
665 printk("inia100: %x %x\n", pSCB
->SCB_HaStat
, pSCB
->SCB_TaStat
);
666 pSCB
->SCB_HaStat
= DID_ERROR
; /* Couldn't find any better */
670 if (pSCB
->SCB_TaStat
== 2) { /* Check condition */
671 memcpy((unsigned char *) &pSRB
->sense_buffer
[0],
672 (unsigned char *) &pEScb
->ESCB_SGList
[0], SENSE_SIZE
);
674 pSRB
->result
= pSCB
->SCB_TaStat
| (pSCB
->SCB_HaStat
<< 16);
675 pSRB
->scsi_done(pSRB
); /* Notify system DONE */
677 /* Find the next pending SRB */
678 if ((pSRB
= inia100PopSRBFromQueue(pHCB
)) != NULL
) { /* Assume resend will success */
680 inia100BuildSCB(pHCB
, pSCB
, pSRB
); /* Create corresponding SCB */
681 orc_exec_scb(pHCB
, pSCB
); /* Start execute SCB */
682 } else { /* No Pending SRB */
683 orc_release_scb(pHCB
, pSCB
); /* Release SCB for current channel */
688 /*****************************************************************************
689 Function name : inia100_biosparam
690 Description : Return the "logical geometry"
691 Input : pHCB - Pointer to host adapter structure
693 Return : pSRB - Pointer to SCSI request block.
694 *****************************************************************************/
695 int inia100_biosparam(Scsi_Disk
* disk
, kdev_t dev
, int *info_array
)
697 ORC_HCS
*pHcb
; /* Point to Host adapter control block */
700 pHcb
= (ORC_HCS
*) disk
->device
->host
->base
;
701 pTcb
= &pHcb
->HCS_Tcs
[disk
->device
->id
];
703 if (pTcb
->TCS_DrvHead
) {
704 info_array
[0] = pTcb
->TCS_DrvHead
;
705 info_array
[1] = pTcb
->TCS_DrvSector
;
706 info_array
[2] = disk
->capacity
/ pTcb
->TCS_DrvHead
/ pTcb
->TCS_DrvSector
;
708 if (pTcb
->TCS_DrvFlags
& TCF_DRV_255_63
) {
711 info_array
[2] = disk
->capacity
/ 255 / 63;
715 info_array
[2] = disk
->capacity
>> 11;
722 static void subIntr(ORC_HCS
* pHCB
, int irqno
)
726 spin_lock_irqsave(&io_request_lock
, flags
);
728 if (pHCB
->HCS_Intr
!= irqno
) {
729 spin_unlock_irqrestore(&io_request_lock
, flags
);
734 spin_unlock_irqrestore(&io_request_lock
, flags
);
738 * Interrupts handler (main routine of the driver)
740 static void inia100_intr0(int irqno
, void *dev_id
, struct pt_regs
*regs
)
742 subIntr(&orc_hcs
[0], irqno
);
745 static void inia100_intr1(int irqno
, void *dev_id
, struct pt_regs
*regs
)
747 subIntr(&orc_hcs
[1], irqno
);
750 static void inia100_intr2(int irqno
, void *dev_id
, struct pt_regs
*regs
)
752 subIntr(&orc_hcs
[2], irqno
);
755 static void inia100_intr3(int irqno
, void *dev_id
, struct pt_regs
*regs
)
757 subIntr(&orc_hcs
[3], irqno
);
760 static void inia100_intr4(int irqno
, void *dev_id
, struct pt_regs
*regs
)
762 subIntr(&orc_hcs
[4], irqno
);
765 static void inia100_intr5(int irqno
, void *dev_id
, struct pt_regs
*regs
)
767 subIntr(&orc_hcs
[5], irqno
);
770 static void inia100_intr6(int irqno
, void *dev_id
, struct pt_regs
*regs
)
772 subIntr(&orc_hcs
[6], irqno
);
775 static void inia100_intr7(int irqno
, void *dev_id
, struct pt_regs
*regs
)
777 subIntr(&orc_hcs
[7], irqno
);
781 * Dump the current driver status and panic...
783 static void inia100_panic(char *msg
)
785 printk("\ninia100_panic: %s\n", msg
);
786 panic("inia100 panic");
792 int inia100_release(struct Scsi_Host
*hreg
)
794 free_irq(hreg
->irq
, hreg
);
795 release_region(hreg
->io_port
, 256);
799 /*#include "inia100scsi.c" */