This source file includes following definitions.
- xd_init
 
- xd_detect
 
- xd_geninit
 
- xd_open
 
- do_xd_request
 
- xd_ioctl
 
- xd_release
 
- xd_reread_partitions
 
- xd_readwrite
 
- xd_recalibrate
 
- xd_interrupt_handler
 
- xd_setup_dma
 
- xd_build
 
- xd_waitport
 
- xd_command
 
- xd_initdrives
 
- xd_dtc_init_controller
 
- xd_dtc_init_drive
 
- xd_wd_init_controller
 
- xd_wd_init_drive
 
- xd_seagate_init_controller
 
- xd_seagate_init_drive
 
- xd_omti_init_controller
 
- xd_omti_init_drive
 
- xd_override_init_drive
 
- xd_setup
 
- xd_setparam
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 #include <linux/errno.h>
  15 #include <linux/sched.h>
  16 #include <linux/fs.h>
  17 #include <linux/kernel.h>
  18 #include <linux/genhd.h>
  19 #include <linux/xd.h>
  20 
  21 #include <asm/system.h>
  22 #include <asm/io.h>
  23 #include <asm/segment.h>
  24 #include <asm/dma.h>
  25 
  26 #define MAJOR_NR XT_DISK_MAJOR
  27 #include "blk.h"
  28 
  29 XD_INFO xd_info[XD_MAXDRIVES];
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 static XD_SIGNATURE xd_sigs[] = {
  56         { 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, 
  57         { 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, 
  58         { 0x0008,"07/15/86 (C) Copyright 1986 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1002AWX1" }, 
  59         { 0x0008,"06/24/88 (C) Copyright 1988 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1004A27X" }, 
  60         { 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Digital WDXT-GEN2" }, 
  61         { 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, 
  62         { 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, 
  63         { 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, 
  64 };
  65 static u_char *xd_bases[] =
  66 {
  67         (u_char *) 0xC8000,(u_char *) 0xCA000,(u_char *) 0xCC000,
  68         (u_char *) 0xCE000,(u_char *) 0xD0000,(u_char *) 0xD8000,
  69         (u_char *) 0xE0000
  70 };
  71 
  72 static struct hd_struct xd[XD_MAXDRIVES << 6];
  73 static int xd_sizes[XD_MAXDRIVES << 6],xd_access[XD_MAXDRIVES] = { 0,0 };
  74 static int xd_blocksizes[XD_MAXDRIVES << 6];
  75 static struct gendisk xd_gendisk = { MAJOR_NR,"xd",6,1 << 6,XD_MAXDRIVES,xd_geninit,xd,xd_sizes,0,(void *) xd_info,NULL };
  76 static struct file_operations xd_fops = { NULL,block_read,block_write,NULL,NULL,xd_ioctl,NULL,xd_open,xd_release,block_fsync };
  77 
  78 static struct wait_queue *xd_wait_int = NULL,*xd_wait_open = NULL;
  79 static u_char xd_valid[XD_MAXDRIVES] = { 0,0 };
  80 static u_char xd_drives = 0,xd_irq = 0,xd_dma = 0,xd_maxsectors,xd_override = 0,xd_type = 0;
  81 static u_short xd_iobase = 0;
  82 
  83 
  84 u_long xd_init (u_long mem_start,u_long mem_end)
     
  85 {
  86         u_char i,controller,*address;
  87         
  88         if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
  89                 printk("xd_init: unable to get major number %d\n",MAJOR_NR);
  90                 return (mem_start);
  91         }
  92         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
  93         read_ahead[MAJOR_NR] = 8;       
  94         xd_gendisk.next = gendisk_head;
  95         gendisk_head = &xd_gendisk;
  96 
  97         if (xd_detect(&controller,&address)) {
  98 
  99                 printk("xd_init: detected a%s controller (type %d) at address %p\n",xd_sigs[controller].name,controller,address);
 100                 if (controller)
 101                         xd_sigs[controller].init_controller(address);
 102                 xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
 103                 
 104                 printk("xd_init: detected %d hard drive%s (using IRQ%d & DMA%d)\n",xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
 105                 for (i = 0; i < xd_drives; i++)
 106                         printk("xd_init: drive %d geometry - heads = %d, cylinders = %d, sectors = %d\n",i,xd_info[i].heads,xd_info[i].cylinders,xd_info[i].sectors);
 107 
 108                 if (!request_irq(xd_irq,xd_interrupt_handler)) {
 109                         if (request_dma(xd_dma)) {
 110                                 printk("xd_init: unable to get DMA%d\n",xd_dma);
 111                                 free_irq(xd_irq);
 112                         }
 113                 }
 114                 else
 115                         printk("xd_init: unable to get IRQ%d\n",xd_irq);
 116         }
 117         return mem_start;
 118 }
 119 
 120 
 121 static u_char xd_detect (u_char *controller,u_char **address)
     
 122 {
 123         u_char i,j,found = 0;
 124 
 125         if (xd_override)
 126         {
 127                 *controller = xd_type;
 128                 *address = NULL;
 129                 return(1);
 130         }
 131 
 132         for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])) && !found; i++)
 133                 for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])) && !found; j++)
 134                         if (!memcmp(xd_bases[i] + xd_sigs[j].offset,xd_sigs[j].string,strlen(xd_sigs[j].string))) {
 135                                 *controller = j;
 136                                 *address = xd_bases[i];
 137                                 found++;
 138                         }
 139         return (found);
 140 }
 141 
 142 
 143 static void xd_geninit (void)
     
 144 {
 145         u_char i;
 146 
 147         for (i = 0; i < xd_drives; i++) {
 148                 xd[i << 6].nr_sects = xd_info[i].heads * xd_info[i].cylinders * xd_info[i].sectors;
 149                 xd_valid[i] = 1;
 150         }
 151 
 152         xd_gendisk.nr_real = xd_drives;
 153 
 154         for(i=0;i<(XD_MAXDRIVES << 6);i++) xd_blocksizes[i] = 1024;
 155         blksize_size[MAJOR_NR] = xd_blocksizes;
 156 }
 157 
 158 
 159 static int xd_open (struct inode *inode,struct file *file)
     
 160 {
 161         int dev = DEVICE_NR(MINOR(inode->i_rdev));
 162 
 163         if (dev < xd_drives) {
 164                 while (!xd_valid[dev])
 165                         sleep_on(&xd_wait_open);
 166 
 167                 xd_access[dev]++;
 168 
 169                 return (0);
 170         }
 171         else
 172                 return (-ENODEV);
 173 }
 174 
 175 
 176 static void do_xd_request (void)
     
 177 {
 178         u_int block,count,retry;
 179         int code;
 180 
 181         sti();
 182         while (code = 0, CURRENT) {
 183                 INIT_REQUEST;   
 184 
 185                 if (CURRENT_DEV < xd_drives && CURRENT->sector + CURRENT->nr_sectors <= xd[MINOR(CURRENT->dev)].nr_sects) {
 186                         block = CURRENT->sector + xd[MINOR(CURRENT->dev)].start_sect;
 187                         count = CURRENT->nr_sectors;
 188 
 189                         switch (CURRENT->cmd) {
 190                                 case READ:
 191                                 case WRITE:     for (retry = 0; (retry < XD_RETRIES) && !code; retry++)
 192                                                         code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count);
 193                                                 break;
 194                                 default:        printk("do_xd_request: unknown request\n"); break;
 195                         }
 196                 }
 197                 end_request(code);      
 198         }
 199 }
 200 
 201 
 202 static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
     
 203 {
 204         XD_GEOMETRY *geometry = (XD_GEOMETRY *) arg;
 205         int dev = DEVICE_NR(MINOR(inode->i_rdev)),err;
 206 
 207         if (inode && (dev < xd_drives))
 208                 switch (cmd) {
 209                         case HDIO_GETGEO:       if (arg) {
 210                                                         if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry))))
 211                                                                 return (err);
 212                                                         put_fs_byte(xd_info[dev].heads,(char *) &geometry->heads);
 213                                                         put_fs_byte(xd_info[dev].sectors,(char *) &geometry->sectors);
 214                                                         put_fs_word(xd_info[dev].cylinders,(short *) &geometry->cylinders);
 215                                                         put_fs_long(xd[MINOR(inode->i_rdev)].start_sect,(long *) &geometry->start);
 216 
 217                                                         return (0);
 218                                                 }
 219                                                 break;
 220                         case BLKGETSIZE:        if (arg) {
 221                                                         if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long))))
 222                                                                 return (err);
 223                                                         put_fs_long(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
 224 
 225                                                         return (0);
 226                                                 }
 227                                                 break;
 228                         case BLKFLSBUF:
 229                                 if(!suser())  return -EACCES;
 230                                 if(!inode->i_rdev) return -EINVAL;
 231                                 fsync_dev(inode->i_rdev);
 232                                 invalidate_buffers(inode->i_rdev);
 233                                 return 0;
 234                                 
 235                         case BLKRRPART:         return (xd_reread_partitions(inode->i_rdev));
 236                         RO_IOCTLS(inode->i_rdev,arg);
 237                 }
 238         return (-EINVAL);
 239 }
 240 
 241 
 242 static void xd_release (struct inode *inode, struct file *file)
     
 243 {
 244         int dev = DEVICE_NR(MINOR(inode->i_rdev));
 245 
 246         if (dev < xd_drives) {
 247                 sync_dev(dev);
 248                 xd_access[dev]--;
 249         }
 250 }
 251 
 252 
 253 static int xd_reread_partitions(int dev)
     
 254 {
 255         int target = DEVICE_NR(MINOR(dev)),start = target << xd_gendisk.minor_shift,partition;
 256 
 257         cli(); xd_valid[target] = (xd_access[target] != 1); sti();
 258         if (xd_valid[target])
 259                 return (-EBUSY);
 260 
 261         for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
 262                 sync_dev(MAJOR_NR << 8 | start | partition);
 263                 invalidate_inodes(MAJOR_NR << 8 | start | partition);
 264                 invalidate_buffers(MAJOR_NR << 8 | start | partition);
 265                 xd_gendisk.part[start + partition].start_sect = 0;
 266                 xd_gendisk.part[start + partition].nr_sects = 0;
 267         };
 268 
 269         xd_gendisk.part[start].nr_sects = xd_info[target].heads * xd_info[target].cylinders * xd_info[target].sectors;
 270         resetup_one_dev(&xd_gendisk,target);
 271 
 272         xd_valid[target] = 1;
 273         wake_up(&xd_wait_open);
 274 
 275         return (0);
 276 }
 277 
 278 
 279 static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block,u_int count)
     
 280 {
 281         u_char cmdblk[6],sense[4];
 282         u_short track,cylinder;
 283         u_char head,sector,control,mode,temp;
 284         
 285 #ifdef DEBUG_READWRITE
 286         printk("xd_readwrite: operation = %s, drive = %d, buffer = 0x%X, block = %d, count = %d\n",operation == READ ? "read" : "write",drive,buffer,block,count);
 287 #endif 
 288 
 289         control = xd_info[drive].control;
 290         while (count) {
 291                 temp = count < xd_maxsectors ? count : xd_maxsectors;
 292 
 293                 track = block / xd_info[drive].sectors;
 294                 head = track % xd_info[drive].heads;
 295                 cylinder = track / xd_info[drive].heads;
 296                 sector = block % xd_info[drive].sectors;
 297 
 298 #ifdef DEBUG_READWRITE
 299                 printk("xd_readwrite: drive = %d, head = %d, cylinder = %d, sector = %d, count = %d\n",drive,head,cylinder,sector,temp);
 300 #endif 
 301 
 302                 mode = xd_setup_dma(operation == READ ? DMA_MODE_READ : DMA_MODE_WRITE,(u_char *)buffer,temp * 0x200);
 303                 xd_build(cmdblk,operation == READ ? CMD_READ : CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control);
 304 
 305                 switch (xd_command(cmdblk,mode,(u_char *) buffer,(u_char *) buffer,sense,XD_TIMEOUT)) {
 306                         case 1: printk("xd_readwrite: timeout, recalibrating drive\n"); xd_recalibrate(drive); return (0);
 307                         case 2: switch ((sense[0] & 0x30) >> 4) {
 308                                         case 0: printk("xd_readwrite: drive error, code = 0x%X",sense[0] & 0x0F); break;
 309                                         case 1: printk("xd_readwrite: controller error, code = 0x%X",sense[0] & 0x0F); break;
 310                                         case 2: printk("xd_readwrite: command error, code = 0x%X",sense[0] & 0x0F); break;
 311                                         case 3: printk("xd_readwrite: miscellaneous error, code = 0x%X",sense[0] & 0x0F); break;
 312                                 }
 313                                 if (sense[0] & 0x80)
 314                                         printk(" - drive = %d, head = %d, cylinder = %d, sector = %d\n",sense[1] & 0xE0,sense[1] & 0x1F,((sense[2] & 0xC0) << 2) | sense[3],sense[2] & 0x3F);
 315                                 else
 316                                         printk(" - no valid disk address\n");
 317                                 return (0);
 318                 }
 319                 count -= temp, buffer += temp * 0x200, block += temp;
 320         }
 321         return (1);
 322 }
 323 
 324 
 325 static void xd_recalibrate (u_char drive)
     
 326 {
 327         u_char cmdblk[6];
 328         
 329         xd_build(cmdblk,CMD_RECALIBRATE,drive,0,0,0,0,0);
 330         if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8))
 331                 printk("xd_recalibrate: warning! error recalibrating, controller may be unstable\n");
 332 }
 333 
 334 
 335 static void xd_interrupt_handler (int unused)
     
 336 {
 337         if (inb(XD_STATUS) & STAT_INTERRUPT) {                                                  
 338 #ifdef DEBUG_OTHER
 339                 printk("xd_interrupt_handler: interrupt detected\n");
 340 #endif 
 341                 outb(0,XD_CONTROL);                                                             
 342                 wake_up(&xd_wait_int);                                                          
 343         }
 344         else
 345                 printk("xd_interrupt_handler: unexpected interrupt\n");
 346 }
 347 
 348 
 349 static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count)
     
 350 {
 351         if (buffer < ((u_char *) 0x1000000 - count)) {          
 352                 if (((u_int) buffer & 0xFFFF0000) != ((u_int) buffer + count) & 0xFFFF0000) {
 353 #ifdef DEBUG_OTHER
 354                         printk("xd_setup_dma: using PIO, transfer overlaps 64k boundary\n");
 355 #endif 
 356                         return (PIO_MODE);
 357                 }
 358                 disable_dma(xd_dma);
 359                 clear_dma_ff(xd_dma);
 360                 set_dma_mode(xd_dma,mode);
 361                 set_dma_addr(xd_dma,(u_int) buffer);
 362                 set_dma_count(xd_dma,count);
 363 
 364                 return (DMA_MODE);                      
 365         }
 366 #ifdef DEBUG_OTHER
 367         printk("xd_setup_dma: using PIO, cannot DMA above 16 meg\n");
 368 #endif 
 369         return (PIO_MODE);
 370 }
 371 
 372 
 373 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)
     
 374 {
 375         cmdblk[0] = command;
 376         cmdblk[1] = ((drive & 0x07) << 5) | (head & 0x1F);
 377         cmdblk[2] = ((cylinder & 0x300) >> 2) | (sector & 0x3F);
 378         cmdblk[3] = cylinder & 0xFF;
 379         cmdblk[4] = count;
 380         cmdblk[5] = control;
 381         
 382         return (cmdblk);
 383 }
 384 
 385 
 386 static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long timeout)
     
 387 {
 388         u_long expiry = jiffies + timeout;
 389 
 390         while (((inb(port) & mask) != flags) && (jiffies < expiry))
 391                 ;
 392 
 393         return (jiffies >= expiry);
 394 }
 395 
 396 
 397 static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outdata,u_char *sense,u_long timeout)
     
 398 {
 399         u_char cmdblk[6],csb,complete = 0;
 400 
 401 #ifdef DEBUG_COMMAND
 402         printk("xd_command: command = 0x%X, mode = 0x%X, indata = 0x%X, outdata = 0x%X, sense = 0x%X\n",command,mode,indata,outdata,sense);
 403 #endif 
 404 
 405         outb(0,XD_SELECT);
 406         outb(mode,XD_CONTROL);
 407 
 408         if (xd_waitport(XD_STATUS,STAT_SELECT,STAT_SELECT,timeout))
 409                 return (1);
 410         
 411         while (!complete) {
 412                 if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout))
 413                         return (1);
 414                 switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) {
 415                         case 0:                 if (mode == DMA_MODE) {
 416                                                         enable_dma(xd_dma);
 417                                                         sleep_on(&xd_wait_int);
 418                                                         disable_dma(xd_dma);
 419                                                 }
 420                                                 else
 421                                                         outb(outdata ? *outdata++ : 0,XD_DATA);
 422                                                 break;
 423                         case STAT_INPUT:        if (mode == DMA_MODE) {
 424                                                         enable_dma(xd_dma);
 425                                                         sleep_on(&xd_wait_int);
 426                                                         disable_dma(xd_dma);
 427                                                 }
 428                                                 else
 429                                                         if (indata)
 430                                                                 *indata++ = inb(XD_DATA);
 431                                                         else
 432                                                                 inb(XD_DATA);
 433                                                 break;
 434                         case STAT_COMMAND:      outb(command ? *command++ : 0,XD_DATA); break;
 435                         case STAT_COMMAND
 436                              | STAT_INPUT:      complete = 1; break;
 437                 }
 438         }
 439         csb = inb(XD_DATA);
 440 
 441         if (xd_waitport(XD_STATUS,0,STAT_SELECT,timeout))                                       
 442                 return (1);
 443 
 444         if (csb & CSB_ERROR) {                                                                  
 445                 xd_build(cmdblk,CMD_SENSE,(csb & CSB_LUN) >> 5,0,0,0,0,0);
 446                 if (xd_command(cmdblk,0,sense,0,0,XD_TIMEOUT))
 447                         printk("xd_command: warning! sense command failed!\n");
 448         }
 449 
 450 #ifdef DEBUG_COMMAND
 451         printk("xd_command: completed with csb = 0x%X\n",csb);
 452 #endif 
 453 
 454         return (csb & CSB_ERROR);
 455 }
 456 
 457 static u_char xd_initdrives (void (*init_drive)(u_char drive))
     
 458 {
 459         u_char cmdblk[6],i,count = 0;
 460 
 461         for (i = 0; i < XD_MAXDRIVES; i++) {
 462                 xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
 463                 if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2)) {
 464                         init_drive(count);
 465                         count++;
 466                 }
 467         }
 468         return (count);
 469 }
 470 
 471 static void xd_dtc_init_controller (u_char *address)
     
 472 {
 473         switch ((u_long) address) {
 474                 case 0xC8000:   xd_iobase = 0x320; break;
 475                 case 0xCA000:   xd_iobase = 0x324; break;
 476                 default:        printk("xd_dtc_init_controller: unsupported BIOS address %p\n",address);
 477                                 xd_iobase = 0x320; break;
 478         }
 479         xd_irq = 5;                     
 480         xd_dma = 3;
 481         xd_maxsectors = 0x01;           
 482 
 483         outb(0,XD_RESET);               
 484 }
 485 
 486 static void xd_dtc_init_drive (u_char drive)
     
 487 {
 488         u_char cmdblk[6],buf[64];
 489 
 490         xd_build(cmdblk,CMD_DTCGETGEOM,drive,0,0,0,0,0);
 491         if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
 492                 xd_info[drive].heads = buf[0x0A];                       
 493                 xd_info[drive].cylinders = ((u_short *) (buf))[0x04];   
 494                 xd_info[drive].sectors = 17;                            
 495 #if 0
 496                 xd_info[drive].rwrite = ((u_short *) (buf + 1))[0x05];  
 497                 xd_info[drive].precomp = ((u_short *) (buf + 1))[0x06]; 
 498                 xd_info[drive].ecc = buf[0x0F];                         
 499 #endif 
 500                 xd_info[drive].control = 0;                             
 501 
 502                 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]);
 503                 xd_build(cmdblk,CMD_DTCSETSTEP,drive,0,0,0,0,7);
 504                 if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
 505                         printk("xd_dtc_init_drive: error setting step rate for drive %d\n",drive);
 506         }
 507         else
 508                 printk("xd_dtc_init_drive: error reading geometry for drive %d\n",drive);
 509 }
 510 
 511 static void xd_wd_init_controller (u_char *address)
     
 512 {
 513         switch ((u_long) address) {
 514                 case 0xC8000:   xd_iobase = 0x320; break;
 515                 case 0xCA000:   xd_iobase = 0x324; break;
 516                 case 0xCC000:   xd_iobase = 0x328; break;
 517                 case 0xCE000:   xd_iobase = 0x32C; break;
 518                 case 0xD0000:   xd_iobase = 0x328; break;
 519                 case 0xD8000:   xd_iobase = 0x32C; break;
 520                 default:        printk("xd_wd_init_controller: unsupported BIOS address %p\n",address);
 521                                 xd_iobase = 0x320; break;
 522         }
 523         xd_irq = 5;                     
 524         xd_dma = 3;
 525         xd_maxsectors = 0x01;           
 526 
 527                  
 528 }
 529 
 530 static void xd_wd_init_drive (u_char drive)
     
 531 {
 532         u_char cmdblk[6],buf[0x200];
 533 
 534         xd_build(cmdblk,CMD_READ,drive,0,0,0,1,0);
 535         if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
 536                 xd_info[drive].heads = buf[0x1AF];                              
 537                 xd_info[drive].cylinders = ((u_short *) (buf + 1))[0xD6];       
 538                 xd_info[drive].sectors = 17;                                    
 539 #if 0
 540                 xd_info[drive].rwrite = ((u_short *) (buf))[0xD8];              
 541                 xd_info[drive].wprecomp = ((u_short *) (buf))[0xDA];            
 542                 xd_info[drive].ecc = buf[0x1B4];                                
 543 #endif 
 544                 xd_info[drive].control = buf[0x1B5];                            
 545 
 546                 xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
 547         }
 548         else
 549                 printk("xd_wd_init_drive: error reading geometry for drive %d\n",drive);        
 550 }
 551 
 552 static void xd_seagate_init_controller (u_char *address)
     
 553 {
 554         switch ((u_long) address) {
 555                 case 0xC8000:   xd_iobase = 0x320; break;
 556                 case 0xD0000:   xd_iobase = 0x324; break;
 557                 case 0xD8000:   xd_iobase = 0x328; break;
 558                 case 0xE0000:   xd_iobase = 0x32C; break;
 559                 default:        printk("xd_seagate_init_controller: unsupported BIOS address %p\n",address);
 560                                 xd_iobase = 0x320; break;
 561         }
 562         xd_irq = 5;                     
 563         xd_dma = 3;
 564         xd_maxsectors = 0x40;
 565 
 566         outb(0,XD_RESET);               
 567 }
 568 
 569 static void xd_seagate_init_drive (u_char drive)
     
 570 {
 571         u_char cmdblk[6],buf[0x200];
 572 
 573         xd_build(cmdblk,CMD_ST11GETGEOM,drive,0,0,0,1,0);
 574         if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
 575                 xd_info[drive].heads = buf[0x04];                               
 576                 xd_info[drive].cylinders = (buf[0x02] << 8) | buf[0x03];        
 577                 xd_info[drive].sectors = buf[0x05];                             
 578                 xd_info[drive].control = 0;                                     
 579         }
 580         else
 581                 printk("xd_seagate_init_drive: error reading geometry from drive %d\n",drive);
 582 }
 583 
 584 
 585 static void xd_omti_init_controller (u_char *address)
     
 586 {
 587         switch ((u_long) address) {
 588                 case 0xC8000:   xd_iobase = 0x320; break;
 589                 case 0xD0000:   xd_iobase = 0x324; break;
 590                 case 0xD8000:   xd_iobase = 0x328; break;
 591                 case 0xE0000:   xd_iobase = 0x32C; break;
 592                 default:        printk("xd_omti_init_controller: unsupported BIOS address %p\n",address);
 593                                 xd_iobase = 0x320; break;
 594         }
 595         
 596         xd_irq = 5;                     
 597         xd_dma = 3;
 598         xd_maxsectors = 0x40;
 599 
 600         outb(0,XD_RESET);               
 601 }
 602 
 603 static void xd_omti_init_drive (u_char drive)
     
 604 {
 605         
 606         xd_override_init_drive(drive);
 607 
 608         
 609         xd_info[drive].control = 2;
 610 }
 611 
 612 
 613 
 614 static void xd_override_init_drive (u_char drive)
     
 615 {
 616         u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 };
 617         u_char cmdblk[6],i;
 618 
 619         for (i = 0; i < 3; i++) {
 620                 while (min[i] != max[i] - 1) {
 621                         test[i] = (min[i] + max[i]) / 2;
 622                         xd_build(cmdblk,CMD_SEEK,drive,(u_char) test[0],(u_short) test[1],(u_char) test[2],0,0);
 623                         if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
 624                                 min[i] = test[i];
 625                         else
 626                                 max[i] = test[i];
 627                 }
 628                 test[i] = min[i];
 629         }
 630         xd_info[drive].heads = (u_char) min[0] + 1;
 631         xd_info[drive].cylinders = (u_short) min[1] + 1;
 632         xd_info[drive].sectors = (u_char) min[2] + 1;
 633         xd_info[drive].control = 0;
 634 }
 635 
 636 
 637 void xd_setup (char *command,int *integers)
     
 638 {
 639         xd_override = 1;
 640 
 641         xd_type = integers[1];
 642         xd_irq = integers[2];
 643         xd_iobase = integers[3];
 644         xd_dma = integers[4];
 645 
 646         xd_maxsectors = 0x01;
 647 }
 648 
 649 
 650 static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc)
     
 651 {
 652         u_char cmdblk[14];
 653 
 654         xd_build(cmdblk,command,drive,0,0,0,0,0);
 655         cmdblk[6] = (u_char) (cylinders >> 8) & 0x03;
 656         cmdblk[7] = (u_char) (cylinders & 0xFF);
 657         cmdblk[8] = heads & 0x1F;
 658         cmdblk[9] = (u_char) (rwrite >> 8) & 0x03;
 659         cmdblk[10] = (u_char) (rwrite & 0xFF);
 660         cmdblk[11] = (u_char) (wprecomp >> 8) & 0x03;
 661         cmdblk[12] = (u_char) (wprecomp & 0xFF);
 662         cmdblk[13] = ecc;
 663 
 664         if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
 665                 printk("xd_setparam: error setting characteristics for drive %d\n",drive);
 666 }
 667