2 /* #define PSEUDO_DMA */
5 * EcoSCSI 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.2 1998/03/08 05:49:47 davem
45 * Revision 1.1 1998/02/23 02:45:24 davem
50 #include <linux/module.h>
51 #include <linux/signal.h>
52 #include <linux/sched.h>
53 #include <linux/ioport.h>
54 #include <linux/init.h>
55 #include <linux/blk.h>
58 #include <asm/system.h>
60 #include "../../scsi/scsi.h"
61 #include "../../scsi/hosts.h"
62 #include "../../scsi/NCR5380.h"
63 #include "../../scsi/constants.h"
65 #define ECOSCSI_PUBLIC_RELEASE 1
67 static char ecoscsi_read(struct Scsi_Host *instance, int reg)
69 int iobase = instance->io_port;
70 outb(reg | 8, iobase);
71 return inb(iobase + 1);
74 static void ecoscsi_write(struct Scsi_Host *instance, int reg, int value)
76 int iobase = instance->io_port;
77 outb(reg | 8, iobase);
78 outb(value, iobase + 1);
82 * Function : ecoscsi_setup(char *str, int *ints)
84 * Purpose : LILO command line initialization of the overrides array,
86 * Inputs : str - unused, ints - array of integer parameters with ints[0]
87 * equal to the number of ints.
91 void ecoscsi_setup(char *str, int *ints) {
95 * Function : int ecoscsi_detect(Scsi_Host_Template * tpnt)
97 * Purpose : initializes ecoscsi NCR5380 driver based on the
98 * command line / compile time port and irq definitions.
100 * Inputs : tpnt - template for this SCSI adapter.
102 * Returns : 1 if a host adapter was found, 0 if not.
106 int ecoscsi_detect(Scsi_Host_Template * tpnt)
108 struct Scsi_Host *instance;
110 tpnt->proc_name = "ecoscsi";
112 instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
113 instance->io_port = 0x80ce8000;
114 instance->n_io_port = 144;
115 instance->irq = IRQ_NONE;
117 if (check_region (instance->io_port, instance->n_io_port)) {
118 scsi_unregister (instance);
122 ecoscsi_write (instance, MODE_REG, 0x20); /* Is it really SCSI? */
123 if (ecoscsi_read (instance, MODE_REG) != 0x20) { /* Write to a reg. */
124 scsi_unregister(instance);
125 return 0; /* and try to read */
127 ecoscsi_write( instance, MODE_REG, 0x00 ); /* it back. */
128 if (ecoscsi_read (instance, MODE_REG) != 0x00) {
129 scsi_unregister(instance);
133 NCR5380_init(instance, 0);
134 if (request_region (instance->io_port, instance->n_io_port, "ecoscsi") == NULL) {
135 scsi_unregister(instance);
139 if (instance->irq != IRQ_NONE)
140 if (request_irq(instance->irq, do_ecoscsi_intr, SA_INTERRUPT, "ecoscsi", NULL)) {
141 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
142 instance->host_no, instance->irq);
143 instance->irq = IRQ_NONE;
146 if (instance->irq != IRQ_NONE) {
147 printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
148 printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
151 printk("scsi%d: at port %X irq", instance->host_no, instance->io_port);
152 if (instance->irq == IRQ_NONE)
153 printk ("s disabled");
155 printk (" %d", instance->irq);
156 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
157 CAN_QUEUE, CMD_PER_LUN, ECOSCSI_PUBLIC_RELEASE);
158 printk("\nscsi%d:", instance->host_no);
159 NCR5380_print_options(instance);
164 int ecoscsi_release (struct Scsi_Host *shpnt)
166 if (shpnt->irq != IRQ_NONE)
167 free_irq (shpnt->irq, NULL);
169 release_region (shpnt->io_port, shpnt->n_io_port);
173 const char * ecoscsi_info (struct Scsi_Host *spnt) {
178 #define STAT(p) inw(p + 144)
180 static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
183 int iobase = instance->io_port;
184 printk("writing %p len %d\n",addr, len);
190 while(((status = STAT(iobase)) & 0x100)==0);
194 static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
197 int iobase = instance->io_port;
198 int iobase2= instance->io_port + 0x100;
199 unsigned char *start = addr;
201 printk("reading %p len %d\n",addr, len);
202 outb(inb(iobase + 128), iobase + 135);
205 int status,b,i, timeout;
206 timeout = 0x07FFFFFF;
207 while(((status = STAT(iobase)) & 0x100)==0)
210 if(status & 0x200 || !timeout)
212 printk("status = %p\n",status);
213 outb(0, iobase + 135);
221 b = inw(iobase + 136);
229 b = inw(iobase + 136);
237 outb(0, iobase + 135);
238 printk("first bytes = %02X %02X %02X %20X %02X %02X %02X\n",*start, start[1], start[2], start[3], start[4], start[5], start[6]);
244 #define NCR5380_implementation_fields \
247 #define NCR5380_local_declare() \
248 struct Scsi_Host *_instance
250 #define NCR5380_setup(instance) \
253 #define NCR5380_read(reg) ecoscsi_read(_instance, reg)
254 #define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value)
256 #define do_NCR5380_intr do_ecoscsi_intr
257 #define NCR5380_queue_command ecoscsi_queue_command
258 #define NCR5380_abort ecoscsi_abort
259 #define NCR5380_reset ecoscsi_reset
260 #define NCR5380_proc_info ecoscsi_proc_info
262 int NCR5380_proc_info(char *buffer, char **start, off_t offset,
263 int length, int hostno, int inout);
265 #define BOARD_NORMAL 0
266 #define BOARD_NCR53C400 1
268 #include "../../scsi/NCR5380.c"
270 static Scsi_Host_Template ecoscsi_template = {
272 name: "Serial Port EcoSCSI NCR5380",
273 detect: ecoscsi_detect,
274 release: ecoscsi_release,
276 queuecommand: ecoscsi_queue_command,
277 abort: ecoscsi_abort,
278 reset: ecoscsi_reset,
281 sg_tablesize: SG_ALL,
283 use_clustering: DISABLE_CLUSTERING
286 static int __init ecoscsi_init(void)
288 scsi_register_module(MODULE_SCSI_HA, &ecoscsi_template);
289 if (ecoscsi_template.present)
292 scsi_unregister_module(MODULE_SCSI_HA, &ecoscsi_template);
296 static void __exit ecoscsi_exit(void)
298 scsi_unregister_module(MODULE_SCSI_HA, &ecoscsi_template);
301 module_init(ecoscsi_init);
302 module_exit(ecoscsi_exit);
304 MODULE_AUTHOR("Russell King");
305 MODULE_DESCRIPTION("Econet-SCSI driver for Acorn machines");
306 MODULE_LICENSE("GPL");