Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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