5 * Oak 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
27 * PARITY - enable parity checking. Not supported.
29 * SCSI2 - enable support for SCSI-II tagged queueing. Untested.
31 * USLEEP - enable support for devices that don't disconnect. Untested.
36 * Revision 1.1.1.1 2005/04/11 02:50:14 jack
39 * Revision 1.1.1.1 2005/01/10 13:16:15 jack
42 * Revision 1.3 1998/05/03 20:45:37 alan
43 * ARM SCSI update. This adds the eesox driver and massively updates the
44 * Cumana driver. The folks who bought cumana arent anal retentive all
45 * docs are secret weenies so now there are docs ..
47 * Revision 1.2 1998/03/08 05:49:48 davem
50 * Revision 1.1 1998/02/23 02:45:27 davem
55 #include <linux/module.h>
56 #include <linux/signal.h>
57 #include <linux/sched.h>
58 #include <linux/ioport.h>
59 #include <linux/blk.h>
60 #include <linux/init.h>
62 #include <asm/ecard.h>
64 #include <asm/system.h>
66 #include "../../scsi/scsi.h"
67 #include "../../scsi/hosts.h"
68 #include "../../scsi/constants.h"
70 #define OAKSCSI_PUBLIC_RELEASE 1
72 #define NCR5380_read(reg) oakscsi_read(_instance, reg)
73 #define NCR5380_write(reg, value) oakscsi_write(_instance, reg, value)
74 #define do_NCR5380_intr do_oakscsi_intr
75 #define NCR5380_queue_command oakscsi_queue_command
76 #define NCR5380_abort oakscsi_abort
77 #define NCR5380_reset oakscsi_reset
78 #define NCR5380_proc_info oakscsi_proc_info
80 int NCR5380_proc_info(char *buffer, char **start, off_t offset,
81 int length, int hostno, int inout);
83 #define NCR5380_implementation_fields \
86 #define NCR5380_local_declare() \
87 struct Scsi_Host *_instance
89 #define NCR5380_setup(instance) \
92 #define BOARD_NORMAL 0
93 #define BOARD_NCR53C400 1
95 #include "../../scsi/NCR5380.h"
97 #undef START_DMA_INITIATOR_RECEIVE_REG
98 #define START_DMA_INITIATOR_RECEIVE_REG (7 + 128)
100 static const card_ids oakscsi_cids[] = {
101 { MANU_OAK, PROD_OAK_SCSI },
105 #define OAK_ADDRESS(card) (ecard_address((card), ECARD_MEMC, 0))
106 #define OAK_IRQ(card) (IRQ_NONE)
108 * Function : int oakscsi_detect(Scsi_Host_Template * tpnt)
110 * Purpose : initializes oak NCR5380 driver based on the
111 * command line / compile time port and irq definitions.
113 * Inputs : tpnt - template for this SCSI adapter.
115 * Returns : 1 if a host adapter was found, 0 if not.
118 static struct expansion_card *ecs[4];
120 int oakscsi_detect(Scsi_Host_Template * tpnt)
123 struct Scsi_Host *instance;
125 tpnt->proc_name = "oakscsi";
127 memset (ecs, 0, sizeof (ecs));
132 if ((ecs[count] = ecard_find(0, oakscsi_cids)) == NULL)
135 instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
136 instance->io_port = OAK_ADDRESS(ecs[count]);
137 instance->irq = OAK_IRQ(ecs[count]);
139 NCR5380_init(instance, 0);
140 ecard_claim(ecs[count]);
142 instance->n_io_port = 255;
143 request_region (instance->io_port, instance->n_io_port, "Oak SCSI");
145 if (instance->irq != IRQ_NONE)
146 if (request_irq(instance->irq, do_oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
147 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
148 instance->host_no, instance->irq);
149 instance->irq = IRQ_NONE;
152 if (instance->irq != IRQ_NONE) {
153 printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
154 printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
157 printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
158 if (instance->irq == IRQ_NONE)
159 printk ("s disabled");
161 printk (" %d", instance->irq);
162 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
163 tpnt->can_queue, tpnt->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE);
164 printk("\nscsi%d:", instance->host_no);
165 NCR5380_print_options(instance);
172 printk("No oak scsi devices found\n");
177 int oakscsi_release (struct Scsi_Host *shpnt)
181 if (shpnt->irq != IRQ_NONE)
182 free_irq (shpnt->irq, NULL);
184 release_region (shpnt->io_port, shpnt->n_io_port);
186 for (i = 0; i < 4; i++)
187 if (shpnt->io_port == OAK_ADDRESS(ecs[i]))
188 ecard_release (ecs[i]);
192 const char * oakscsi_info (struct Scsi_Host *spnt) {
196 #define STAT(p) inw(p + 144)
197 extern void inswb(int from, void *to, int len);
199 static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
202 int iobase = instance->io_port;
203 printk("writing %p len %d\n",addr, len);
209 while(((status = STAT(iobase)) & 0x100)==0);
213 static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
216 int iobase = instance->io_port;
217 printk("reading %p len %d\n", addr, len);
223 timeout = 0x01FFFFFF;
225 while(((status = STAT(iobase)) & 0x100)==0)
228 if(status & 0x200 || !timeout)
230 printk("status = %08X\n",status);
236 inswb(iobase + 136, addr, 128);
242 b = (unsigned long) inw(iobase + 136);
253 #define oakscsi_read(instance,reg) (inb((instance)->io_port + (reg)))
254 #define oakscsi_write(instance,reg,val) (outb((val), (instance)->io_port + (reg)))
258 #include "../../scsi/NCR5380.c"
260 static Scsi_Host_Template oakscsi_template = {
262 proc_info: oakscsi_proc_info,
263 name: "Oak 16-bit SCSI",
264 detect: oakscsi_detect,
265 release: oakscsi_release,
267 queuecommand: oakscsi_queue_command,
268 abort: oakscsi_abort,
269 reset: oakscsi_reset,
272 sg_tablesize: SG_ALL,
274 use_clustering: DISABLE_CLUSTERING
277 static int __init oakscsi_init(void)
279 scsi_register_module(MODULE_SCSI_HA, &oakscsi_template);
280 if (oakscsi_template.present)
283 scsi_unregister_module(MODULE_SCSI_HA, &oakscsi_template);
287 static void __exit oakscsi_exit(void)
289 scsi_unregister_module(MODULE_SCSI_HA, &oakscsi_template);
292 module_init(oakscsi_init);
293 module_exit(oakscsi_exit);
295 MODULE_AUTHOR("Russell King");
296 MODULE_DESCRIPTION("Oak SCSI driver");
297 MODULE_LICENSE("GPL");