Pull fluff into release branch
[sfrench/cifs-2.6.git] / drivers / scsi / arm / ecoscsi.c
1 #define AUTOSENSE
2 /* #define PSEUDO_DMA */
3
4 /*
5  * EcoSCSI Generic NCR5380 driver
6  *
7  * Copyright 1995, Russell King
8  *
9  * ALPHA RELEASE 1.
10  *
11  * For more information, please consult
12  *
13  * NCR 5380 Family
14  * SCSI Protocol Controller
15  * Databook
16  *
17  * NCR Microelectronics
18  * 1635 Aeroplaza Drive
19  * Colorado Springs, CO 80916
20  * 1+ (719) 578-3400
21  * 1+ (800) 334-5454
22  */
23
24 #include <linux/module.h>
25 #include <linux/signal.h>
26 #include <linux/ioport.h>
27 #include <linux/delay.h>
28 #include <linux/init.h>
29 #include <linux/blkdev.h>
30
31 #include <asm/io.h>
32 #include <asm/system.h>
33
34 #include "../scsi.h"
35 #include <scsi/scsi_host.h>
36
37 #define NCR5380_implementation_fields   int port, ctrl
38 #define NCR5380_local_declare()         struct Scsi_Host *_instance
39 #define NCR5380_setup(instance)         _instance = instance
40
41 #define NCR5380_read(reg)               ecoscsi_read(_instance, reg)
42 #define NCR5380_write(reg, value)       ecoscsi_write(_instance, reg, value)
43
44 #define NCR5380_intr                    ecoscsi_intr
45 #define NCR5380_queue_command           ecoscsi_queue_command
46 #define NCR5380_proc_info               ecoscsi_proc_info
47
48 #include "../NCR5380.h"
49
50 #define ECOSCSI_PUBLIC_RELEASE 1
51
52 static char ecoscsi_read(struct Scsi_Host *instance, int reg)
53 {
54   int iobase = instance->io_port;
55   outb(reg | 8, iobase);
56   return inb(iobase + 1);
57 }
58
59 static void ecoscsi_write(struct Scsi_Host *instance, int reg, int value)
60 {
61   int iobase = instance->io_port;
62   outb(reg | 8, iobase);
63   outb(value, iobase + 1);
64 }
65
66 /*
67  * Function : ecoscsi_setup(char *str, int *ints)
68  *
69  * Purpose : LILO command line initialization of the overrides array,
70  *
71  * Inputs : str - unused, ints - array of integer parameters with ints[0]
72  *      equal to the number of ints.
73  *
74  */
75
76 void ecoscsi_setup(char *str, int *ints)
77 {
78 }
79
80 const char * ecoscsi_info (struct Scsi_Host *spnt)
81 {
82         return "";
83 }
84
85 #if 0
86 #define STAT(p) inw(p + 144)
87
88 static inline int NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr,
89               int len)
90 {
91   int iobase = host->io_port;
92 printk("writing %p len %d\n",addr, len);
93   if(!len) return -1;
94
95   while(1)
96   {
97     int status;
98     while(((status = STAT(iobase)) & 0x100)==0);
99   }
100 }
101
102 static inline int NCR5380_pread(struct Scsi_Host *host, unsigned char *addr,
103               int len)
104 {
105   int iobase = host->io_port;
106   int iobase2= host->io_port + 0x100;
107   unsigned char *start = addr;
108   int s;
109 printk("reading %p len %d\n",addr, len);
110   outb(inb(iobase + 128), iobase + 135);
111   while(len > 0)
112   {
113     int status,b,i, timeout;
114     timeout = 0x07FFFFFF;
115     while(((status = STAT(iobase)) & 0x100)==0)
116     {
117       timeout--;
118       if(status & 0x200 || !timeout)
119       {
120         printk("status = %p\n",status);
121         outb(0, iobase + 135);
122         return 1;
123       }
124     }
125     if(len >= 128)
126     {
127       for(i=0; i<64; i++)
128       {
129         b = inw(iobase + 136);
130         *addr++ = b;
131         *addr++ = b>>8;
132       }
133       len -= 128;
134     }
135     else
136     {
137       b = inw(iobase + 136);
138       *addr ++ = b;
139       len -= 1;
140       if(len)
141         *addr ++ = b>>8;
142       len -= 1;
143     }
144   }
145   outb(0, iobase + 135);
146   printk("first bytes = %02X %02X %02X %20X %02X %02X %02X\n",*start, start[1], start[2], start[3], start[4], start[5], start[6]);
147   return 1;
148 }
149 #endif
150 #undef STAT
151
152 #define BOARD_NORMAL    0
153 #define BOARD_NCR53C400 1
154
155 #include "../NCR5380.c"
156
157 static struct scsi_host_template ecoscsi_template =  {
158         .module         = THIS_MODULE,
159         .name           = "Serial Port EcoSCSI NCR5380",
160         .proc_name      = "ecoscsi",
161         .info           = ecoscsi_info,
162         .queuecommand   = ecoscsi_queue_command,
163         .eh_abort_handler       = NCR5380_abort,
164         .eh_bus_reset_handler   = NCR5380_bus_reset,
165         .can_queue      = 16,
166         .this_id        = 7,
167         .sg_tablesize   = SG_ALL,
168         .cmd_per_lun    = 2,
169         .use_clustering = DISABLE_CLUSTERING
170 };
171
172 static struct Scsi_Host *host;
173
174 static int __init ecoscsi_init(void)
175 {
176
177         host = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata));
178         if (!host)
179                 return 0;
180
181         host->io_port = 0x80ce8000;
182         host->n_io_port = 144;
183         host->irq = IRQ_NONE;
184
185         if (!(request_region(host->io_port, host->n_io_port, "ecoscsi")) )
186                 goto unregister_scsi;
187
188         ecoscsi_write(host, MODE_REG, 0x20);            /* Is it really SCSI? */
189         if (ecoscsi_read(host, MODE_REG) != 0x20) /* Write to a reg.    */
190                 goto release_reg;
191
192         ecoscsi_write(host, MODE_REG, 0x00 );           /* it back.           */
193         if (ecoscsi_read(host, MODE_REG) != 0x00)
194                 goto release_reg;
195
196         NCR5380_init(host, 0);
197
198         printk("scsi%d: at port 0x%08lx irqs disabled", host->host_no, host->io_port);
199         printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
200                 host->can_queue, host->cmd_per_lun, ECOSCSI_PUBLIC_RELEASE);
201         printk("\nscsi%d:", host->host_no);
202         NCR5380_print_options(host);
203         printk("\n");
204
205         scsi_add_host(host, NULL); /* XXX handle failure */
206         scsi_scan_host(host);
207         return 0;
208
209 release_reg:
210         release_region(host->io_port, host->n_io_port);
211 unregister_scsi:
212         scsi_host_put(host);
213         return -ENODEV;
214 }
215
216 static void __exit ecoscsi_exit(void)
217 {
218         scsi_remove_host(host);
219
220         if (shpnt->irq != IRQ_NONE)
221                 free_irq(shpnt->irq, NULL);
222         NCR5380_exit(host);
223         if (shpnt->io_port)
224                 release_region(shpnt->io_port, shpnt->n_io_port);
225
226         scsi_host_put(host);
227         return 0;
228 }
229
230 module_init(ecoscsi_init);
231 module_exit(ecoscsi_exit);
232
233 MODULE_AUTHOR("Russell King");
234 MODULE_DESCRIPTION("Econet-SCSI driver for Acorn machines");
235 MODULE_LICENSE("GPL");
236