MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / scsi / inia100.c
blob3d1025e6c7fe1b95f1fb5e0d5d33eaf551a17fc4
1 /**************************************************************************
2 * Initio A100 device driver for Linux.
4 * Copyright (c) 1994-1998 Initio Corporation
5 * All rights reserved.
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.
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
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.
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.
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.
54 **************************************************************************
56 * module: inia100.c
57 * DESCRIPTION:
58 * This is the Linux low-level SCSI driver for Initio INIA100 SCSI host
59 * adapters
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 * 06/25/02 Doug Ledford <dledford@redhat.com> - v1.02d
63 * - Remove limit on number of controllers
64 * - Port to DMA mapping API
65 * - Clean up interrupt handler registration
66 * - Fix memory leaks
67 * - Fix allocation of scsi host structs and private data
68 * 18/11/03 Christoph Hellwig <hch@lst.de>
69 * - Port to new probing API
70 * - Fix some more leaks in init failure cases
71 * TODO:
72 * - use list.h macros for SCB queue
73 * ( - merge with i60uscsi.c )
74 **************************************************************************/
76 #include <linux/module.h>
77 #include <linux/errno.h>
78 #include <linux/delay.h>
79 #include <linux/interrupt.h>
80 #include <linux/pci.h>
81 #include <linux/init.h>
82 #include <linux/blkdev.h>
83 #include <linux/spinlock.h>
84 #include <linux/kernel.h>
85 #include <linux/string.h>
86 #include <linux/ioport.h>
87 #include <linux/slab.h>
88 #include <asm/io.h>
89 #include <asm/irq.h>
91 #include <scsi/scsi.h>
92 #include <scsi/scsi_cmnd.h>
93 #include <scsi/scsi_device.h>
94 #include <scsi/scsi_host.h>
96 #include "inia100.h"
98 #define ORC_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
100 char *inia100_Copyright = "Copyright (C) 1998-99";
101 char *inia100_InitioName = "by Initio Corporation";
102 char *inia100_ProductName = "INI-A100U2W";
103 char *inia100_Version = "v1.02d";
105 /* ---- EXTERNAL FUNCTIONS ---- */
106 extern void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
107 extern int init_inia100Adapter_table(int);
108 extern ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
109 extern void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp);
110 extern void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp);
111 extern void orc_release_dma(ORC_HCS * hcsp, struct scsi_cmnd * cmnd);
112 extern void orc_interrupt(ORC_HCS * hcsp);
113 extern int orc_device_reset(ORC_HCS * pHCB, struct scsi_cmnd *SCpnt, unsigned int target);
114 extern int orc_reset_scsi_bus(ORC_HCS * pHCB);
115 extern int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb);
116 extern int orc_abort_srb(ORC_HCS * hcsp, struct scsi_cmnd *SCpnt);
117 extern int init_orchid(ORC_HCS * hcsp);
119 /*****************************************************************************
120 Function name : inia100AppendSRBToQueue
121 Description : This function will push current request into save list
122 Input : pSRB - Pointer to SCSI request block.
123 pHCB - Pointer to host adapter structure
124 Output : None.
125 Return : None.
126 *****************************************************************************/
127 static void inia100AppendSRBToQueue(ORC_HCS * pHCB, struct scsi_cmnd * pSRB)
129 ULONG flags;
131 spin_lock_irqsave(&(pHCB->pSRB_lock), flags);
133 pSRB->SCp.ptr = NULL; /* Pointer to next */
134 if (pHCB->pSRB_head == NULL)
135 pHCB->pSRB_head = pSRB;
136 else
137 pHCB->pSRB_tail->SCp.ptr = (char *)pSRB; /* Pointer to next */
138 pHCB->pSRB_tail = pSRB;
139 spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags);
140 return;
143 /*****************************************************************************
144 Function name : inia100PopSRBFromQueue
145 Description : This function will pop current request from save list
146 Input : pHCB - Pointer to host adapter structure
147 Output : None.
148 Return : pSRB - Pointer to SCSI request block.
149 *****************************************************************************/
150 static struct scsi_cmnd *inia100PopSRBFromQueue(ORC_HCS * pHCB)
152 struct scsi_cmnd *pSRB;
153 ULONG flags;
154 spin_lock_irqsave(&(pHCB->pSRB_lock), flags);
155 if ((pSRB = (struct scsi_cmnd *) pHCB->pSRB_head) != NULL) {
156 pHCB->pSRB_head = (struct scsi_cmnd *) pHCB->pSRB_head->SCp.ptr;
157 pSRB->SCp.ptr = NULL;
159 spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags);
160 return (pSRB);
163 /*****************************************************************************
164 Function name : inia100BuildSCB
165 Description :
166 Input : pHCB - Pointer to host adapter structure
167 Output : None.
168 Return : pSRB - Pointer to SCSI request block.
169 *****************************************************************************/
170 static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, struct scsi_cmnd * SCpnt)
171 { /* Create corresponding SCB */
172 struct scatterlist *pSrbSG;
173 ORC_SG *pSG; /* Pointer to SG list */
174 int i, count_sg;
175 U32 TotalLen;
176 ESCB *pEScb;
178 pEScb = pSCB->SCB_EScb;
179 pEScb->SCB_Srb = SCpnt;
180 pSG = NULL;
182 pSCB->SCB_Opcode = ORC_EXECSCSI;
183 pSCB->SCB_Flags = SCF_NO_DCHK; /* Clear done bit */
184 pSCB->SCB_Target = SCpnt->device->id;
185 pSCB->SCB_Lun = SCpnt->device->lun;
186 pSCB->SCB_Reserved0 = 0;
187 pSCB->SCB_Reserved1 = 0;
188 pSCB->SCB_SGLen = 0;
190 if ((pSCB->SCB_XferLen = (U32) SCpnt->request_bufflen)) {
191 pSG = (ORC_SG *) & pEScb->ESCB_SGList[0];
192 if (SCpnt->use_sg) {
193 TotalLen = 0;
194 pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
195 count_sg = pci_map_sg(pHCB->pdev, pSrbSG, SCpnt->use_sg,
196 SCpnt->sc_data_direction);
197 pSCB->SCB_SGLen = (U32) (count_sg * 8);
198 for (i = 0; i < count_sg; i++, pSG++, pSrbSG++) {
199 pSG->SG_Ptr = (U32) sg_dma_address(pSrbSG);
200 pSG->SG_Len = (U32) sg_dma_len(pSrbSG);
201 TotalLen += (U32) sg_dma_len(pSrbSG);
203 } else if (SCpnt->request_bufflen != 0) {/* Non SG */
204 pSCB->SCB_SGLen = 0x8;
205 pSG->SG_Ptr = (U32) pci_map_single(pHCB->pdev,
206 SCpnt->request_buffer, SCpnt->request_bufflen,
207 SCpnt->sc_data_direction);
208 SCpnt->host_scribble = (void *)pSG->SG_Ptr;
209 pSG->SG_Len = (U32) SCpnt->request_bufflen;
210 } else {
211 pSCB->SCB_SGLen = 0;
212 pSG->SG_Ptr = 0;
213 pSG->SG_Len = 0;
216 pSCB->SCB_SGPAddr = (U32) pSCB->SCB_SensePAddr;
217 pSCB->SCB_HaStat = 0;
218 pSCB->SCB_TaStat = 0;
219 pSCB->SCB_Link = 0xFF;
220 pSCB->SCB_SenseLen = SENSE_SIZE;
221 pSCB->SCB_CDBLen = SCpnt->cmd_len;
222 if (pSCB->SCB_CDBLen >= IMAX_CDB) {
223 printk("max cdb length= %x\b", SCpnt->cmd_len);
224 pSCB->SCB_CDBLen = IMAX_CDB;
226 pSCB->SCB_Ident = SCpnt->device->lun | DISC_ALLOW;
227 if (SCpnt->device->tagged_supported) { /* Tag Support */
228 pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG; /* Do simple tag only */
229 } else {
230 pSCB->SCB_TagMsg = 0; /* No tag support */
232 memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, pSCB->SCB_CDBLen);
233 return;
236 /*****************************************************************************
237 Function name : inia100_queue
238 Description : Queue a command and setup interrupts for a free bus.
239 Input : pHCB - Pointer to host adapter structure
240 Output : None.
241 Return : pSRB - Pointer to SCSI request block.
242 *****************************************************************************/
243 static int inia100_queue(struct scsi_cmnd * SCpnt, void (*done) (struct scsi_cmnd *))
245 register ORC_SCB *pSCB;
246 ORC_HCS *pHCB; /* Point to Host adapter control block */
248 pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
249 SCpnt->scsi_done = done;
250 /* Get free SCSI control block */
251 if ((pSCB = orc_alloc_scb(pHCB)) == NULL) {
252 inia100AppendSRBToQueue(pHCB, SCpnt); /* Buffer this request */
253 /* printk("inia100_entry: can't allocate SCB\n"); */
254 return (0);
256 inia100BuildSCB(pHCB, pSCB, SCpnt);
257 orc_exec_scb(pHCB, pSCB); /* Start execute SCB */
259 return (0);
262 /*****************************************************************************
263 Function name : inia100_abort
264 Description : Abort a queued command.
265 (commands that are on the bus can't be aborted easily)
266 Input : pHCB - Pointer to host adapter structure
267 Output : None.
268 Return : pSRB - Pointer to SCSI request block.
269 *****************************************************************************/
270 static int inia100_abort(struct scsi_cmnd * SCpnt)
272 ORC_HCS *hcsp;
274 hcsp = (ORC_HCS *) SCpnt->device->host->hostdata;
275 return orc_abort_srb(hcsp, SCpnt);
278 /*****************************************************************************
279 Function name : inia100_reset
280 Description : Reset registers, reset a hanging bus and
281 kill active and disconnected commands for target w/o soft reset
282 Input : pHCB - Pointer to host adapter structure
283 Output : None.
284 Return : pSRB - Pointer to SCSI request block.
285 *****************************************************************************/
286 static int inia100_bus_reset(struct scsi_cmnd * SCpnt)
287 { /* I need Host Control Block Information */
288 ORC_HCS *pHCB;
289 pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
290 return orc_reset_scsi_bus(pHCB);
293 /*****************************************************************************
294 Function name : inia100_device_reset
295 Description : Reset the device
296 Input : pHCB - Pointer to host adapter structure
297 Output : None.
298 Return : pSRB - Pointer to SCSI request block.
299 *****************************************************************************/
300 static int inia100_device_reset(struct scsi_cmnd * SCpnt)
301 { /* I need Host Control Block Information */
302 ORC_HCS *pHCB;
303 pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;
304 return orc_device_reset(pHCB, SCpnt, SCpnt->device->id);
308 /*****************************************************************************
309 Function name : inia100SCBPost
310 Description : This is callback routine be called when orc finish one
311 SCSI command.
312 Input : pHCB - Pointer to host adapter control block.
313 pSCB - Pointer to SCSI control block.
314 Output : None.
315 Return : None.
316 *****************************************************************************/
317 void inia100SCBPost(BYTE * pHcb, BYTE * pScb)
319 struct scsi_cmnd *pSRB; /* Pointer to SCSI request block */
320 ORC_HCS *pHCB;
321 ORC_SCB *pSCB;
322 ESCB *pEScb;
324 pHCB = (ORC_HCS *) pHcb;
325 pSCB = (ORC_SCB *) pScb;
326 pEScb = pSCB->SCB_EScb;
327 if ((pSRB = (struct scsi_cmnd *) pEScb->SCB_Srb) == 0) {
328 printk("inia100SCBPost: SRB pointer is empty\n");
329 orc_release_scb(pHCB, pSCB); /* Release SCB for current channel */
330 return;
332 pEScb->SCB_Srb = NULL;
334 switch (pSCB->SCB_HaStat) {
335 case 0x0:
336 case 0xa: /* Linked command complete without error and linked normally */
337 case 0xb: /* Linked command complete without error interrupt generated */
338 pSCB->SCB_HaStat = 0;
339 break;
341 case 0x11: /* Selection time out-The initiator selection or target
342 reselection was not complete within the SCSI Time out period */
343 pSCB->SCB_HaStat = DID_TIME_OUT;
344 break;
346 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
347 phase sequence was requested by the target. The host adapter
348 will generate a SCSI Reset Condition, notifying the host with
349 a SCRD interrupt */
350 pSCB->SCB_HaStat = DID_RESET;
351 break;
353 case 0x1a: /* SCB Aborted. 07/21/98 */
354 pSCB->SCB_HaStat = DID_ABORT;
355 break;
357 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
358 than was allocated by the Data Length field or the sum of the
359 Scatter / Gather Data Length fields. */
360 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
361 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid. */
363 default:
364 printk("inia100: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);
365 pSCB->SCB_HaStat = DID_ERROR; /* Couldn't find any better */
366 break;
369 if (pSCB->SCB_TaStat == 2) { /* Check condition */
370 memcpy((unsigned char *) &pSRB->sense_buffer[0],
371 (unsigned char *) &pEScb->ESCB_SGList[0], SENSE_SIZE);
373 pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
374 orc_release_dma(pHCB, pSRB); /* release DMA before we call scsi_done */
375 pSRB->scsi_done(pSRB); /* Notify system DONE */
377 /* Find the next pending SRB */
378 if ((pSRB = inia100PopSRBFromQueue(pHCB)) != NULL) { /* Assume resend will success */
379 inia100BuildSCB(pHCB, pSCB, pSRB); /* Create corresponding SCB */
380 orc_exec_scb(pHCB, pSCB); /* Start execute SCB */
381 } else {
382 orc_release_scb(pHCB, pSCB); /* Release SCB for current channel */
384 return;
388 * Interrupt handler (main routine of the driver)
390 static irqreturn_t inia100_intr(int irqno, void *devid, struct pt_regs *regs)
392 struct Scsi_Host *host = (struct Scsi_Host *)devid;
393 ORC_HCS *pHcb = (ORC_HCS *)host->hostdata;
394 unsigned long flags;
396 spin_lock_irqsave(host->host_lock, flags);
397 orc_interrupt(pHcb);
398 spin_unlock_irqrestore(host->host_lock, flags);
400 return IRQ_HANDLED;
403 static struct scsi_host_template inia100_template = {
404 .proc_name = "inia100",
405 .name = inia100_REVID,
406 .queuecommand = inia100_queue,
407 .eh_abort_handler = inia100_abort,
408 .eh_bus_reset_handler = inia100_bus_reset,
409 .eh_device_reset_handler = inia100_device_reset,
410 .can_queue = 1,
411 .this_id = 1,
412 .sg_tablesize = SG_ALL,
413 .cmd_per_lun = 1,
414 .use_clustering = ENABLE_CLUSTERING,
417 static int __devinit inia100_probe_one(struct pci_dev *pdev,
418 const struct pci_device_id *id)
420 struct Scsi_Host *shost;
421 ORC_HCS *pHCB;
422 unsigned long port, bios;
423 int error = -ENODEV;
424 u32 sz;
425 unsigned long dBiosAdr;
426 char *pbBiosAdr;
428 if (pci_enable_device(pdev))
429 goto out;
430 if (pci_set_dma_mask(pdev, 0xffffffffULL)) {
431 printk(KERN_WARNING "Unable to set 32bit DMA "
432 "on inia100 adapter, ignoring.\n");
433 goto out_disable_device;
436 pci_set_master(pdev);
438 port = pci_resource_start(pdev, 0);
439 if (!request_region(port, 256, "inia100")) {
440 printk(KERN_WARNING "inia100: io port 0x%lx, is busy.\n", port);
441 goto out_disable_device;
444 /* <02> read from base address + 0x50 offset to get the bios balue. */
445 bios = ORC_RDWORD(port, 0x50);
448 shost = scsi_host_alloc(&inia100_template, sizeof(ORC_HCS));
449 if (!shost)
450 goto out_release_region;
452 pHCB = (ORC_HCS *)shost->hostdata;
453 pHCB->pdev = pdev;
454 pHCB->HCS_Base = port;
455 pHCB->HCS_BIOS = bios;
456 pHCB->pSRB_head = NULL; /* Initial SRB save queue */
457 pHCB->pSRB_tail = NULL; /* Initial SRB save queue */
458 pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */
459 pHCB->BitAllocFlagLock = SPIN_LOCK_UNLOCKED;
461 /* Get total memory needed for SCB */
462 sz = ORC_MAXQUEUE * sizeof(ORC_SCB);
463 pHCB->HCS_virScbArray = pci_alloc_consistent(pdev, sz,
464 &pHCB->HCS_physScbArray);
465 if (!pHCB->HCS_virScbArray) {
466 printk("inia100: SCB memory allocation error\n");
467 goto out_host_put;
469 memset(pHCB->HCS_virScbArray, 0, sz);
471 /* Get total memory needed for ESCB */
472 sz = ORC_MAXQUEUE * sizeof(ESCB);
473 pHCB->HCS_virEscbArray = pci_alloc_consistent(pdev, sz,
474 &pHCB->HCS_physEscbArray);
475 if (!pHCB->HCS_virEscbArray) {
476 printk("inia100: ESCB memory allocation error\n");
477 goto out_free_scb_array;
479 memset(pHCB->HCS_virEscbArray, 0, sz);
481 dBiosAdr = pHCB->HCS_BIOS;
482 dBiosAdr = (dBiosAdr << 4);
483 pbBiosAdr = phys_to_virt(dBiosAdr);
484 if (init_orchid(pHCB)) { /* Initialize orchid chip */
485 printk("inia100: initial orchid fail!!\n");
486 goto out_free_escb_array;
489 shost->io_port = pHCB->HCS_Base;
490 shost->n_io_port = 0xff;
491 shost->can_queue = ORC_MAXQUEUE;
492 shost->unique_id = shost->io_port;
493 shost->max_id = pHCB->HCS_MaxTar;
494 shost->max_lun = 16;
495 shost->irq = pHCB->HCS_Intr = pdev->irq;
496 shost->this_id = pHCB->HCS_SCSI_ID; /* Assign HCS index */
497 shost->sg_tablesize = TOTAL_SG_ENTRY;
499 /* Initial orc chip */
500 error = request_irq(pdev->irq, inia100_intr, SA_SHIRQ,
501 "inia100", shost);
502 if (error < 0) {
503 printk(KERN_WARNING "inia100: unable to get irq %d\n",
504 pdev->irq);
505 goto out_free_escb_array;
508 pci_set_drvdata(pdev, shost);
510 error = scsi_add_host(shost, &pdev->dev);
511 if (error)
512 goto out_free_irq;
514 scsi_scan_host(shost);
515 return 0;
517 out_free_irq:
518 free_irq(shost->irq, shost);
519 out_free_escb_array:
520 pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB),
521 pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray);
522 out_free_scb_array:
523 pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),
524 pHCB->HCS_virScbArray, pHCB->HCS_physScbArray);
525 out_host_put:
526 scsi_host_put(shost);
527 out_release_region:
528 release_region(port, 256);
529 out_disable_device:
530 pci_disable_device(pdev);
531 out:
532 return error;
535 static void __devexit inia100_remove_one(struct pci_dev *pdev)
537 struct Scsi_Host *shost = pci_get_drvdata(pdev);
538 ORC_HCS *pHCB = (ORC_HCS *)shost->hostdata;
540 scsi_remove_host(shost);
542 free_irq(shost->irq, shost);
543 pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB),
544 pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray);
545 pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),
546 pHCB->HCS_virScbArray, pHCB->HCS_physScbArray);
547 release_region(shost->io_port, 256);
549 scsi_host_put(shost);
552 static struct pci_device_id inia100_pci_tbl[] = {
553 {ORC_VENDOR_ID, ORC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
554 {0,}
556 MODULE_DEVICE_TABLE(pci, inia100_pci_tbl);
558 static struct pci_driver inia100_pci_driver = {
559 .name = "inia100",
560 .id_table = inia100_pci_tbl,
561 .probe = inia100_probe_one,
562 .remove = __devexit_p(inia100_remove_one),
565 static int __init inia100_init(void)
567 return pci_module_init(&inia100_pci_driver);
570 static void __exit inia100_exit(void)
572 pci_unregister_driver(&inia100_pci_driver);
575 MODULE_DESCRIPTION("Initio A100U2W SCSI driver");
576 MODULE_AUTHOR("Initio Corporation");
577 MODULE_LICENSE("Dual BSD/GPL");
579 module_init(inia100_init);
580 module_exit(inia100_exit);