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.2 1998/03/08 05:49:47 davem
39 * Revision 1.1 1998/02/23 02:45:24 davem
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>
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
));
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. */
121 ecoscsi_write( instance
, MODE_REG
, 0x00 ); /* it back. */
122 if (ecoscsi_read (instance
, MODE_REG
) != 0x00)
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");
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
);
154 release_region(instance
->io_port
, instance
->n_io_port
);
156 scsi_unregister(instance
);
160 int ecoscsi_release (struct Scsi_Host
*shpnt
)
162 if (shpnt
->irq
!= IRQ_NONE
)
163 free_irq (shpnt
->irq
, NULL
);
165 release_region (shpnt
->io_port
, shpnt
->n_io_port
);
169 const char * ecoscsi_info (struct Scsi_Host
*spnt
) {
174 #define STAT(p) inw(p + 144)
176 static inline int NCR5380_pwrite(struct Scsi_Host
*instance
, unsigned char *addr
,
179 int iobase
= instance
->io_port
;
180 printk("writing %p len %d\n",addr
, len
);
186 while(((status
= STAT(iobase
)) & 0x100)==0);
190 static inline int NCR5380_pread(struct Scsi_Host
*instance
, unsigned char *addr
,
193 int iobase
= instance
->io_port
;
194 int iobase2
= instance
->io_port
+ 0x100;
195 unsigned char *start
= addr
;
197 printk("reading %p len %d\n",addr
, len
);
198 outb(inb(iobase
+ 128), iobase
+ 135);
201 int status
,b
,i
, timeout
;
202 timeout
= 0x07FFFFFF;
203 while(((status
= STAT(iobase
)) & 0x100)==0)
206 if(status
& 0x200 || !timeout
)
208 printk("status = %p\n",status
);
209 outb(0, iobase
+ 135);
217 b
= inw(iobase
+ 136);
225 b
= inw(iobase
+ 136);
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]);
240 #define NCR5380_implementation_fields \
243 #define NCR5380_local_declare() \
244 struct Scsi_Host *_instance
246 #define NCR5380_setup(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
,
277 .sg_tablesize
= SG_ALL
,
279 .use_clustering
= DISABLE_CLUSTERING
282 static int __init
ecoscsi_init(void)
284 scsi_register_host(&ecoscsi_template
);
285 if (ecoscsi_template
.present
)
288 scsi_unregister_host(&ecoscsi_template
);
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");