root/kernel/blk_drv/hd.c

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

DEFINITIONS

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

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