~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/block/xd.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * This file contains the driver for an XT hard disk controller
  3  * (at least the DTC 5150X) for Linux.
  4  *
  5  * Author: Pat Mackinlay, pat@it.com.au
  6  * Date: 29/09/92
  7  * 
  8  * Revised: 01/01/93, ...
  9  *
 10  * Ref: DTC 5150X Controller Specification (thanks to Kevin Fowler,
 11  *   kevinf@agora.rain.com)
 12  * Also thanks to: Salvador Abreu, Dave Thaler, Risto Kankkunen and
 13  *   Wim Van Dorst.
 14  *
 15  * Revised: 04/04/94 by Risto Kankkunen
 16  *   Moved the detection code from xd_init() to xd_geninit() as it needed
 17  *   interrupts enabled and Linus didn't want to enable them in that first
 18  *   phase. xd_geninit() is the place to do these kinds of things anyway,
 19  *   he says.
 20  *
 21  * Modularized: 04/10/96 by Todd Fries, tfries@umr.edu
 22  *
 23  * Revised: 13/12/97 by Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl
 24  *   Fixed some problems with disk initialization and module initiation.
 25  *   Added support for manual geometry setting (except Seagate controllers)
 26  *   in form:
 27  *      xd_geo=<cyl_xda>,<head_xda>,<sec_xda>[,<cyl_xdb>,<head_xdb>,<sec_xdb>]
 28  *   Recovered DMA access. Abridged messages. Added support for DTC5051CX,
 29  *   WD1002-27X & XEBEC controllers. Driver uses now some jumper settings.
 30  *   Extended ioctl() support.
 31  */
 32 
 33 #include <linux/module.h>
 34 #include <linux/errno.h>
 35 #include <linux/sched.h>
 36 #include <linux/mm.h>
 37 #include <linux/fs.h>
 38 #include <linux/kernel.h>
 39 #include <linux/timer.h>
 40 #include <linux/genhd.h>
 41 #include <linux/hdreg.h>
 42 #include <linux/ioport.h>
 43 #include <linux/init.h>
 44 #include <linux/devfs_fs_kernel.h>
 45 
 46 #include <asm/system.h>
 47 #include <asm/io.h>
 48 #include <asm/uaccess.h>
 49 #include <asm/dma.h>
 50 
 51 #define MAJOR_NR XT_DISK_MAJOR
 52 #include <linux/blk.h>
 53 #include <linux/blkpg.h>
 54 
 55 #include "xd.h"
 56 
 57 #define XD_DONT_USE_DMA         0  /* Initial value. may be overriden using
 58                                       "nodma" module option */
 59 #define XD_INIT_DISK_DELAY      (30*HZ/1000)  /* 30 ms delay during disk initialization */
 60 
 61 /* Above may need to be increased if a problem with the 2nd drive detection
 62    (ST11M controller) or resetting a controler (WD) appears */
 63 
 64 XD_INFO xd_info[XD_MAXDRIVES];
 65 
 66 /* If you try this driver and find that your card is not detected by the driver at bootup, you need to add your BIOS
 67    signature and details to the following list of signatures. A BIOS signature is a string embedded into the first
 68    few bytes of your controller's on-board ROM BIOS. To find out what yours is, use something like MS-DOS's DEBUG
 69    command. Run DEBUG, and then you can examine your BIOS signature with:
 70 
 71         d xxxx:0000
 72 
 73    where xxxx is the segment of your controller (like C800 or D000 or something). On the ASCII dump at the right, you should
 74    be able to see a string mentioning the manufacturer's copyright etc. Add this string into the table below. The parameters
 75    in the table are, in order:
 76 
 77         offset                  ; this is the offset (in bytes) from the start of your ROM where the signature starts
 78         signature               ; this is the actual text of the signature
 79         xd_?_init_controller    ; this is the controller init routine used by your controller
 80         xd_?_init_drive         ; this is the drive init routine used by your controller
 81 
 82    The controllers directly supported at the moment are: DTC 5150x, WD 1004A27X, ST11M/R and override. If your controller is
 83    made by the same manufacturer as one of these, try using the same init routines as they do. If that doesn't work, your
 84    best bet is to use the "override" routines. These routines use a "portable" method of getting the disk's geometry, and
 85    may work with your card. If none of these seem to work, try sending me some email and I'll see what I can do <grin>.
 86 
 87    NOTE: You can now specify your XT controller's parameters from the command line in the form xd=TYPE,IRQ,IO,DMA. The driver
 88    should be able to detect your drive's geometry from this info. (eg: xd=0,5,0x320,3 is the "standard"). */
 89 
 90 #include <asm/page.h>
 91 #define xd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size))
 92 #define xd_dma_mem_free(addr, size) free_pages(addr, get_order(size))
 93 static char *xd_dma_buffer = 0;
 94 
 95 static XD_SIGNATURE xd_sigs[] __initdata = {
 96         { 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, /* Pat Mackinlay, pat@it.com.au */
 97         { 0x0008,"[BXD06 (C) DTC 17-MAY-1985]",xd_dtc_init_controller,xd_dtc5150cx_init_drive," DTC 5150CX" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
 98         { 0x000B,"CRD18A   Not an IBM rom. (C) Copyright Data Technology Corp. 05/31/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Todd Fries, tfries@umr.edu */
 99         { 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Pat Mackinlay, pat@it.com.au */
100         { 0x0008,"07/15/86(C) Copyright 1986 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1002-27X" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
101         { 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */
102         { 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
103         { 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
104         { 0x0010,"ST11 BIOS v1.7",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11R" }, /* Alan Hourihane, alanh@fairlite.demon.co.uk */
105         { 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, /* Dirk Melchers, dirk@merlin.nbg.sub.org */
106         { 0x0006,"COPYRIGHT XEBEC (C) 1984",xd_xebec_init_controller,xd_xebec_init_drive," XEBEC" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
107 };
108 
109 static unsigned int xd_bases[] __initdata =
110 {
111         0xC8000, 0xCA000, 0xCC000,
112         0xCE000, 0xD0000, 0xD2000,
113         0xD4000, 0xD6000, 0xD8000,
114         0xDA000, 0xDC000, 0xDE000,
115         0xE0000
116 };
117 
118 static struct hd_struct xd_struct[XD_MAXDRIVES << 6];
119 static int xd_sizes[XD_MAXDRIVES << 6], xd_access[XD_MAXDRIVES];
120 static int xd_blocksizes[XD_MAXDRIVES << 6];
121 
122 extern struct block_device_operations xd_fops;
123 
124 static struct gendisk xd_gendisk = {
125         MAJOR_NR,       /* Major number */
126         "xd",           /* Major name */
127         6,              /* Bits to shift to get real from partition */
128         1 << 6,         /* Number of partitions per real */
129         xd_struct,      /* hd struct */
130         xd_sizes,       /* block sizes */
131         0,              /* number */
132         (void *) xd_info,       /* internal */
133         NULL,           /* next */
134         &xd_fops,       /* file operations */
135 };
136 static struct block_device_operations xd_fops = {
137         open:           xd_open,
138         release:        xd_release,
139         ioctl:          xd_ioctl,
140 };
141 static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
142 static DECLARE_WAIT_QUEUE_HEAD(xd_wait_open);
143 static u_char xd_valid[XD_MAXDRIVES] = { 0,0 };
144 static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors;
145 static u_char xd_override __initdata = 0, xd_type __initdata = 0;
146 static u_short xd_iobase = 0x320;
147 static int xd_geo[XD_MAXDRIVES*3] __initdata = { 0, };
148 
149 static volatile int xdc_busy;
150 static DECLARE_WAIT_QUEUE_HEAD(xdc_wait);
151 
152 static struct timer_list xd_timer, xd_watchdog_int;
153 
154 static volatile u_char xd_error;
155 static int nodma = XD_DONT_USE_DMA;
156 
157 static devfs_handle_t devfs_handle = NULL;
158 
159 /* xd_init: register the block device number and set up pointer tables */
160 int __init xd_init (void)
161 {
162         init_timer (&xd_timer); xd_timer.function = xd_wakeup;
163         init_timer (&xd_watchdog_int); xd_watchdog_int.function = xd_watchdog;
164 
165         if (devfs_register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
166                 printk("xd: Unable to get major number %d\n",MAJOR_NR);
167                 return -1;
168         }
169         devfs_handle = devfs_mk_dir (NULL, xd_gendisk.major_name, NULL);
170         blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
171         read_ahead[MAJOR_NR] = 8;       /* 8 sector (4kB) read ahead */
172         xd_gendisk.next = gendisk_head;
173         gendisk_head = &xd_gendisk;
174         xd_geninit();
175 
176         return 0;
177 }
178 
179 /* xd_detect: scan the possible BIOS ROM locations for the signature strings */
180 static u_char __init xd_detect (u_char *controller, unsigned int *address)
181 {
182         u_char i,j,found = 0;
183 
184         if (xd_override)
185         {
186                 *controller = xd_type;
187                 *address = 0;
188                 return(1);
189         }
190 
191         for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])) && !found; i++)
192                 for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])) && !found; j++)
193                         if (isa_check_signature(xd_bases[i] + xd_sigs[j].offset,xd_sigs[j].string,strlen(xd_sigs[j].string))) {
194                                 *controller = j;
195                                 xd_type = j;
196                                 *address = xd_bases[i];
197                                 found++;
198                         }
199         return (found);
200 }
201 
202 /* xd_geninit: grab the IRQ and DMA channel, initialise the drives */
203 /* and set up the "raw" device entries in the table */
204 static void __init xd_geninit (void)
205 {
206         u_char i,controller;
207         unsigned int address;
208 
209         for(i=0;i<(XD_MAXDRIVES << 6);i++) xd_blocksizes[i] = 1024;
210         blksize_size[MAJOR_NR] = xd_blocksizes;
211 
212         if (xd_detect(&controller,&address)) {
213 
214                 printk("Detected a%s controller (type %d) at address %06x\n",
215                         xd_sigs[controller].name,controller,address);
216                 if (check_region(xd_iobase,4)) {
217                         printk("xd: Ports at 0x%x are not available\n",
218                                 xd_iobase);
219                         return;
220                 }
221                 request_region(xd_iobase,4,"xd");
222                 if (controller)
223                         xd_sigs[controller].init_controller(address);
224                 xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
225                 
226                 printk("Detected %d hard drive%s (using IRQ%d & DMA%d)\n",
227                         xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
228                 for (i = 0; i < xd_drives; i++)
229                         printk(" xd%c: CHS=%d/%d/%d\n",'a'+i,
230                                 xd_info[i].cylinders,xd_info[i].heads,
231                                 xd_info[i].sectors);
232 
233         }
234         if (xd_drives) {
235                 if (!request_irq(xd_irq,xd_interrupt_handler, 0, "XT hard disk", NULL)) {
236                         if (request_dma(xd_dma,"xd")) {
237                                 printk("xd: unable to get DMA%d\n",xd_dma);
238                                 free_irq(xd_irq, NULL);
239                         }
240                 }
241                 else
242                         printk("xd: unable to get IRQ%d\n",xd_irq);
243         }
244 
245         for (i = 0; i < xd_drives; i++) {
246                 xd_valid[i] = 1;
247                 register_disk(&xd_gendisk, MKDEV(MAJOR_NR,i<<6), 1<<6, &xd_fops,
248                                 xd_info[i].heads * xd_info[i].cylinders *
249                                 xd_info[i].sectors);
250         }
251 
252         xd_gendisk.nr_real = xd_drives;
253 
254 }
255 
256 /* xd_open: open a device */
257 static int xd_open (struct inode *inode,struct file *file)
258 {
259         int dev = DEVICE_NR(inode->i_rdev);
260 
261         MOD_INC_USE_COUNT;
262 
263         if (dev < xd_drives) {
264                 while (!xd_valid[dev])
265                         sleep_on(&xd_wait_open);
266 
267                 xd_access[dev]++;
268 
269                 return (0);
270         }
271 
272         MOD_DEC_USE_COUNT;
273         return -ENXIO;
274 }
275 
276 /* do_xd_request: handle an incoming request */
277 static void do_xd_request (request_queue_t * q)
278 {
279         u_int block,count,retry;
280         int code;
281 
282         sti();
283         if (xdc_busy)
284                 return;
285         while (code = 0, !QUEUE_EMPTY) {
286                 INIT_REQUEST;   /* do some checking on the request structure */
287 
288                 if (CURRENT_DEV < xd_drives
289                     && CURRENT->sector + CURRENT->nr_sectors
290                          <= xd_struct[MINOR(CURRENT->rq_dev)].nr_sects) {
291                         block = CURRENT->sector + xd_struct[MINOR(CURRENT->rq_dev)].start_sect;
292                         count = CURRENT->nr_sectors;
293 
294                         switch (CURRENT->cmd) {
295                                 case READ:
296                                 case WRITE:
297                                         for (retry = 0; (retry < XD_RETRIES) && !code; retry++)
298                                                 code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count);
299                                         break;
300                                 default:
301                                         printk("do_xd_request: unknown request\n");
302                                         break;
303                         }
304                 }
305                 end_request(code);      /* wrap up, 0 = fail, 1 = success */
306         }
307 }
308 
309 /* xd_ioctl: handle device ioctl's */
310 static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
311 {
312         int dev;
313 
314         if ((!inode) || !(inode->i_rdev))
315                 return -EINVAL;
316         dev = DEVICE_NR(inode->i_rdev);
317 
318         if (dev >= xd_drives) return -EINVAL;
319         switch (cmd) {
320                 case HDIO_GETGEO:
321                 {
322                         struct hd_geometry g;
323                         struct hd_geometry *geometry = (struct hd_geometry *) arg;
324                         if (!geometry) return -EINVAL;
325                         g.heads = xd_info[dev].heads;
326                         g.sectors = xd_info[dev].sectors;
327                         g.cylinders = xd_info[dev].cylinders;
328                         g.start = xd_struct[MINOR(inode->i_rdev)].start_sect;
329                         return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0;
330                 }
331                 case BLKGETSIZE:
332                         if (!arg) return -EINVAL;
333                         return put_user(xd_struct[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
334                 case HDIO_SET_DMA:
335                         if (!capable(CAP_SYS_ADMIN)) return -EACCES;
336                         if (xdc_busy) return -EBUSY;
337                         nodma = !arg;
338                         if (nodma && xd_dma_buffer) {
339                                 xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200);
340                                 xd_dma_buffer = 0;
341                         }
342                         return 0;
343                 case HDIO_GET_DMA:
344                         return put_user(!nodma, (long *) arg);
345                 case HDIO_GET_MULTCOUNT:
346                         return put_user(xd_maxsectors, (long *) arg);
347                 case BLKRRPART:
348                         if (!capable(CAP_SYS_ADMIN)) 
349                                 return -EACCES;
350                         return xd_reread_partitions(inode->i_rdev);
351 
352                 case BLKFLSBUF:
353                 case BLKROSET:
354                 case BLKROGET:
355                 case BLKRASET:
356                 case BLKRAGET:
357                 case BLKPG:
358                         return blk_ioctl(inode->i_rdev, cmd, arg);
359 
360                 default:
361                         return -EINVAL;
362         }
363 }
364 
365 /* xd_release: release the device */
366 static int xd_release (struct inode *inode, struct file *file)
367 {
368         int target = DEVICE_NR(inode->i_rdev);
369         if (target < xd_drives) {
370                 xd_access[target]--;
371 #ifdef MODULE
372                 MOD_DEC_USE_COUNT;
373 #endif /* MODULE */
374         }
375         return 0;
376 }
377 
378 /* xd_reread_partitions: rereads the partition table from a drive */
379 static int xd_reread_partitions(kdev_t dev)
380 {
381         int target;
382         int start;
383         int partition;
384         
385         target = DEVICE_NR(dev);
386         start = target << xd_gendisk.minor_shift;
387 
388         cli();
389         xd_valid[target] = (xd_access[target] != 1);
390         sti();
391         if (xd_valid[target])
392                 return -EBUSY;
393 
394         for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
395                 int minor = (start | partition);
396                 kdev_t devp = MKDEV(MAJOR_NR, minor);
397                 struct super_block * sb = get_super(devp);
398                 
399                 sync_dev(devp);
400                 if (sb)
401                         invalidate_inodes(sb);
402                 invalidate_buffers(devp);
403                 xd_gendisk.part[minor].start_sect = 0;
404                 xd_gendisk.part[minor].nr_sects = 0;
405         };
406 
407         grok_partitions(&xd_gendisk, target, 1<<6,
408                         xd_info[target].heads * xd_info[target].cylinders * xd_info[target].sectors);
409 
410         xd_valid[target] = 1;
411         wake_up(&xd_wait_open);
412 
413         return 0;
414 }
415 
416 /* xd_readwrite: handle a read/write request */
417 static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block,u_int count)
418 {
419         u_char cmdblk[6],sense[4];
420         u_short track,cylinder;
421         u_char head,sector,control,mode = PIO_MODE,temp;
422         char **real_buffer;
423         register int i;
424         
425 #ifdef DEBUG_READWRITE
426         printk("xd_readwrite: operation = %s, drive = %d, buffer = 0x%X, block = %d, count = %d\n",operation == READ ? "read" : "write",drive,buffer,block,count);
427 #endif /* DEBUG_READWRITE */
428 
429         control = xd_info[drive].control;
430         if (!xd_dma_buffer)
431                 xd_dma_buffer = (char *)xd_dma_mem_alloc(xd_maxsectors * 0x200);
432         while (count) {
433                 temp = count < xd_maxsectors ? count : xd_maxsectors;
434 
435                 track = block / xd_info[drive].sectors;
436                 head = track % xd_info[drive].heads;
437                 cylinder = track / xd_info[drive].heads;
438                 sector = block % xd_info[drive].sectors;
439 
440 #ifdef DEBUG_READWRITE
441                 printk("xd_readwrite: drive = %d, head = %d, cylinder = %d, sector = %d, count = %d\n",drive,head,cylinder,sector,temp);
442 #endif /* DEBUG_READWRITE */
443 
444                 if (xd_dma_buffer) {
445                         mode = xd_setup_dma(operation == READ ? DMA_MODE_READ : DMA_MODE_WRITE,(u_char *)(xd_dma_buffer),temp * 0x200);
446                         real_buffer = &xd_dma_buffer;
447                         for (i=0; i < (temp * 0x200); i++)
448                                 xd_dma_buffer[i] = buffer[i];
449                 }
450                 else
451                         real_buffer = &buffer;
452 
453                 xd_build(cmdblk,operation == READ ? CMD_READ : CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control);
454 
455                 switch (xd_command(cmdblk,mode,(u_char *)(*real_buffer),(u_char *)(*real_buffer),sense,XD_TIMEOUT)) {
456                         case 1:
457                                 printk("xd%c: %s timeout, recalibrating drive\n",'a'+drive,(operation == READ ? "read" : "write"));
458                                 xd_recalibrate(drive);
459                                 return (0);
460                         case 2:
461                                 if (sense[0] & 0x30) {
462                                         printk("xd%c: %s - ",'a'+drive,(operation == READ ? "reading" : "writing"));
463                                         switch ((sense[0] & 0x30) >> 4) {
464                                         case 0: printk("drive error, code = 0x%X",sense[0] & 0x0F);
465                                                 break;
466                                         case 1: printk("controller error, code = 0x%X",sense[0] & 0x0F);
467                                                 break;
468                                         case 2: printk("command error, code = 0x%X",sense[0] & 0x0F);
469                                                 break;
470                                         case 3: printk("miscellaneous error, code = 0x%X",sense[0] & 0x0F);
471                                                 break;
472                                         }
473                                 }
474                                 if (sense[0] & 0x80)
475                                         printk(" - CHS = %d/%d/%d\n",((sense[2] & 0xC0) << 2) | sense[3],sense[1] & 0x1F,sense[2] & 0x3F);
476                                 /*      reported drive number = (sense[1] & 0xE0) >> 5 */
477                                 else
478                                         printk(" - no valid disk address\n");
479                                 return (0);
480                 }
481                 if (xd_dma_buffer)
482                         for (i=0; i < (temp * 0x200); i++)
483                                 buffer[i] = xd_dma_buffer[i];
484 
485                 count -= temp, buffer += temp * 0x200, block += temp;
486         }
487         return (1);
488 }
489 
490 /* xd_recalibrate: recalibrate a given drive and reset controller if necessary */
491 static void xd_recalibrate (u_char drive)
492 {
493         u_char cmdblk[6];
494         
495         xd_build(cmdblk,CMD_RECALIBRATE,drive,0,0,0,0,0);
496         if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8))
497                 printk("xd%c: warning! error recalibrating, controller may be unstable\n", 'a'+drive);
498 }
499 
500 /* xd_interrupt_handler: interrupt service routine */
501 static void xd_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs)
502 {
503         if (inb(XD_STATUS) & STAT_INTERRUPT) {                                                  /* check if it was our device */
504 #ifdef DEBUG_OTHER
505                 printk("xd_interrupt_handler: interrupt detected\n");
506 #endif /* DEBUG_OTHER */
507                 outb(0,XD_CONTROL);                                                             /* acknowledge interrupt */
508                 wake_up(&xd_wait_int);                                                          /* and wake up sleeping processes */
509         }
510         else
511                 printk("xd: unexpected interrupt\n");
512 }
513 
514 /* xd_setup_dma: set up the DMA controller for a data transfer */
515 static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count)
516 {
517         unsigned long f;
518         
519         if (nodma)
520                 return (PIO_MODE);
521         if (((unsigned long) buffer & 0xFFFF0000) != (((unsigned long) buffer + count) & 0xFFFF0000)) {
522 #ifdef DEBUG_OTHER
523                 printk("xd_setup_dma: using PIO, transfer overlaps 64k boundary\n");
524 #endif /* DEBUG_OTHER */
525                 return (PIO_MODE);
526         }
527         
528         f=claim_dma_lock();
529         disable_dma(xd_dma);
530         clear_dma_ff(xd_dma);
531         set_dma_mode(xd_dma,mode);
532         set_dma_addr(xd_dma, (unsigned long) buffer);
533         set_dma_count(xd_dma,count);
534         
535         release_dma_lock(f);
536 
537         return (DMA_MODE);                      /* use DMA and INT */
538 }
539 
540 /* xd_build: put stuff into an array in a format suitable for the controller */
541 static u_char *xd_build (u_char *cmdblk,u_char command,u_char drive,u_char head,u_short cylinder,u_char sector,u_char count,u_char control)
542 {
543         cmdblk[0] = command;
544         cmdblk[1] = ((drive & 0x07) << 5) | (head & 0x1F);
545         cmdblk[2] = ((cylinder & 0x300) >> 2) | (sector & 0x3F);
546         cmdblk[3] = cylinder & 0xFF;
547         cmdblk[4] = count;
548         cmdblk[5] = control;
549         
550         return (cmdblk);
551 }
552 
553 /* xd_wakeup is called from timer interrupt */
554 static void xd_wakeup (unsigned long unused)
555 {
556         wake_up(&xdc_wait);
557 }
558 
559 /* xd_wakeup is called from timer interrupt */
560 static void xd_watchdog (unsigned long unused)
561 {
562         xd_error = 1;
563         wake_up(&xd_wait_int);
564 }
565 
566 /* xd_waitport: waits until port & mask == flags or a timeout occurs. return 1 for a timeout */
567 static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long timeout)
568 {
569         u_long expiry = jiffies + timeout;
570         int success;
571 
572         xdc_busy = 1;
573         while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry)) {
574                 xd_timer.expires = jiffies;
575                 cli();
576                 add_timer(&xd_timer);
577                 sleep_on(&xdc_wait);
578                 del_timer(&xd_timer);
579                 sti();
580         }
581         xdc_busy = 0;
582         return (success);
583 }
584 
585 static inline u_int xd_wait_for_IRQ (void)
586 {
587         unsigned long flags;
588         xd_watchdog_int.expires = jiffies + 8 * HZ;
589         add_timer(&xd_watchdog_int);
590         
591         flags=claim_dma_lock();
592         enable_dma(xd_dma);
593         release_dma_lock(flags);
594         
595         sleep_on(&xd_wait_int);
596         del_timer(&xd_watchdog_int);
597         xdc_busy = 0;
598         
599         flags=claim_dma_lock();
600         disable_dma(xd_dma);
601         release_dma_lock(flags);
602         
603         if (xd_error) {
604                 printk("xd: missed IRQ - command aborted\n");
605                 xd_error = 0;
606                 return (1);
607         }
608         return (0);
609 }
610 
611 /* xd_command: handle all data transfers necessary for a single command */
612 static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outdata,u_char *sense,u_long timeout)
613 {
614         u_char cmdblk[6],csb,complete = 0;
615 
616 #ifdef DEBUG_COMMAND
617         printk("xd_command: command = 0x%X, mode = 0x%X, indata = 0x%X, outdata = 0x%X, sense = 0x%X\n",command,mode,indata,outdata,sense);
618 #endif /* DEBUG_COMMAND */
619 
620         outb(0,XD_SELECT);
621         outb(mode,XD_CONTROL);
622 
623         if (xd_waitport(XD_STATUS,STAT_SELECT,STAT_SELECT,timeout))
624                 return (1);
625 
626         while (!complete) {
627                 if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout))
628                         return (1);
629 
630                 switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) {
631                         case 0:
632                                 if (mode == DMA_MODE) {
633                                         if (xd_wait_for_IRQ())
634                                                 return (1);
635                                 } else
636                                         outb(outdata ? *outdata++ : 0,XD_DATA);
637                                 break;
638                         case STAT_INPUT:
639                                 if (mode == DMA_MODE) {
640                                         if (xd_wait_for_IRQ())
641                                                 return (1);
642                                 } else
643                                         if (indata)
644                                                 *indata++ = inb(XD_DATA);
645                                         else
646                                                 inb(XD_DATA);
647                                 break;
648                         case STAT_COMMAND:
649                                 outb(command ? *command++ : 0,XD_DATA);
650                                 break;
651                         case STAT_COMMAND | STAT_INPUT:
652                                 complete = 1;
653                                 break;
654                 }
655         }
656         csb = inb(XD_DATA);
657 
658         if (xd_waitport(XD_STATUS,0,STAT_SELECT,timeout))                                       /* wait until deselected */
659                 return (1);
660 
661         if (csb & CSB_ERROR) {                                                                  /* read sense data if error */
662                 xd_build(cmdblk,CMD_SENSE,(csb & CSB_LUN) >> 5,0,0,0,0,0);
663                 if (xd_command(cmdblk,0,sense,0,0,XD_TIMEOUT))
664                         printk("xd: warning! sense command failed!\n");
665         }
666 
667 #ifdef DEBUG_COMMAND
668         printk("xd_command: completed with csb = 0x%X\n",csb);
669 #endif /* DEBUG_COMMAND */
670 
671         return (csb & CSB_ERROR);
672 }
673 
674 static u_char __init xd_initdrives (void (*init_drive)(u_char drive))
675 {
676         u_char cmdblk[6],i,count = 0;
677 
678         for (i = 0; i < XD_MAXDRIVES; i++) {
679                 xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
680                 if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8)) {
681                         xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
682                         add_timer(&xd_timer);
683                         sleep_on(&xdc_wait);
684 
685                         init_drive(count);
686                         count++;
687 
688                         xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
689                         add_timer(&xd_timer);
690                         sleep_on(&xdc_wait);
691                 }
692         }
693         return (count);
694 }
695 
696 static void __init xd_manual_geo_set (u_char drive)
697 {
698         xd_info[drive].heads = (u_char)(xd_geo[3 * drive + 1]);
699         xd_info[drive].cylinders = (u_short)(xd_geo[3 * drive]);
700         xd_info[drive].sectors = (u_char)(xd_geo[3 * drive + 2]);
701 }
702 
703 static void __init xd_dtc_init_controller (unsigned int address)
704 {
705         switch (address) {
706                 case 0x00000:
707                 case 0xC8000:   break;                  /*initial: 0x320 */
708                 case 0xCA000:   xd_iobase = 0x324; 
709                 case 0xD0000:                           /*5150CX*/
710                 case 0xD8000:   break;                  /*5150CX & 5150XL*/
711                 default:        printk("xd_dtc_init_controller: unsupported BIOS address %06x\n",address);
712                                 break;
713         }
714         xd_maxsectors = 0x01;           /* my card seems to have trouble doing multi-block transfers? */
715 
716         outb(0,XD_RESET);               /* reset the controller */
717 }
718 
719 
720 static void __init xd_dtc5150cx_init_drive (u_char drive)
721 {
722         /* values from controller's BIOS - BIOS chip may be removed */
723         static u_short geometry_table[][4] = {
724                 {0x200,8,0x200,0x100},
725                 {0x267,2,0x267,0x267},
726                 {0x264,4,0x264,0x80},
727                 {0x132,4,0x132,0x0},
728                 {0x132,2,0x80, 0x132},
729                 {0x177,8,0x177,0x0},
730                 {0x132,8,0x84, 0x0},
731                 {},  /* not used */
732                 {0x132,6,0x80, 0x100},
733                 {0x200,6,0x100,0x100},
734                 {0x264,2,0x264,0x80},
735                 {0x280,4,0x280,0x100},
736                 {0x2B9,3,0x2B9,0x2B9},
737                 {0x2B9,5,0x2B9,0x2B9},
738                 {0x280,6,0x280,0x100},
739                 {0x132,4,0x132,0x0}};
740         u_char n;
741 
742         n = inb(XD_JUMPER);
743         n = (drive ? n : (n >> 2)) & 0x33;
744         n = (n | (n >> 2)) & 0x0F;
745         if (xd_geo[3*drive])
746                 xd_manual_geo_set(drive);
747         else
748                 if (n != 7) {   
749                         xd_info[drive].heads = (u_char)(geometry_table[n][1]);                  /* heads */
750                         xd_info[drive].cylinders = geometry_table[n][0];        /* cylinders */
751                         xd_info[drive].sectors = 17;                            /* sectors */
752 #if 0
753                         xd_info[drive].rwrite = geometry_table[n][2];   /* reduced write */
754                         xd_info[drive].precomp = geometry_table[n][3]           /* write precomp */
755                         xd_info[drive].ecc = 0x0B;                              /* ecc length */
756 #endif /* 0 */
757                 }
758                 else {
759                         printk("xd%c: undetermined drive geometry\n",'a'+drive);
760                         return;
761                 }
762         xd_info[drive].control = 5;                             /* control byte */
763         xd_setparam(CMD_DTCSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,geometry_table[n][2],geometry_table[n][3],0x0B);
764         xd_recalibrate(drive);
765 }
766 
767 static void __init xd_dtc_init_drive (u_char drive)
768 {
769         u_char cmdblk[6],buf[64];
770 
771         xd_build(cmdblk,CMD_DTCGETGEOM,drive,0,0,0,0,0);
772         if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
773                 xd_info[drive].heads = buf[0x0A];                       /* heads */
774                 xd_info[drive].cylinders = ((u_short *) (buf))[0x04];   /* cylinders */
775                 xd_info[drive].sectors = 17;                            /* sectors */
776                 if (xd_geo[3*drive])
777                         xd_manual_geo_set(drive);
778 #if 0
779                 xd_info[drive].rwrite = ((u_short *) (buf + 1))[0x05];  /* reduced write */
780                 xd_info[drive].precomp = ((u_short *) (buf + 1))[0x06]; /* write precomp */
781                 xd_info[drive].ecc = buf[0x0F];                         /* ecc length */
782 #endif /* 0 */
783                 xd_info[drive].control = 0;                             /* control byte */
784 
785                 xd_setparam(CMD_DTCSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,((u_short *) (buf + 1))[0x05],((u_short *) (buf + 1))[0x06],buf[0x0F]);
786                 xd_build(cmdblk,CMD_DTCSETSTEP,drive,0,0,0,0,7);
787                 if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
788                         printk("xd_dtc_init_drive: error setting step rate for xd%c\n", 'a'+drive);
789         }
790         else
791                 printk("xd_dtc_init_drive: error reading geometry for xd%c\n", 'a'+drive);
792 }
793 
794 static void __init xd_wd_init_controller (unsigned int address)
795 {
796         switch (address) {
797                 case 0x00000:
798                 case 0xC8000:   break;                  /*initial: 0x320 */
799                 case 0xCA000:   xd_iobase = 0x324; break;
800                 case 0xCC000:   xd_iobase = 0x328; break;
801                 case 0xCE000:   xd_iobase = 0x32C; break;
802                 case 0xD0000:   xd_iobase = 0x328; break; /* ? */
803                 case 0xD8000:   xd_iobase = 0x32C; break; /* ? */
804                 default:        printk("xd_wd_init_controller: unsupported BIOS address %06x\n",address);
805                                 break;
806         }
807         xd_maxsectors = 0x01;           /* this one doesn't wrap properly either... */
808 
809         outb(0,XD_RESET);               /* reset the controller */
810 
811         xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
812         add_timer(&xd_timer);
813         sleep_on(&xdc_wait);
814 }
815 
816 static void __init xd_wd_init_drive (u_char drive)
817 {
818         /* values from controller's BIOS - BIOS may be disabled */
819         static u_short geometry_table[][4] = {
820                 {0x264,4,0x1C2,0x1C2},   /* common part */
821                 {0x132,4,0x099,0x0},
822                 {0x267,2,0x1C2,0x1C2},
823                 {0x267,4,0x1C2,0x1C2},
824 
825                 {0x334,6,0x335,0x335},   /* 1004 series RLL */
826                 {0x30E,4,0x30F,0x3DC},
827                 {0x30E,2,0x30F,0x30F},
828                 {0x267,4,0x268,0x268},
829 
830                 {0x3D5,5,0x3D6,0x3D6},   /* 1002 series RLL */
831                 {0x3DB,7,0x3DC,0x3DC},
832                 {0x264,4,0x265,0x265},
833                 {0x267,4,0x268,0x268}};
834 
835         u_char cmdblk[6],buf[0x200];
836         u_char n = 0,rll,jumper_state,use_jumper_geo;
837         u_char wd_1002 = (xd_sigs[xd_type].string[7] == '6');
838         
839         jumper_state = ~(inb(0x322));
840         if (jumper_state & 0x40)
841                 xd_irq = 9;
842         rll = (jumper_state & 0x30) ? (0x04 << wd_1002) : 0;
843         xd_build(cmdblk,CMD_READ,drive,0,0,0,1,0);
844         if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
845                 xd_info[drive].heads = buf[0x1AF];                              /* heads */
846                 xd_info[drive].cylinders = ((u_short *) (buf + 1))[0xD6];       /* cylinders */
847                 xd_info[drive].sectors = 17;                                    /* sectors */
848                 if (xd_geo[3*drive])
849                         xd_manual_geo_set(drive);
850 #if 0
851                 xd_info[drive].rwrite = ((u_short *) (buf))[0xD8];              /* reduced write */
852                 xd_info[drive].wprecomp = ((u_short *) (buf))[0xDA];            /* write precomp */
853                 xd_info[drive].ecc = buf[0x1B4];                                /* ecc length */
854 #endif /* 0 */
855                 xd_info[drive].control = buf[0x1B5];                            /* control byte */
856                 use_jumper_geo = !(xd_info[drive].heads) || !(xd_info[drive].cylinders);
857                 if (xd_geo[3*drive]) {
858                         xd_manual_geo_set(drive);
859                         xd_info[drive].control = rll ? 7 : 5;
860                 }
861                 else if (use_jumper_geo) {
862                         n = (((jumper_state & 0x0F) >> (drive << 1)) & 0x03) | rll;
863                         xd_info[drive].cylinders = geometry_table[n][0];
864                         xd_info[drive].heads = (u_char)(geometry_table[n][1]);
865                         xd_info[drive].control = rll ? 7 : 5;
866 #if 0
867                         xd_info[drive].rwrite = geometry_table[n][2];
868                         xd_info[drive].wprecomp = geometry_table[n][3];
869                         xd_info[drive].ecc = 0x0B;
870 #endif /* 0 */
871                 }
872                 if (!wd_1002) {
873                         if (use_jumper_geo)
874                                 xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
875                                         geometry_table[n][2],geometry_table[n][3],0x0B);
876                         else
877                                 xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
878                                         ((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
879                 }
880         /* 1002 based RLL controler requests converted addressing, but reports physical 
881            (physical 26 sec., logical 17 sec.) 
882            1004 based ???? */
883                 if (rll & wd_1002) {
884                         if ((xd_info[drive].cylinders *= 26,
885                              xd_info[drive].cylinders /= 17) > 1023)
886                                 xd_info[drive].cylinders = 1023;  /* 1024 ? */
887 #if 0
888                         xd_info[drive].rwrite *= 26; 
889                         xd_info[drive].rwrite /= 17;
890                         xd_info[drive].wprecomp *= 26
891                         xd_info[drive].wprecomp /= 17;
892 #endif /* 0 */
893                 }
894         }
895         else
896                 printk("xd_wd_init_drive: error reading geometry for xd%c\n",'a'+drive);        
897 
898 }
899 
900 static void __init xd_seagate_init_controller (unsigned int address)
901 {
902         switch (address) {
903                 case 0x00000:
904                 case 0xC8000:   break;                  /*initial: 0x320 */
905                 case 0xD0000:   xd_iobase = 0x324; break;
906                 case 0xD8000:   xd_iobase = 0x328; break;
907                 case 0xE0000:   xd_iobase = 0x32C; break;
908                 default:        printk("xd_seagate_init_controller: unsupported BIOS address %06x\n",address);
909                                 break;
910         }
911         xd_maxsectors = 0x40;
912 
913         outb(0,XD_RESET);               /* reset the controller */
914 }
915 
916 static void __init xd_seagate_init_drive (u_char drive)
917 {
918         u_char cmdblk[6],buf[0x200];
919 
920         xd_build(cmdblk,CMD_ST11GETGEOM,drive,0,0,0,1,0);
921         if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
922                 xd_info[drive].heads = buf[0x04];                               /* heads */
923                 xd_info[drive].cylinders = (buf[0x02] << 8) | buf[0x03];        /* cylinders */
924                 xd_info[drive].sectors = buf[0x05];                             /* sectors */
925                 xd_info[drive].control = 0;                                     /* control byte */
926         }
927         else
928                 printk("xd_seagate_init_drive: error reading geometry from xd%c\n", 'a'+drive);
929 }
930 
931 /* Omti support courtesy Dirk Melchers */
932 static void __init xd_omti_init_controller (unsigned int address)
933 {
934         switch (address) {
935                 case 0x00000:
936                 case 0xC8000:   break;                  /*initial: 0x320 */
937                 case 0xD0000:   xd_iobase = 0x324; break;
938                 case 0xD8000:   xd_iobase = 0x328; break;
939                 case 0xE0000:   xd_iobase = 0x32C; break;
940                 default:        printk("xd_omti_init_controller: unsupported BIOS address %06x\n",address);
941                                 break;
942         }
943         
944         xd_maxsectors = 0x40;
945 
946         outb(0,XD_RESET);               /* reset the controller */
947 }
948 
949 static void __init xd_omti_init_drive (u_char drive)
950 {
951         /* gets infos from drive */
952         xd_override_init_drive(drive);
953 
954         /* set other parameters, Hardcoded, not that nice :-) */
955         xd_info[drive].control = 2;
956 }
957 
958 /* Xebec support (AK) */
959 static void __init xd_xebec_init_controller (unsigned int address)
960 {
961 /* iobase may be set manually in range 0x300 - 0x33C
962       irq may be set manually to 2(9),3,4,5,6,7
963       dma may be set manually to 1,2,3
964         (How to detect them ???)
965 BIOS address may be set manually in range 0x0 - 0xF8000
966 If you need non-standard settings use the xd=... command */
967 
968         switch (address) {
969                 case 0x00000:
970                 case 0xC8000:   /* initially: xd_iobase==0x320 */
971                 case 0xD0000:
972                 case 0xD2000:
973                 case 0xD4000:
974                 case 0xD6000:
975                 case 0xD8000:
976                 case 0xDA000:
977                 case 0xDC000:
978                 case 0xDE000:
979                 case 0xE0000:   break;
980                 default:        printk("xd_xebec_init_controller: unsupported BIOS address %06x\n",address);
981                                 break;
982                 }
983 
984         xd_maxsectors = 0x01;
985         outb(0,XD_RESET);               /* reset the controller */
986 
987         xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
988         add_timer(&xd_timer);
989         sleep_on(&xdc_wait);
990 }
991 
992 static void __init xd_xebec_init_drive (u_char drive)
993 {
994         /* values from controller's BIOS - BIOS chip may be removed */
995         static u_short geometry_table[][5] = {
996                 {0x132,4,0x080,0x080,0x7},
997                 {0x132,4,0x080,0x080,0x17},
998                 {0x264,2,0x100,0x100,0x7},
999                 {0x264,2,0x100,0x100,0x17},
1000                 {0x132,8,0x080,0x080,0x7},
1001                 {0x132,8,0x080,0x080,0x17},
1002                 {0x264,4,0x100,0x100,0x6},
1003                 {0x264,4,0x100,0x100,0x17},
1004                 {0x2BC,5,0x2BC,0x12C,0x6},
1005                 {0x3A5,4,0x3A5,0x3A5,0x7},
1006                 {0x26C,6,0x26C,0x26C,0x7},
1007                 {0x200,8,0x200,0x100,0x17},
1008                 {0x400,5,0x400,0x400,0x7},
1009                 {0x400,6,0x400,0x400,0x7},
1010                 {0x264,8,0x264,0x200,0x17},
1011                 {0x33E,7,0x33E,0x200,0x7}};
1012         u_char n;
1013 
1014         n = inb(XD_JUMPER) & 0x0F; /* BIOS's drive number: same geometry 
1015                                         is assumed for BOTH drives */
1016         if (xd_geo[3*drive])
1017                 xd_manual_geo_set(drive);
1018         else {
1019                 xd_info[drive].heads = (u_char)(geometry_table[n][1]);                  /* heads */
1020                 xd_info[drive].cylinders = geometry_table[n][0];        /* cylinders */
1021                 xd_info[drive].sectors = 17;                            /* sectors */
1022 #if 0
1023                 xd_info[drive].rwrite = geometry_table[n][2];   /* reduced write */
1024                 xd_info[drive].precomp = geometry_table[n][3]           /* write precomp */
1025                 xd_info[drive].ecc = 0x0B;                              /* ecc length */
1026 #endif /* 0 */
1027         }
1028         xd_info[drive].control = geometry_table[n][4];                  /* control byte */
1029         xd_setparam(CMD_XBSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,geometry_table[n][2],geometry_table[n][3],0x0B);
1030         xd_recalibrate(drive);
1031 }
1032 
1033 /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
1034    etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
1035 static void __init xd_override_init_drive (u_char drive)
1036 {
1037         u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 };
1038         u_char cmdblk[6],i;
1039 
1040         if (xd_geo[3*drive])
1041                 xd_manual_geo_set(drive);
1042         else {
1043                 for (i = 0; i < 3; i++) {
1044                         while (min[i] != max[i] - 1) {
1045                                 test[i] = (min[i] + max[i]) / 2;
1046                                 xd_build(cmdblk,CMD_SEEK,drive,(u_char) test[0],(u_short) test[1],(u_char) test[2],0,0);
1047                                 if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
1048                                         min[i] = test[i];
1049                                 else
1050                                         max[i] = test[i];
1051                         }
1052                         test[i] = min[i];
1053                 }
1054                 xd_info[drive].heads = (u_char) min[0] + 1;
1055                 xd_info[drive].cylinders = (u_short) min[1] + 1;
1056                 xd_info[drive].sectors = (u_char) min[2] + 1;
1057         }
1058         xd_info[drive].control = 0;
1059 }
1060 
1061 /* xd_setup: initialise controler from command line parameters */
1062 void __init do_xd_setup (int *integers)
1063 {
1064         switch (integers[0]) {
1065                 case 4: if (integers[4] < 0)
1066                                 nodma = 1;
1067                         else if (integers[4] < 8)
1068                                 xd_dma = integers[4];
1069                 case 3: if ((integers[3] > 0) && (integers[3] <= 0x3FC))
1070                                 xd_iobase = integers[3];
1071                 case 2: if ((integers[2] > 0) && (integers[2] < 16))
1072                                 xd_irq = integers[2];
1073                 case 1: xd_override = 1;
1074                         if ((integers[1] >= 0) && (integers[1] < (sizeof(xd_sigs) / sizeof(xd_sigs[0]))))
1075                                 xd_type = integers[1];
1076                 case 0: break;
1077                 default:printk("xd: too many parameters for xd\n");
1078         }
1079         xd_maxsectors = 0x01;
1080 }
1081 
1082 /* xd_setparam: set the drive characteristics */
1083 static void __init xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc)
1084 {
1085         u_char cmdblk[14];
1086 
1087         xd_build(cmdblk,command,drive,0,0,0,0,0);
1088         cmdblk[6] = (u_char) (cylinders >> 8) & 0x03;
1089         cmdblk[7] = (u_char) (cylinders & 0xFF);
1090         cmdblk[8] = heads & 0x1F;
1091         cmdblk[9] = (u_char) (rwrite >> 8) & 0x03;
1092         cmdblk[10] = (u_char) (rwrite & 0xFF);
1093         cmdblk[11] = (u_char) (wprecomp >> 8) & 0x03;
1094         cmdblk[12] = (u_char) (wprecomp & 0xFF);
1095         cmdblk[13] = ecc;
1096 
1097         /* Some controllers require geometry info as data, not command */
1098 
1099         if (xd_command(cmdblk,PIO_MODE,0,&cmdblk[6],0,XD_TIMEOUT * 2))
1100                 printk("xd: error setting characteristics for xd%c\n", 'a'+drive);
1101 }
1102 
1103 
1104 #ifdef MODULE
1105 static int xd[5] = { -1,-1,-1,-1, };
1106 
1107 MODULE_PARM(xd, "1-4i");
1108 MODULE_PARM(xd_geo, "3-6i");
1109 MODULE_PARM(nodma, "i");
1110 
1111 static void xd_done (void)
1112 {
1113         struct gendisk ** gdp;
1114         
1115         blksize_size[MAJOR_NR] = NULL;
1116         blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1117         blk_size[MAJOR_NR] = NULL;
1118         hardsect_size[MAJOR_NR] = NULL;
1119         read_ahead[MAJOR_NR] = 0;
1120         for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
1121                 if (*gdp == &xd_gendisk)
1122                         break;
1123         if (*gdp)
1124                 *gdp = (*gdp)->next;
1125         release_region(xd_iobase,4);
1126 }
1127 
1128 int init_module(void)
1129 {
1130         int i,count = 0;
1131         int error;
1132 
1133         for (i = 4; i > 0; i--)
1134                 if(((xd[i] = xd[i-1]) >= 0) && !count)
1135                         count = i;
1136         if((xd[0] = count))
1137                 do_xd_setup(xd);
1138 
1139         error = xd_init();
1140         if (error) return error;
1141 
1142         printk(KERN_INFO "XD: Loaded as a module.\n");
1143         if (!xd_drives) {
1144                 /* no drives detected - unload module */
1145                 devfs_unregister_blkdev(MAJOR_NR, "xd");
1146                 xd_done();
1147                 return (-1);
1148         }
1149         
1150         return 0;
1151 }
1152 
1153 void cleanup_module(void)
1154 {
1155         int partition,dev,start;
1156 
1157         devfs_unregister_blkdev(MAJOR_NR, "xd");
1158         for (dev = 0; dev < xd_drives; dev++) {
1159                 start = dev << xd_gendisk.minor_shift; 
1160                 for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
1161                         int minor = (start | partition);
1162                         kdev_t devp = MKDEV(MAJOR_NR, minor);
1163                         start = dev << xd_gendisk.minor_shift; 
1164                         sync_dev(devp);
1165                         invalidate_buffers(devp);
1166                 }
1167         }
1168         xd_done();
1169         devfs_unregister (devfs_handle);
1170         if (xd_drives) {
1171                 free_irq(xd_irq, NULL);
1172                 free_dma(xd_dma);
1173                 if (xd_dma_buffer)
1174                         xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200);
1175         }
1176 }
1177 #else
1178 
1179 static int __init xd_setup (char *str)
1180 {
1181         int ints[5];
1182         get_options (str, ARRAY_SIZE (ints), ints);
1183         do_xd_setup (ints);
1184         return 1;
1185 }
1186 
1187 /* xd_manual_geo_init: initialise drive geometry from command line parameters
1188    (used only for WD drives) */
1189 static int __init xd_manual_geo_init (char *str)
1190 {
1191         int i, integers[1 + 3*XD_MAXDRIVES];
1192 
1193         get_options (str, ARRAY_SIZE (integers), integers);
1194         if (integers[0]%3 != 0) {
1195                 printk("xd: incorrect number of parameters for xd_geo\n");
1196                 return 1;
1197         }
1198         for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++)
1199                 xd_geo[i] = integers[i+1];
1200         return 1;
1201 }
1202 
1203 __setup ("xd=", xd_setup);
1204 __setup ("xd_geo=", xd_manual_geo_init);
1205 
1206 #endif /* MODULE */
1207 
1208 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.