Merge with Linux 2.5.48.
[linux-2.6/linux-mips.git] / drivers / acorn / scsi / ecoscsi.c
blobe1fe32536477ac85215de8dae5e060eeef16be7d
1 #define AUTOSENSE
2 /* #define PSEUDO_DMA */
4 /*
5 * EcoSCSI Generic NCR5380 driver
7 * Copyright 1995, Russell King
9 * ALPHA RELEASE 1.
11 * For more information, please consult
13 * NCR 5380 Family
14 * SCSI Protocol Controller
15 * Databook
17 * NCR Microelectronics
18 * 1635 Aeroplaza Drive
19 * Colorado Springs, CO 80916
20 * 1+ (719) 578-3400
21 * 1+ (800) 334-5454
25 * Options :
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.
35 * $Log: ecoscsi.c,v $
36 * Revision 1.2 1998/03/08 05:49:47 davem
37 * Merge to 2.1.89
39 * Revision 1.1 1998/02/23 02:45:24 davem
40 * Merge to 2.1.88
44 #include <linux/module.h>
45 #include <linux/signal.h>
46 #include <linux/sched.h>
47 #include <linux/ioport.h>
48 #include <linux/delay.h>
49 #include <linux/init.h>
50 #include <linux/blk.h>
52 #include <asm/io.h>
53 #include <asm/system.h>
55 #include "../../scsi/scsi.h"
56 #include "../../scsi/hosts.h"
57 #include "../../scsi/NCR5380.h"
59 #define ECOSCSI_PUBLIC_RELEASE 1
61 static char ecoscsi_read(struct Scsi_Host *instance, int reg)
63 int iobase = instance->io_port;
64 outb(reg | 8, iobase);
65 return inb(iobase + 1);
68 static void ecoscsi_write(struct Scsi_Host *instance, int reg, int value)
70 int iobase = instance->io_port;
71 outb(reg | 8, iobase);
72 outb(value, iobase + 1);
76 * Function : ecoscsi_setup(char *str, int *ints)
78 * Purpose : LILO command line initialization of the overrides array,
80 * Inputs : str - unused, ints - array of integer parameters with ints[0]
81 * equal to the number of ints.
85 void ecoscsi_setup(char *str, int *ints) {
89 * Function : int ecoscsi_detect(Scsi_Host_Template * tpnt)
91 * Purpose : initializes ecoscsi NCR5380 driver based on the
92 * command line / compile time port and irq definitions.
94 * Inputs : tpnt - template for this SCSI adapter.
96 * Returns : 1 if a host adapter was found, 0 if not.
100 int ecoscsi_detect(Scsi_Host_Template * tpnt)
102 struct Scsi_Host *instance;
104 tpnt->proc_name = "ecoscsi";
106 instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
107 if (!instance)
108 return 0;
110 instance->io_port = 0x80ce8000;
111 instance->n_io_port = 144;
112 instance->irq = IRQ_NONE;
114 if ( !(request_region(instance->io_port, instance->n_io_port, "ecoscsi")) )
115 goto unregister_scsi;
117 ecoscsi_write (instance, MODE_REG, 0x20); /* Is it really SCSI? */
118 if (ecoscsi_read (instance, MODE_REG) != 0x20) /* Write to a reg. */
119 goto release_reg;
121 ecoscsi_write( instance, MODE_REG, 0x00 ); /* it back. */
122 if (ecoscsi_read (instance, MODE_REG) != 0x00)
123 goto release_reg;
125 NCR5380_init(instance, 0);
127 if (instance->irq != IRQ_NONE) {
128 if (request_irq(instance->irq, do_ecoscsi_intr, SA_INTERRUPT, "ecoscsi", NULL)) {
129 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
130 instance->host_no, instance->irq);
131 instance->irq = IRQ_NONE;
135 if (instance->irq != IRQ_NONE) {
136 printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
137 printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
140 printk("scsi%d: at port %X irq", instance->host_no, instance->io_port);
141 if (instance->irq == IRQ_NONE)
142 printk ("s disabled");
143 else
144 printk (" %d", instance->irq);
145 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
146 CAN_QUEUE, CMD_PER_LUN, ECOSCSI_PUBLIC_RELEASE);
147 printk("\nscsi%d:", instance->host_no);
148 NCR5380_print_options(instance);
149 printk("\n");
151 return 1;
153 release_reg:
154 release_region(instance->io_port, instance->n_io_port);
155 unregister_scsi:
156 scsi_unregister(instance);
157 return 0
160 int ecoscsi_release (struct Scsi_Host *shpnt)
162 if (shpnt->irq != IRQ_NONE)
163 free_irq (shpnt->irq, NULL);
164 if (shpnt->io_port)
165 release_region (shpnt->io_port, shpnt->n_io_port);
166 return 0;
169 const char * ecoscsi_info (struct Scsi_Host *spnt) {
170 return "";
173 #if 0
174 #define STAT(p) inw(p + 144)
176 static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
177 int len)
179 int iobase = instance->io_port;
180 printk("writing %p len %d\n",addr, len);
181 if(!len) return -1;
183 while(1)
185 int status;
186 while(((status = STAT(iobase)) & 0x100)==0);
190 static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
191 int len)
193 int iobase = instance->io_port;
194 int iobase2= instance->io_port + 0x100;
195 unsigned char *start = addr;
196 int s;
197 printk("reading %p len %d\n",addr, len);
198 outb(inb(iobase + 128), iobase + 135);
199 while(len > 0)
201 int status,b,i, timeout;
202 timeout = 0x07FFFFFF;
203 while(((status = STAT(iobase)) & 0x100)==0)
205 timeout--;
206 if(status & 0x200 || !timeout)
208 printk("status = %p\n",status);
209 outb(0, iobase + 135);
210 return 1;
213 if(len >= 128)
215 for(i=0; i<64; i++)
217 b = inw(iobase + 136);
218 *addr++ = b;
219 *addr++ = b>>8;
221 len -= 128;
223 else
225 b = inw(iobase + 136);
226 *addr ++ = b;
227 len -= 1;
228 if(len)
229 *addr ++ = b>>8;
230 len -= 1;
233 outb(0, iobase + 135);
234 printk("first bytes = %02X %02X %02X %20X %02X %02X %02X\n",*start, start[1], start[2], start[3], start[4], start[5], start[6]);
235 return 1;
237 #endif
238 #undef STAT
240 #define NCR5380_implementation_fields \
241 int port, ctrl
243 #define NCR5380_local_declare() \
244 struct Scsi_Host *_instance
246 #define NCR5380_setup(instance) \
247 _instance = instance
249 #define NCR5380_read(reg) ecoscsi_read(_instance, reg)
250 #define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value)
252 #define NCR5380_intr ecoscsi_intr
253 #define NCR5380_queue_command ecoscsi_queue_command
254 #define NCR5380_proc_info ecoscsi_proc_info
256 int NCR5380_proc_info(char *buffer, char **start, off_t offset,
257 int length, int hostno, int inout);
259 #define BOARD_NORMAL 0
260 #define BOARD_NCR53C400 1
262 #include "../../scsi/NCR5380.c"
264 static Scsi_Host_Template ecoscsi_template = {
265 .module = THIS_MODULE,
266 .name = "Serial Port EcoSCSI NCR5380",
267 .detect = ecoscsi_detect,
268 .release = ecoscsi_release,
269 .info = ecoscsi_info,
270 .queuecommand = ecoscsi_queue_command,
271 .eh_abort_handler = NCR5380_abort,
272 .eh_device_reset_handler= NCR5380_device_reset,
273 .eh_bus_reset_handler = NCR5380_bus_reset,
274 .eh_host_reset_handler = NCR5380_host_reset,
275 .can_queue = 16,
276 .this_id = 7,
277 .sg_tablesize = SG_ALL,
278 .cmd_per_lun = 2,
279 .use_clustering = DISABLE_CLUSTERING
282 static int __init ecoscsi_init(void)
284 scsi_register_host(&ecoscsi_template);
285 if (ecoscsi_template.present)
286 return 0;
288 scsi_unregister_host(&ecoscsi_template);
289 return -ENODEV;
292 static void __exit ecoscsi_exit(void)
294 scsi_unregister_host(&ecoscsi_template);
297 module_init(ecoscsi_init);
298 module_exit(ecoscsi_exit);
300 MODULE_AUTHOR("Russell King");
301 MODULE_DESCRIPTION("Econet-SCSI driver for Acorn machines");
302 MODULE_LICENSE("GPL");