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

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