root/drivers/block/hd.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. CMOS_READ
  2. read_timer
  3. hd_setup
  4. win_result
  5. controller_ready
  6. status_ok
  7. controller_busy
  8. hd_out
  9. drive_busy
  10. reset_controller
  11. reset_hd
  12. unexpected_hd_interrupt
  13. bad_rw_intr
  14. wait_DRQ
  15. read_intr
  16. write_intr
  17. recal_intr
  18. hd_times_out
  19. do_hd_request
  20. hd_ioctl
  21. hd_open
  22. hd_release
  23. hd_interrupt
  24. hd_geninit
  25. hd_init
  26. revalidate_hddisk

   1 /*
   2  *  linux/kernel/hd.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  * This is the low-level hd interrupt support. It traverses the
   9  * request-list, using interrupts to jump between functions. As
  10  * all the functions are called within interrupts, we may not
  11  * sleep. Special care is recommended.
  12  * 
  13  *  modified by Drew Eckhardt to check nr of hd's from the CMOS.
  14  *
  15  *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
  16  *  in the early extended-partition checks and added DM partitions
  17  */
  18 
  19 
  20 #include <linux/errno.h>
  21 #include <linux/signal.h>
  22 #include <linux/sched.h>
  23 #include <linux/timer.h>
  24 #include <linux/fs.h>
  25 #include <linux/kernel.h>
  26 #include <linux/hdreg.h>
  27 #include <linux/genhd.h>
  28 #include <linux/config.h>
  29 
  30 #define REALLY_SLOW_IO
  31 #include <asm/system.h>
  32 #include <asm/io.h>
  33 #include <asm/segment.h>
  34 
  35 #define MAJOR_NR HD_MAJOR
  36 #include "blk.h"
  37 
  38 #define HD_IRQ 14
  39 
  40 static int revalidate_hddisk(int, int);
  41 
  42 static inline unsigned char CMOS_READ(unsigned char addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44         outb_p(addr,0x70);
  45         return inb_p(0x71);
  46 }
  47 
  48 #define HD_DELAY        0
  49 
  50 #define MAX_ERRORS     16       /* Max read/write errors/sector */
  51 #define RESET_FREQ      8       /* Reset controller every 8th retry */
  52 #define RECAL_FREQ      4       /* Recalibrate every 4th retry */
  53 #define MAX_HD          2
  54 
  55 static void recal_intr(void);
  56 static void bad_rw_intr(void);
  57 
  58 static char recalibrate[ MAX_HD ] = { 0, };
  59 static int access_count[MAX_HD] = {0, };
  60 static char busy[MAX_HD] = {0, };
  61 static struct wait_queue * busy_wait = NULL;
  62 
  63 static int reset = 0;
  64 static int hd_error = 0;
  65 
  66 #if (HD_DELAY > 0)
  67 unsigned long last_req, read_timer();
  68 #endif
  69 
  70 /*
  71  *  This struct defines the HD's and their types.
  72  */
  73 struct hd_i_struct {
  74         unsigned int head,sect,cyl,wpcom,lzone,ctl;
  75         };
  76 #ifdef HD_TYPE
  77 struct hd_i_struct hd_info[] = { HD_TYPE };
  78 static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
  79 #else
  80 struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
  81 static int NR_HD = 0;
  82 #endif
  83 
  84 static struct hd_struct hd[MAX_HD<<6]={{0,0},};
  85 static int hd_sizes[MAX_HD<<6] = {0, };
  86 static int hd_blocksizes[MAX_HD<<6] = {0, };
  87 
  88 #if (HD_DELAY > 0)
  89 unsigned long read_timer(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         unsigned long t;
  92         int i;
  93 
  94         cli();
  95         t = jiffies * 11932;
  96         outb_p(0, 0x43);
  97         i = inb_p(0x40);
  98         i |= inb(0x40) << 8;
  99         sti();
 100         return(t - i);
 101 }
 102 #endif
 103 
 104 void hd_setup(char *str, int *ints)
     /* [previous][next][first][last][top][bottom][index][help] */
 105 {
 106         int hdind = 0;
 107 
 108         if (ints[0] != 3)
 109                 return;
 110         if (hd_info[0].head != 0)
 111                 hdind=1;
 112         hd_info[hdind].head = ints[2];
 113         hd_info[hdind].sect = ints[3];
 114         hd_info[hdind].cyl = ints[1];
 115         hd_info[hdind].wpcom = 0;
 116         hd_info[hdind].lzone = ints[1];
 117         hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
 118         NR_HD = hdind+1;
 119 }
 120 
 121 static int win_result(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123         int i=inb_p(HD_STATUS);
 124 
 125         if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
 126                 == (READY_STAT | SEEK_STAT)) {
 127                 hd_error = 0;
 128                 return 0; /* ok */
 129         }
 130         printk("HD: win_result: status = 0x%02x\n",i);
 131         if (i&1) {
 132                 hd_error = inb(HD_ERROR);
 133                 printk("HD: win_result: error = 0x%02x\n",hd_error);
 134         }       
 135         return 1;
 136 }
 137 
 138 static int controller_busy(void);
 139 static int status_ok(void);
 140 
 141 static int controller_ready(unsigned int drive, unsigned int head)
     /* [previous][next][first][last][top][bottom][index][help] */
 142 {
 143         int retry = 100;
 144 
 145         do {
 146                 if (controller_busy() & BUSY_STAT)
 147                         return 0;
 148                 outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
 149                 if (status_ok())
 150                         return 1;
 151         } while (--retry);
 152         return 0;
 153 }
 154 
 155 static int status_ok(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157         unsigned char status = inb_p(HD_STATUS);
 158 
 159         if (status & BUSY_STAT)
 160                 return 1;
 161         if (status & WRERR_STAT)
 162                 return 0;
 163         if (!(status & READY_STAT))
 164                 return 0;
 165         if (!(status & SEEK_STAT))
 166                 return 0;
 167         return 1;
 168 }
 169 
 170 static int controller_busy(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172         int retries = 100000;
 173         unsigned char status;
 174 
 175         do {
 176                 status = inb_p(HD_STATUS);
 177         } while ((status & BUSY_STAT) && --retries);
 178         return status;
 179 }
 180 
 181 static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
     /* [previous][next][first][last][top][bottom][index][help] */
 182                 unsigned int head,unsigned int cyl,unsigned int cmd,
 183                 void (*intr_addr)(void))
 184 {
 185         unsigned short port;
 186 
 187         if (drive>1 || head>15)
 188                 panic("Trying to write bad sector");
 189 #if (HD_DELAY > 0)
 190         while (read_timer() - last_req < HD_DELAY)
 191                 /* nothing */;
 192 #endif
 193         if (reset)
 194                 return;
 195         if (!controller_ready(drive, head)) {
 196                 reset = 1;
 197                 return;
 198         }
 199         SET_INTR(intr_addr);
 200         outb_p(hd_info[drive].ctl,HD_CMD);
 201         port=HD_DATA;
 202         outb_p(hd_info[drive].wpcom>>2,++port);
 203         outb_p(nsect,++port);
 204         outb_p(sect,++port);
 205         outb_p(cyl,++port);
 206         outb_p(cyl>>8,++port);
 207         outb_p(0xA0|(drive<<4)|head,++port);
 208         outb_p(cmd,++port);
 209 }
 210 
 211 static int drive_busy(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 212 {
 213         unsigned int i;
 214         unsigned char c;
 215 
 216         for (i = 0; i < 500000 ; i++) {
 217                 c = inb_p(HD_STATUS);
 218                 c &= (BUSY_STAT | READY_STAT | SEEK_STAT);
 219                 if (c == (READY_STAT | SEEK_STAT))
 220                         return 0;
 221         }
 222         printk("HD controller times out, status = 0x%02x\n",c);
 223         return 1;
 224 }
 225 
 226 static void reset_controller(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 227 {
 228         int     i;
 229 
 230         printk(KERN_DEBUG "HD-controller reset\n");
 231         outb_p(4,HD_CMD);
 232         for(i = 0; i < 1000; i++) nop();
 233         outb(hd_info[0].ctl & 0x0f ,HD_CMD);
 234         if (drive_busy())
 235                 printk("HD-controller still busy\n");
 236         if ((hd_error = inb(HD_ERROR)) != 1)
 237                 printk("HD-controller reset failed: %02x\n",hd_error);
 238 }
 239 
 240 static void reset_hd(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 241 {
 242         static int i;
 243 
 244 repeat:
 245         if (reset) {
 246                 reset = 0;
 247                 i = -1;
 248                 reset_controller();
 249         } else if (win_result()) {
 250                 bad_rw_intr();
 251                 if (reset)
 252                         goto repeat;
 253         }
 254         i++;
 255         if (i < NR_HD) {
 256                 hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
 257                         hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
 258                 if (reset)
 259                         goto repeat;
 260         } else
 261                 do_hd_request();
 262 }
 263 
 264 /*
 265  * Ok, don't know what to do with the unexpected interrupts: on some machines
 266  * doing a reset and a retry seems to result in an eternal loop. Right now I
 267  * ignore it, and just set the timeout.
 268  */
 269 void unexpected_hd_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 270 {
 271         sti();
 272         printk(KERN_DEBUG "Unexpected HD interrupt\n");
 273         SET_TIMER;
 274 }
 275 
 276 /*
 277  * bad_rw_intr() now tries to be a bit smarter and does things
 278  * according to the error returned by the controller.
 279  * -Mika Liljeberg (liljeber@cs.Helsinki.FI)
 280  */
 281 static void bad_rw_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 282 {
 283         int dev;
 284 
 285         if (!CURRENT)
 286                 return;
 287         dev = MINOR(CURRENT->dev) >> 6;
 288         if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
 289                 end_request(0);
 290                 recalibrate[dev] = 1;
 291         } else if (CURRENT->errors % RESET_FREQ == 0)
 292                 reset = 1;
 293         else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
 294                 recalibrate[dev] = 1;
 295         /* Otherwise just retry */
 296 }
 297 
 298 static inline int wait_DRQ(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 299 {
 300         int retries = 100000;
 301 
 302         while (--retries > 0)
 303                 if (inb_p(HD_STATUS) & DRQ_STAT)
 304                         return 0;
 305         return -1;
 306 }
 307 
 308 #define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
 309 #define STAT_OK (READY_STAT | SEEK_STAT)
 310 
 311 static void read_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 312 {
 313         int i;
 314         int retries = 100000;
 315 
 316         do {
 317                 i = (unsigned) inb_p(HD_STATUS);
 318                 if (i & BUSY_STAT)
 319                         continue;
 320                 if ((i & STAT_MASK) != STAT_OK)
 321                         break;
 322                 if (i & DRQ_STAT)
 323                         goto ok_to_read;
 324         } while (--retries > 0);
 325         sti();
 326         printk("HD: read_intr: status = 0x%02x\n",i);
 327         if (i & ERR_STAT) {
 328                 hd_error = (unsigned) inb(HD_ERROR);
 329                 printk("HD: read_intr: error = 0x%02x\n",hd_error);
 330         }
 331         bad_rw_intr();
 332         cli();
 333         do_hd_request();
 334         return;
 335 ok_to_read:
 336         insw(HD_DATA,CURRENT->buffer,256);
 337         CURRENT->errors = 0;
 338         CURRENT->buffer += 512;
 339         CURRENT->sector++;
 340         i = --CURRENT->nr_sectors;
 341         --CURRENT->current_nr_sectors;
 342 #ifdef DEBUG
 343         printk("hd%d : sector = %d, %d remaining to buffer = %08x\n",
 344                 MINOR(CURRENT->dev), CURRENT->sector, i, CURRENT-> 
 345                 buffer);
 346 #endif
 347         if (!i || (CURRENT->bh && !SUBSECTOR(i)))
 348                 end_request(1);
 349         if (i > 0) {
 350                 SET_INTR(&read_intr);
 351                 sti();
 352                 return;
 353         }
 354         (void) inb_p(HD_STATUS);
 355 #if (HD_DELAY > 0)
 356         last_req = read_timer();
 357 #endif
 358         do_hd_request();
 359         return;
 360 }
 361 
 362 static void write_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 363 {
 364         int i;
 365         int retries = 100000;
 366 
 367         do {
 368                 i = (unsigned) inb_p(HD_STATUS);
 369                 if (i & BUSY_STAT)
 370                         continue;
 371                 if ((i & STAT_MASK) != STAT_OK)
 372                         break;
 373                 if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
 374                         goto ok_to_write;
 375         } while (--retries > 0);
 376         sti();
 377         printk("HD: write_intr: status = 0x%02x\n",i);
 378         if (i & ERR_STAT) {
 379                 hd_error = (unsigned) inb(HD_ERROR);
 380                 printk("HD: write_intr: error = 0x%02x\n",hd_error);
 381         }
 382         bad_rw_intr();
 383         cli();
 384         do_hd_request();
 385         return;
 386 ok_to_write:
 387         CURRENT->sector++;
 388         i = --CURRENT->nr_sectors;
 389         --CURRENT->current_nr_sectors;
 390         CURRENT->buffer += 512;
 391         if (!i || (CURRENT->bh && !SUBSECTOR(i)))
 392                 end_request(1);
 393         if (i > 0) {
 394                 SET_INTR(&write_intr);
 395                 outsw(HD_DATA,CURRENT->buffer,256);
 396                 sti();
 397         } else {
 398 #if (HD_DELAY > 0)
 399                 last_req = read_timer();
 400 #endif
 401                 do_hd_request();
 402         }
 403         return;
 404 }
 405 
 406 static void recal_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 407 {
 408         if (win_result())
 409                 bad_rw_intr();
 410         do_hd_request();
 411 }
 412 
 413 /*
 414  * This is another of the error-routines I don't know what to do with. The
 415  * best idea seems to just set reset, and start all over again.
 416  */
 417 static void hd_times_out(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 418 {
 419         DEVICE_INTR = NULL;
 420         sti();
 421         reset = 1;
 422         if (!CURRENT)
 423                 return;
 424         printk(KERN_DEBUG "HD timeout\n");
 425         cli();
 426         if (++CURRENT->errors >= MAX_ERRORS) {
 427 #ifdef DEBUG
 428                 printk("hd : too many errors.\n");
 429 #endif
 430                 end_request(0);
 431         }
 432 
 433         do_hd_request();
 434 }
 435 
 436 /*
 437  * The driver has been modified to enable interrupts a bit more: in order to
 438  * do this we first (a) disable the timeout-interrupt and (b) clear the
 439  * device-interrupt. This way the interrupts won't mess with out code (the
 440  * worst that can happen is that an unexpected HD-interrupt comes in and
 441  * sets the "reset" variable and starts the timer)
 442  */
 443 static void do_hd_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 444 {
 445         unsigned int block,dev;
 446         unsigned int sec,head,cyl,track;
 447         unsigned int nsect;
 448 
 449         if (CURRENT && CURRENT->dev < 0) return;
 450 
 451         if (DEVICE_INTR)
 452                 return;
 453 repeat:
 454         timer_active &= ~(1<<HD_TIMER);
 455         sti();
 456         INIT_REQUEST;
 457         dev = MINOR(CURRENT->dev);
 458         block = CURRENT->sector;
 459         nsect = CURRENT->nr_sectors;
 460         if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
 461 #ifdef DEBUG
 462                 printk("hd%d : attempted read for sector %d past end of device at sector %d.\n",
 463                         block, hd[dev].nr_sects);
 464 #endif
 465                 end_request(0);
 466                 goto repeat;
 467         }
 468         block += hd[dev].start_sect;
 469         dev >>= 6;
 470         sec = block % hd_info[dev].sect + 1;
 471         track = block / hd_info[dev].sect;
 472         head = track % hd_info[dev].head;
 473         cyl = track / hd_info[dev].head;
 474 #ifdef DEBUG
 475         printk("hd%d : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
 476                 dev, cyl, head, sec, CURRENT->buffer);
 477 #endif
 478         cli();
 479         if (reset) {
 480                 int i;
 481 
 482                 for (i=0; i < NR_HD; i++)
 483                         recalibrate[i] = 1;
 484                 reset_hd();
 485                 sti();
 486                 return;
 487         }
 488         if (recalibrate[dev]) {
 489                 recalibrate[dev] = 0;
 490                 hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
 491                 if (reset)
 492                         goto repeat;
 493                 sti();
 494                 return;
 495         }       
 496         if (CURRENT->cmd == WRITE) {
 497                 hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
 498                 if (reset)
 499                         goto repeat;
 500                 if (wait_DRQ()) {
 501                         printk("HD: do_hd_request: no DRQ\n");
 502                         bad_rw_intr();
 503                         goto repeat;
 504                 }
 505                 outsw(HD_DATA,CURRENT->buffer,256);
 506                 sti();
 507                 return;
 508         }
 509         if (CURRENT->cmd == READ) {
 510                 hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
 511                 if (reset)
 512                         goto repeat;
 513                 sti();
 514                 return;
 515         }
 516         panic("unknown hd-command");
 517 }
 518 
 519 static int hd_ioctl(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 520         unsigned int cmd, unsigned long arg)
 521 {
 522         struct hd_geometry *loc = (struct hd_geometry *) arg;
 523         int dev, err;
 524 
 525         if (!inode)
 526                 return -EINVAL;
 527         dev = MINOR(inode->i_rdev) >> 6;
 528         if (dev >= NR_HD)
 529                 return -EINVAL;
 530         switch (cmd) {
 531                 case HDIO_GETGEO:
 532                         if (!loc)  return -EINVAL;
 533                         err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
 534                         if (err)
 535                                 return err;
 536                         put_fs_byte(hd_info[dev].head,
 537                                 (char *) &loc->heads);
 538                         put_fs_byte(hd_info[dev].sect,
 539                                 (char *) &loc->sectors);
 540                         put_fs_word(hd_info[dev].cyl,
 541                                 (short *) &loc->cylinders);
 542                         put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
 543                                 (long *) &loc->start);
 544                         return 0;
 545                 case BLKGETSIZE:   /* Return device size */
 546                         if (!arg)  return -EINVAL;
 547                         err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
 548                         if (err)
 549                                 return err;
 550                         put_fs_long(hd[MINOR(inode->i_rdev)].nr_sects,
 551                                 (long *) arg);
 552                         return 0;
 553                 case BLKFLSBUF:
 554                         if(!suser())  return -EACCES;
 555                         if(!inode->i_rdev) return -EINVAL;
 556                         fsync_dev(inode->i_rdev);
 557                         invalidate_buffers(inode->i_rdev);
 558                         return 0;
 559 
 560                 case BLKRRPART: /* Re-read partition tables */
 561                         return revalidate_hddisk(inode->i_rdev, 1);
 562                 RO_IOCTLS(inode->i_rdev,arg);
 563                 default:
 564                         return -EINVAL;
 565         }
 566 }
 567 
 568 static int hd_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 569 {
 570         int target;
 571         target =  DEVICE_NR(MINOR(inode->i_rdev));
 572 
 573         while (busy[target])
 574                 sleep_on(&busy_wait);
 575         access_count[target]++;
 576         return 0;
 577 }
 578 
 579 /*
 580  * Releasing a block device means we sync() it, so that it can safely
 581  * be forgotten about...
 582  */
 583 static void hd_release(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 584 {
 585         int target;
 586         sync_dev(inode->i_rdev);
 587 
 588         target =  DEVICE_NR(MINOR(inode->i_rdev));
 589         access_count[target]--;
 590 
 591 }
 592 
 593 static void hd_geninit(void);
 594 
 595 static struct gendisk hd_gendisk = {
 596         MAJOR_NR,       /* Major number */      
 597         "hd",           /* Major name */
 598         6,              /* Bits to shift to get real from partition */
 599         1 << 6,         /* Number of partitions per real */
 600         MAX_HD,         /* maximum number of real */
 601         hd_geninit,     /* init function */
 602         hd,             /* hd struct */
 603         hd_sizes,       /* block sizes */
 604         0,              /* number */
 605         (void *) hd_info,       /* internal */
 606         NULL            /* next */
 607 };
 608         
 609 static void hd_interrupt(int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
 610 {
 611         void (*handler)(void) = DEVICE_INTR;
 612 
 613         DEVICE_INTR = NULL;
 614         timer_active &= ~(1<<HD_TIMER);
 615         if (!handler)
 616                 handler = unexpected_hd_interrupt;
 617         handler();
 618         sti();
 619 }
 620 
 621 /*
 622  * This is the harddisk IRQ description. The SA_INTERRUPT in sa_flags
 623  * means we run the IRQ-handler with interrupts disabled: this is bad for
 624  * interrupt latency, but anything else has led to problems on some
 625  * machines...
 626  *
 627  * We enable interrupts in some of the routines after making sure it's
 628  * safe.
 629  */
 630 static struct sigaction hd_sigaction = {
 631         hd_interrupt,
 632         0,
 633         SA_INTERRUPT,
 634         NULL
 635 };
 636 
 637 static void hd_geninit(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 638 {
 639         int drive, i;
 640         extern struct drive_info drive_info;
 641         unsigned char *BIOS = (unsigned char *) &drive_info;
 642         int cmos_disks;
 643 
 644         if (!NR_HD) {      
 645                 for (drive=0 ; drive<2 ; drive++) {
 646                         hd_info[drive].cyl = *(unsigned short *) BIOS;
 647                         hd_info[drive].head = *(2+BIOS);
 648                         hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
 649                         hd_info[drive].ctl = *(8+BIOS);
 650                         hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
 651                         hd_info[drive].sect = *(14+BIOS);
 652                         BIOS += 16;
 653                 }
 654 
 655         /*
 656                 We querry CMOS about hard disks : it could be that 
 657                 we have a SCSI/ESDI/etc controller that is BIOS
 658                 compatable with ST-506, and thus showing up in our
 659                 BIOS table, but not register compatable, and therefore
 660                 not present in CMOS.
 661 
 662                 Furthurmore, we will assume that our ST-506 drives
 663                 <if any> are the primary drives in the system, and 
 664                 the ones reflected as drive 1 or 2.
 665 
 666                 The first drive is stored in the high nibble of CMOS
 667                 byte 0x12, the second in the low nibble.  This will be
 668                 either a 4 bit drive type or 0xf indicating use byte 0x19 
 669                 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
 670 
 671                 Needless to say, a non-zero value means we have 
 672                 an AT controller hard disk for that drive.
 673 
 674                 
 675         */
 676 
 677                 if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
 678                         if (cmos_disks & 0x0f)
 679                                 NR_HD = 2;
 680                         else
 681                                 NR_HD = 1;
 682         }
 683         i = NR_HD;
 684         while (i-- > 0) {
 685                 hd[i<<6].nr_sects = 0;
 686                 if (hd_info[i].head > 16) {
 687                         printk("hd.c: ST-506 interface disk with more than 16 heads detected,\n");
 688                         printk("  probably due to non-standard sector translation. Giving up.\n");
 689                         printk("  (disk %d: cyl=%d, sect=%d, head=%d)\n", i,
 690                                 hd_info[i].cyl,
 691                                 hd_info[i].sect,
 692                                 hd_info[i].head);
 693                         if (i+1 == NR_HD)
 694                                 NR_HD--;
 695                         continue;
 696                 }
 697                 hd[i<<6].nr_sects = hd_info[i].head*
 698                                 hd_info[i].sect*hd_info[i].cyl;
 699         }
 700         if (NR_HD) {
 701                 if (irqaction(HD_IRQ,&hd_sigaction)) {
 702                         printk("hd.c: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
 703                         NR_HD = 0;
 704                 }
 705         }
 706         hd_gendisk.nr_real = NR_HD;
 707 
 708         for(i=0;i<(MAX_HD << 6);i++) hd_blocksizes[i] = 1024;
 709         blksize_size[MAJOR_NR] = hd_blocksizes;
 710 }
 711 
 712 static struct file_operations hd_fops = {
 713         NULL,                   /* lseek - default */
 714         block_read,             /* read - general block-dev read */
 715         block_write,            /* write - general block-dev write */
 716         NULL,                   /* readdir - bad */
 717         NULL,                   /* select */
 718         hd_ioctl,               /* ioctl */
 719         NULL,                   /* mmap */
 720         hd_open,                /* open */
 721         hd_release,             /* release */
 722         block_fsync             /* fsync */
 723 };
 724 
 725 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
 726 {
 727         if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
 728                 printk("Unable to get major %d for harddisk\n",MAJOR_NR);
 729                 return mem_start;
 730         }
 731         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 732         read_ahead[MAJOR_NR] = 8;               /* 8 sector (4kB) read-ahead */
 733         hd_gendisk.next = gendisk_head;
 734         gendisk_head = &hd_gendisk;
 735         timer_table[HD_TIMER].fn = hd_times_out;
 736         return mem_start;
 737 }
 738 
 739 #define DEVICE_BUSY busy[target]
 740 #define USAGE access_count[target]
 741 #define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl)
 742 /* We assume that the the bios parameters do not change, so the disk capacity
 743    will not change */
 744 #undef MAYBE_REINIT
 745 #define GENDISK_STRUCT hd_gendisk
 746 
 747 /*
 748  * This routine is called to flush all partitions and partition tables
 749  * for a changed scsi disk, and then re-read the new partition table.
 750  * If we are revalidating a disk because of a media change, then we
 751  * enter with usage == 0.  If we are using an ioctl, we automatically have
 752  * usage == 1 (we need an open channel to use an ioctl :-), so this
 753  * is our limit.
 754  */
 755 static int revalidate_hddisk(int dev, int maxusage)
     /* [previous][next][first][last][top][bottom][index][help] */
 756 {
 757         int target, major;
 758         struct gendisk * gdev;
 759         int max_p;
 760         int start;
 761         int i;
 762 
 763         target =  DEVICE_NR(MINOR(dev));
 764         gdev = &GENDISK_STRUCT;
 765 
 766         cli();
 767         if (DEVICE_BUSY || USAGE > maxusage) {
 768                 sti();
 769                 return -EBUSY;
 770         };
 771         DEVICE_BUSY = 1;
 772         sti();
 773 
 774         max_p = gdev->max_p;
 775         start = target << gdev->minor_shift;
 776         major = MAJOR_NR << 8;
 777 
 778         for (i=max_p - 1; i >=0 ; i--) {
 779                 sync_dev(major | start | i);
 780                 invalidate_inodes(major | start | i);
 781                 invalidate_buffers(major | start | i);
 782                 gdev->part[start+i].start_sect = 0;
 783                 gdev->part[start+i].nr_sects = 0;
 784         };
 785 
 786 #ifdef MAYBE_REINIT
 787         MAYBE_REINIT;
 788 #endif
 789 
 790         gdev->part[start].nr_sects = CAPACITY;
 791         resetup_one_dev(gdev, target);
 792 
 793         DEVICE_BUSY = 0;
 794         wake_up(&busy_wait);
 795         return 0;
 796 }
 797 

/* [previous][next][first][last][top][bottom][index][help] */