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

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