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 = controller_busy();
 144 
 145         if (status & BUSY_STAT)
 146                 return 0;
 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 (DEVICE_INTR)
 425                 return;
 426 repeat:
 427         timer_active &= ~(1<<HD_TIMER);
 428         sti();
 429         INIT_REQUEST;
 430         dev = MINOR(CURRENT->dev);
 431         block = CURRENT->sector;
 432         nsect = CURRENT->nr_sectors;
 433         if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
 434 #ifdef DEBUG
 435                 printk("hd%d : attempted read for sector %d past end of device at sector %d.\n",
 436                         block, hd[dev].nr_sects);
 437 #endif
 438                 end_request(0);
 439                 goto repeat;
 440         }
 441         block += hd[dev].start_sect;
 442         dev >>= 6;
 443         sec = block % hd_info[dev].sect + 1;
 444         track = block / hd_info[dev].sect;
 445         head = track % hd_info[dev].head;
 446         cyl = track / hd_info[dev].head;
 447 #ifdef DEBUG
 448         printk("hd%d : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
 449                 dev, cyl, head, sec, CURRENT->buffer);
 450 #endif
 451         cli();
 452         if (reset) {
 453                 int i;
 454 
 455                 for (i=0; i < NR_HD; i++)
 456                         recalibrate[i] = 1;
 457                 reset_hd();
 458                 sti();
 459                 return;
 460         }
 461         if (recalibrate[dev]) {
 462                 recalibrate[dev] = 0;
 463                 hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
 464                 if (reset)
 465                         goto repeat;
 466                 sti();
 467                 return;
 468         }       
 469         if (CURRENT->cmd == WRITE) {
 470                 hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
 471                 if (reset)
 472                         goto repeat;
 473                 if (wait_DRQ()) {
 474                         printk("HD: do_hd_request: no DRQ\n");
 475                         bad_rw_intr();
 476                         goto repeat;
 477                 }
 478                 port_write(HD_DATA,CURRENT->buffer,256);
 479                 sti();
 480                 return;
 481         }
 482         if (CURRENT->cmd == READ) {
 483                 hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
 484                 if (reset)
 485                         goto repeat;
 486                 sti();
 487                 return;
 488         }
 489         panic("unknown hd-command");
 490 }
 491 
 492 static int hd_ioctl(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 493         unsigned int cmd, unsigned int arg)
 494 {
 495         struct hd_geometry *loc = (void *) arg;
 496         int dev;
 497 
 498         if (!inode)
 499                 return -EINVAL;
 500         dev = MINOR(inode->i_rdev) >> 6;
 501         if (dev >= NR_HD)
 502                 return -EINVAL;
 503         switch (cmd) {
 504                 case HDIO_GETGEO:
 505                         if (!loc)  return -EINVAL;
 506                         verify_area(loc, sizeof(*loc));
 507                         put_fs_byte(hd_info[dev].head,
 508                                 (char *) &loc->heads);
 509                         put_fs_byte(hd_info[dev].sect,
 510                                 (char *) &loc->sectors);
 511                         put_fs_word(hd_info[dev].cyl,
 512                                 (short *) &loc->cylinders);
 513                         put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
 514                                 (long *) &loc->start);
 515                         return 0;
 516                 case BLKRRPART: /* Re-read partition tables */
 517                         return revalidate_hddisk(inode->i_rdev, 1);
 518                 RO_IOCTLS(inode->i_rdev,arg);
 519                 default:
 520                         return -EINVAL;
 521         }
 522 }
 523 
 524 static int hd_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 525 {
 526         int target;
 527         target =  DEVICE_NR(MINOR(inode->i_rdev));
 528 
 529         while (busy[target])
 530                 sleep_on(&busy_wait);
 531         access_count[target]++;
 532         return 0;
 533 }
 534 
 535 /*
 536  * Releasing a block device means we sync() it, so that it can safely
 537  * be forgotten about...
 538  */
 539 static void hd_release(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 540 {
 541         int target;
 542         sync_dev(inode->i_rdev);
 543 
 544         target =  DEVICE_NR(MINOR(inode->i_rdev));
 545         access_count[target]--;
 546 
 547 }
 548 
 549 static void hd_geninit();
 550 
 551 static struct gendisk hd_gendisk = {
 552         MAJOR_NR,       /* Major number */      
 553         "hd",           /* Major name */
 554         6,              /* Bits to shift to get real from partition */
 555         1 << 6,         /* Number of partitions per real */
 556         MAX_HD,         /* maximum number of real */
 557         hd_geninit,     /* init function */
 558         hd,             /* hd struct */
 559         hd_sizes,       /* block sizes */
 560         0,              /* number */
 561         (void *) hd_info,       /* internal */
 562         NULL            /* next */
 563 };
 564         
 565 static void hd_interrupt(int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
 566 {
 567         void (*handler)(void) = DEVICE_INTR;
 568 
 569         DEVICE_INTR = NULL;
 570         timer_active &= ~(1<<HD_TIMER);
 571         if (!handler)
 572                 handler = unexpected_hd_interrupt;
 573         handler();
 574         sti();
 575 }
 576 
 577 /*
 578  * This is the harddisk IRQ description. The SA_INTERRUPT in sa_flags
 579  * means we run the IRQ-handler with interrupts disabled: this is bad for
 580  * interrupt latency, but anything else has led to problems on some
 581  * machines...
 582  *
 583  * We enable interrupts in some of the routines after making sure it's
 584  * safe.
 585  */
 586 static struct sigaction hd_sigaction = {
 587         hd_interrupt,
 588         0,
 589         SA_INTERRUPT,
 590         NULL
 591 };
 592 
 593 static void hd_geninit(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 594 {
 595         int drive, i;
 596 #ifndef HD_TYPE
 597         extern struct drive_info drive_info;
 598         void *BIOS = (void *) &drive_info;
 599         int cmos_disks;
 600            
 601         for (drive=0 ; drive<2 ; drive++) {
 602                 hd_info[drive].cyl = *(unsigned short *) BIOS;
 603                 hd_info[drive].head = *(unsigned char *) (2+BIOS);
 604                 hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
 605                 hd_info[drive].ctl = *(unsigned char *) (8+BIOS);
 606                 hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
 607                 hd_info[drive].sect = *(unsigned char *) (14+BIOS);
 608                 BIOS += 16;
 609         }
 610 
 611         /*
 612                 We querry CMOS about hard disks : it could be that 
 613                 we have a SCSI/ESDI/etc controller that is BIOS
 614                 compatable with ST-506, and thus showing up in our
 615                 BIOS table, but not register compatable, and therefore
 616                 not present in CMOS.
 617 
 618                 Furthurmore, we will assume that our ST-506 drives
 619                 <if any> are the primary drives in the system, and 
 620                 the ones reflected as drive 1 or 2.
 621 
 622                 The first drive is stored in the high nibble of CMOS
 623                 byte 0x12, the second in the low nibble.  This will be
 624                 either a 4 bit drive type or 0xf indicating use byte 0x19 
 625                 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
 626 
 627                 Needless to say, a non-zero value means we have 
 628                 an AT controller hard disk for that drive.
 629 
 630                 
 631         */
 632 
 633         if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
 634                 if (cmos_disks & 0x0f)
 635                         NR_HD = 2;
 636                 else
 637                         NR_HD = 1;
 638         else
 639                 NR_HD = 0;
 640 #endif
 641         if (NR_HD) {
 642                 if (irqaction(HD_IRQ,&hd_sigaction)) {
 643                         printk("Unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
 644                         NR_HD = 0;
 645                 }
 646         }
 647         for (i = 0 ; i < NR_HD ; i++)
 648                 hd[i<<6].nr_sects = hd_info[i].head*
 649                                 hd_info[i].sect*hd_info[i].cyl;
 650 
 651         hd_gendisk.nr_real = NR_HD;
 652 }
 653 
 654 static struct file_operations hd_fops = {
 655         NULL,                   /* lseek - default */
 656         block_read,             /* read - general block-dev read */
 657         block_write,            /* write - general block-dev write */
 658         NULL,                   /* readdir - bad */
 659         NULL,                   /* select */
 660         hd_ioctl,               /* ioctl */
 661         NULL,                   /* mmap */
 662         hd_open,                /* open */
 663         hd_release              /* release */
 664 };
 665 
 666 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
 667 {
 668         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 669         blkdev_fops[MAJOR_NR] = &hd_fops;
 670         hd_gendisk.next = gendisk_head;
 671         gendisk_head = &hd_gendisk;
 672         timer_table[HD_TIMER].fn = hd_times_out;
 673         return mem_start;
 674 }
 675 
 676 #define DEVICE_BUSY busy[target]
 677 #define USAGE access_count[target]
 678 #define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl)
 679 /* We assume that the the bios parameters do not change, so the disk capacity
 680    will not change */
 681 #undef MAYBE_REINIT
 682 #define GENDISK_STRUCT hd_gendisk
 683 
 684 /*
 685  * This routine is called to flush all partitions and partition tables
 686  * for a changed scsi disk, and then re-read the new partition table.
 687  * If we are revalidating a disk because of a media change, then we
 688  * enter with usage == 0.  If we are using an ioctl, we automatically have
 689  * usage == 1 (we need an open channel to use an ioctl :-), so this
 690  * is our limit.
 691  */
 692 static int revalidate_hddisk(int dev, int maxusage)
     /* [previous][next][first][last][top][bottom][index][help] */
 693 {
 694         int target, major;
 695         struct gendisk * gdev;
 696         int max_p;
 697         int start;
 698         int i;
 699 
 700         target =  DEVICE_NR(MINOR(dev));
 701         gdev = &GENDISK_STRUCT;
 702 
 703         cli();
 704         if (DEVICE_BUSY || USAGE > maxusage) {
 705                 sti();
 706                 return -EBUSY;
 707         };
 708         DEVICE_BUSY = 1;
 709         sti();
 710 
 711         max_p = gdev->max_p;
 712         start = target << gdev->minor_shift;
 713         major = MAJOR_NR << 8;
 714 
 715         for (i=max_p - 1; i >=0 ; i--) {
 716                 sync_dev(major | start | i);
 717                 invalidate_inodes(major | start | i);
 718                 invalidate_buffers(major | start | i);
 719                 gdev->part[i].start_sect = 0;
 720                 gdev->part[i].nr_sects = 0;
 721         };
 722 
 723 #ifdef MAYBE_REINIT
 724         MAYBE_REINIT;
 725 #endif
 726 
 727         gdev->part[start].nr_sects = CAPACITY;
 728         resetup_one_dev(gdev, target);
 729 
 730         DEVICE_BUSY = 0;
 731         wake_up(&busy_wait);
 732         return 0;
 733 }
 734 
 735 #endif

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