5 * Generic Generic NCR5380 driver
7 * Copyright 1995, Russell King
11 * For more information, please consult
14 * SCSI Protocol Controller
17 * NCR Microelectronics
18 * 1635 Aeroplaza Drive
19 * Colorado Springs, CO 80916
28 * PARITY - enable parity checking. Not supported.
30 * SCSI2 - enable support for SCSI-II tagged queueing. Untested.
32 * USLEEP - enable support for devices that don't disconnect. Untested.
36 * $Log: cumana_1.c,v $
37 * Revision 1.1.1.1 2005/04/11 02:50:14 jack
40 * Revision 1.1.1.1 2005/01/10 13:16:15 jack
43 * Revision 1.3 1998/05/03 20:45:32 alan
44 * ARM SCSI update. This adds the eesox driver and massively updates the
45 * Cumana driver. The folks who bought cumana arent anal retentive all
46 * docs are secret weenies so now there are docs ..
48 * Revision 1.2 1998/03/08 05:49:46 davem
51 * Revision 1.1 1998/02/23 02:45:22 davem
56 #include <linux/module.h>
57 #include <linux/signal.h>
58 #include <linux/sched.h>
59 #include <linux/ioport.h>
60 #include <linux/blk.h>
61 #include <linux/init.h>
63 #include <asm/ecard.h>
66 #include <asm/system.h>
68 #include "../../scsi/scsi.h"
69 #include "../../scsi/hosts.h"
70 #include "../../scsi/constants.h"
72 #include <scsi/scsicam.h>
74 #define CUMANASCSI_PUBLIC_RELEASE 1
76 static const card_ids cumanascsi_cids[] = {
77 { MANU_CUMANA, PROD_CUMANA_SCSI_1 },
81 #define NCR5380_implementation_fields \
84 #define NCR5380_local_declare() \
85 struct Scsi_Host *_instance
87 #define NCR5380_setup(instance) \
90 #define NCR5380_read(reg) cumanascsi_read(_instance, reg)
91 #define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
93 #define do_NCR5380_intr do_cumanascsi_intr
94 #define NCR5380_queue_command cumanascsi_queue_command
95 #define NCR5380_abort cumanascsi_abort
96 #define NCR5380_reset cumanascsi_reset
97 #define NCR5380_proc_info cumanascsi_proc_info
99 int NCR5380_proc_info(char *buffer, char **start, off_t offset,
100 int length, int hostno, int inout);
102 #define BOARD_NORMAL 0
103 #define BOARD_NCR53C400 1
105 #include "../../scsi/NCR5380.h"
108 * Function : cumanascsi_setup(char *str, int *ints)
110 * Purpose : LILO command line initialization of the overrides array,
112 * Inputs : str - unused, ints - array of integer parameters with ints[0]
113 * equal to the number of ints.
117 void cumanascsi_setup(char *str, int *ints)
121 #define CUMANA_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800)
122 #define CUMANA_IRQ(card) ((card)->irq)
124 * Function : int cumanascsi_detect(Scsi_Host_Template * tpnt)
126 * Purpose : initializes cumana NCR5380 driver based on the
127 * command line / compile time port and irq definitions.
129 * Inputs : tpnt - template for this SCSI adapter.
131 * Returns : 1 if a host adapter was found, 0 if not.
134 static struct expansion_card *ecs[4];
136 int cumanascsi_detect(Scsi_Host_Template * tpnt)
139 struct Scsi_Host *instance;
141 tpnt->proc_name = "CumanaSCSI-1";
143 memset (ecs, 0, sizeof (ecs));
146 if((ecs[count] = ecard_find(0, cumanascsi_cids)) == NULL)
149 instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
150 instance->io_port = CUMANA_ADDRESS(ecs[count]);
151 instance->irq = CUMANA_IRQ(ecs[count]);
153 NCR5380_init(instance, 0);
154 ecard_claim(ecs[count]);
156 instance->n_io_port = 255;
157 request_region (instance->io_port, instance->n_io_port, "CumanaSCSI-1");
159 ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
160 outb(0x00, instance->io_port - 577);
162 if (instance->irq != IRQ_NONE)
163 if (request_irq(instance->irq, do_cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
164 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
165 instance->host_no, instance->irq);
166 instance->irq = IRQ_NONE;
169 if (instance->irq == IRQ_NONE) {
170 printk("scsi%d: interrupts not enabled. for better interactive performance,\n", instance->host_no);
171 printk("scsi%d: please jumper the board for a free IRQ.\n", instance->host_no);
174 printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
175 if (instance->irq == IRQ_NONE)
176 printk ("s disabled");
178 printk (" %d", instance->irq);
179 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
180 tpnt->can_queue, tpnt->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE);
181 printk("\nscsi%d:", instance->host_no);
182 NCR5380_print_options(instance);
190 int cumanascsi_release (struct Scsi_Host *shpnt)
194 if (shpnt->irq != IRQ_NONE)
195 free_irq (shpnt->irq, NULL);
197 release_region (shpnt->io_port, shpnt->n_io_port);
199 for (i = 0; i < 4; i++)
200 if (shpnt->io_port == CUMANA_ADDRESS(ecs[i]))
201 ecard_release (ecs[i]);
205 const char * cumanascsi_info (struct Scsi_Host *spnt) {
210 #define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
211 #define STAT(p) inb((p)+1)
212 #define IN(p) inb((p))
213 #define OUT(v,p) outb((v), (p))
215 #define CTRL(p,v) (p[-2308] = (*ctrl = (v)))
216 #define STAT(p) (p[4])
218 #define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p)))
219 #define OUT(v,p) (*(p) = (v))
220 #define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v))
222 #define L(v) (((v)<<16)|((v) & 0x0000ffff))
223 #define H(v) (((v)>>16)|((v) & 0xffff0000))
225 static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
228 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
230 unsigned long *laddr;
232 int iobase = instance->io_port;
233 int dma_io = iobase & ~(0x3C0000>>2);
235 volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
236 volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000);
242 laddr = (unsigned long *)addr;
247 status = STAT(iobase);
252 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
253 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
254 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
255 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
256 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
257 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
258 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
259 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
265 addr = (unsigned char *)laddr;
270 status = STAT(iobase);
275 OUT(*addr++, dma_io);
280 status = STAT(iobase);
285 OUT(*addr++, dma_io);
291 CTRL(iobase, oldctrl|0x40);
295 static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
298 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
300 unsigned long *laddr;
302 int iobase = instance->io_port;
303 int dma_io = iobase & ~(0x3C0000>>2);
305 volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
306 volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000);
312 laddr = (unsigned long *)addr;
316 status = STAT(iobase);
321 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
322 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
323 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
324 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
325 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
326 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
327 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
328 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
334 addr = (unsigned char *)laddr;
339 status = STAT(iobase);
344 *addr++ = IN(dma_io);
349 status = STAT(iobase);
354 *addr++ = IN(dma_io);
360 CTRL(iobase, oldctrl|0x40);
369 #define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
371 static char cumanascsi_read(struct Scsi_Host *instance, int reg)
373 int iobase = instance->io_port;
375 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
378 i = inb(iobase + 64 + reg);
384 static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value)
386 int iobase = instance->io_port;
387 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
390 outb(value, iobase + 64 + reg);
396 #include "../../scsi/NCR5380.c"
398 static Scsi_Host_Template cumanascsi_template = {
400 name: "Cumana 16-bit SCSI",
401 detect: cumanascsi_detect,
402 release: cumanascsi_release,
403 info: cumanascsi_info,
404 queuecommand: cumanascsi_queue_command,
405 abort: cumanascsi_abort,
406 reset: cumanascsi_reset,
407 bios_param: scsicam_bios_param,
410 sg_tablesize: SG_ALL,
412 unchecked_isa_dma: 0,
413 use_clustering: DISABLE_CLUSTERING
416 static int __init cumanascsi_init(void)
418 scsi_register_module(MODULE_SCSI_HA, &cumanascsi_template);
419 if (cumanascsi_template.present)
422 scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi_template);
426 static void __exit cumanascsi_exit(void)
428 scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi_template);
431 module_init(cumanascsi_init);
432 module_exit(cumanascsi_exit);
434 MODULE_LICENSE("GPL");