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.3 1998/05/03 20:45:32 alan
38 * ARM SCSI update. This adds the eesox driver and massively updates the
39 * Cumana driver. The folks who bought cumana arent anal retentive all
40 * docs are secret weenies so now there are docs ..
42 * Revision 1.2 1998/03/08 05:49:46 davem
45 * Revision 1.1 1998/02/23 02:45:22 davem
50 #include <linux/module.h>
51 #include <linux/signal.h>
52 #include <linux/sched.h>
53 #include <linux/ioport.h>
54 #include <linux/blk.h>
55 #include <linux/init.h>
57 #include <asm/ecard.h>
60 #include <asm/system.h>
62 #include "../../scsi/scsi.h"
63 #include "../../scsi/hosts.h"
64 #include "../../scsi/constants.h"
66 #include <scsi/scsicam.h>
68 #define CUMANASCSI_PUBLIC_RELEASE 1
70 static const card_ids cumanascsi_cids[] = {
71 { MANU_CUMANA, PROD_CUMANA_SCSI_1 },
75 #define NCR5380_implementation_fields \
78 #define NCR5380_local_declare() \
79 struct Scsi_Host *_instance
81 #define NCR5380_setup(instance) \
84 #define NCR5380_read(reg) cumanascsi_read(_instance, reg)
85 #define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
87 #define do_NCR5380_intr do_cumanascsi_intr
88 #define NCR5380_queue_command cumanascsi_queue_command
89 #define NCR5380_abort cumanascsi_abort
90 #define NCR5380_reset cumanascsi_reset
91 #define NCR5380_proc_info cumanascsi_proc_info
93 int NCR5380_proc_info(char *buffer, char **start, off_t offset,
94 int length, int hostno, int inout);
96 #define BOARD_NORMAL 0
97 #define BOARD_NCR53C400 1
99 #include "../../scsi/NCR5380.h"
102 * Function : cumanascsi_setup(char *str, int *ints)
104 * Purpose : LILO command line initialization of the overrides array,
106 * Inputs : str - unused, ints - array of integer parameters with ints[0]
107 * equal to the number of ints.
111 void cumanascsi_setup(char *str, int *ints)
115 #define CUMANA_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800)
116 #define CUMANA_IRQ(card) ((card)->irq)
118 * Function : int cumanascsi_detect(Scsi_Host_Template * tpnt)
120 * Purpose : initializes cumana NCR5380 driver based on the
121 * command line / compile time port and irq definitions.
123 * Inputs : tpnt - template for this SCSI adapter.
125 * Returns : 1 if a host adapter was found, 0 if not.
128 static struct expansion_card *ecs[4];
130 int cumanascsi_detect(Scsi_Host_Template * tpnt)
133 struct Scsi_Host *instance;
135 tpnt->proc_name = "CumanaSCSI-1";
137 memset (ecs, 0, sizeof (ecs));
140 if((ecs[count] = ecard_find(0, cumanascsi_cids)) == NULL)
143 instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
144 instance->io_port = CUMANA_ADDRESS(ecs[count]);
145 instance->irq = CUMANA_IRQ(ecs[count]);
147 NCR5380_init(instance, 0);
148 ecard_claim(ecs[count]);
150 instance->n_io_port = 255;
151 request_region (instance->io_port, instance->n_io_port, "CumanaSCSI-1");
153 ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
154 outb(0x00, instance->io_port - 577);
156 if (instance->irq != IRQ_NONE)
157 if (request_irq(instance->irq, do_cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
158 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
159 instance->host_no, instance->irq);
160 instance->irq = IRQ_NONE;
163 if (instance->irq == IRQ_NONE) {
164 printk("scsi%d: interrupts not enabled. for better interactive performance,\n", instance->host_no);
165 printk("scsi%d: please jumper the board for a free IRQ.\n", instance->host_no);
168 printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
169 if (instance->irq == IRQ_NONE)
170 printk ("s disabled");
172 printk (" %d", instance->irq);
173 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
174 tpnt->can_queue, tpnt->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE);
175 printk("\nscsi%d:", instance->host_no);
176 NCR5380_print_options(instance);
184 int cumanascsi_release (struct Scsi_Host *shpnt)
188 if (shpnt->irq != IRQ_NONE)
189 free_irq (shpnt->irq, NULL);
191 release_region (shpnt->io_port, shpnt->n_io_port);
193 for (i = 0; i < 4; i++)
194 if (shpnt->io_port == CUMANA_ADDRESS(ecs[i]))
195 ecard_release (ecs[i]);
199 const char * cumanascsi_info (struct Scsi_Host *spnt) {
204 #define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
205 #define STAT(p) inb((p)+1)
206 #define IN(p) inb((p))
207 #define OUT(v,p) outb((v), (p))
209 #define CTRL(p,v) (p[-2308] = (*ctrl = (v)))
210 #define STAT(p) (p[4])
212 #define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p)))
213 #define OUT(v,p) (*(p) = (v))
214 #define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v))
216 #define L(v) (((v)<<16)|((v) & 0x0000ffff))
217 #define H(v) (((v)>>16)|((v) & 0xffff0000))
219 static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
222 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
224 unsigned long *laddr;
226 int iobase = instance->io_port;
227 int dma_io = iobase & ~(0x3C0000>>2);
229 volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
230 volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000);
236 laddr = (unsigned long *)addr;
241 status = STAT(iobase);
246 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
247 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
248 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
249 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
250 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
251 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
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);
259 addr = (unsigned char *)laddr;
264 status = STAT(iobase);
269 OUT(*addr++, dma_io);
274 status = STAT(iobase);
279 OUT(*addr++, dma_io);
285 CTRL(iobase, oldctrl|0x40);
289 static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
292 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
294 unsigned long *laddr;
296 int iobase = instance->io_port;
297 int dma_io = iobase & ~(0x3C0000>>2);
299 volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
300 volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000);
306 laddr = (unsigned long *)addr;
310 status = STAT(iobase);
315 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
316 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
317 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
318 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
319 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
320 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
321 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
322 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
328 addr = (unsigned char *)laddr;
333 status = STAT(iobase);
338 *addr++ = IN(dma_io);
343 status = STAT(iobase);
348 *addr++ = IN(dma_io);
354 CTRL(iobase, oldctrl|0x40);
363 #define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
365 static char cumanascsi_read(struct Scsi_Host *instance, int reg)
367 int iobase = instance->io_port;
369 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
372 i = inb(iobase + 64 + reg);
378 static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value)
380 int iobase = instance->io_port;
381 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
384 outb(value, iobase + 64 + reg);
390 #include "../../scsi/NCR5380.c"
392 static Scsi_Host_Template cumanascsi_template = {
394 name: "Cumana 16-bit SCSI",
395 detect: cumanascsi_detect,
396 release: cumanascsi_release,
397 info: cumanascsi_info,
398 queuecommand: cumanascsi_queue_command,
399 abort: cumanascsi_abort,
400 reset: cumanascsi_reset,
401 bios_param: scsicam_bios_param,
404 sg_tablesize: SG_ALL,
406 unchecked_isa_dma: 0,
407 use_clustering: DISABLE_CLUSTERING
410 static int __init cumanascsi_init(void)
412 scsi_register_module(MODULE_SCSI_HA, &cumanascsi_template);
413 if (cumanascsi_template.present)
416 scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi_template);
420 static void __exit cumanascsi_exit(void)
422 scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi_template);
425 module_init(cumanascsi_init);
426 module_exit(cumanascsi_exit);
428 MODULE_LICENSE("GPL");