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