root/drivers/block/hd.c

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

DEFINITIONS

This source file includes following definitions.
  1. CMOS_READ
  2. read_timer
  3. hd_setup
  4. win_result
  5. controller_ready
  6. status_ok
  7. controller_busy
  8. hd_out
  9. fixstring
  10. identify_intr
  11. set_multmode_intr
  12. drive_busy
  13. reset_controller
  14. reset_hd
  15. unexpected_hd_interrupt
  16. bad_rw_intr
  17. wait_DRQ
  18. read_intr
  19. multwrite
  20. multwrite_intr
  21. write_intr
  22. recal_intr
  23. hd_times_out
  24. hd_request
  25. do_hd_request
  26. hd_ioctl
  27. hd_open
  28. hd_release
  29. hd_interrupt
  30. hd_geninit
  31. hd_init
  32. 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  *  IDE IRQ-unmask & drive-id & multiple-mode code added by Mark Lord.
  19  *
  20  *  Support for BIOS drive geometry translation added by Mark Lord.
  21  *   -- hd.c no longer chokes on drives with "more than 16 heads".
  22  */
  23 
  24 #define DEFAULT_MULT_COUNT  0   /* set to 0 to disable multiple mode at boot */
  25 #define DEFAULT_UNMASK_INTR 0   /* set to 0 to *NOT* unmask irq's more often */
  26 
  27 #include <asm/irq.h>
  28 #include <linux/errno.h>
  29 #include <linux/signal.h>
  30 #include <linux/sched.h>
  31 #include <linux/timer.h>
  32 #include <linux/fs.h>
  33 #include <linux/kernel.h>
  34 #include <linux/hdreg.h>
  35 #include <linux/genhd.h>
  36 #include <linux/config.h>
  37 #include <linux/malloc.h>
  38 #include <linux/string.h>
  39 
  40 #define REALLY_SLOW_IO
  41 #include <asm/system.h>
  42 #include <asm/io.h>
  43 #include <asm/segment.h>
  44 
  45 #define MAJOR_NR HD_MAJOR
  46 #include "blk.h"
  47 
  48 #define HD_IRQ 14
  49 
  50 static int revalidate_hddisk(int, int);
  51 
  52 static inline unsigned char CMOS_READ(unsigned char addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54         outb_p(addr,0x70);
  55         return inb_p(0x71);
  56 }
  57 
  58 #define HD_DELAY        0
  59 
  60 #define MAX_ERRORS     16       /* Max read/write errors/sector */
  61 #define RESET_FREQ      8       /* Reset controller every 8th retry */
  62 #define RECAL_FREQ      4       /* Recalibrate every 4th retry */
  63 #define MAX_HD          2
  64 
  65 static void recal_intr(void);
  66 static void bad_rw_intr(void);
  67 
  68 static char recalibrate[MAX_HD] = { 0, };
  69 static char special_op[MAX_HD] = { 0, };
  70 static int access_count[MAX_HD] = {0, };
  71 static char busy[MAX_HD] = {0, };
  72 static struct wait_queue * busy_wait = NULL;
  73 
  74 static int reset = 0;
  75 static int hd_error = 0;
  76 
  77 /*
  78  *  This struct defines the HD's and their types.
  79  */
  80 struct hd_i_struct {
  81         unsigned int head,sect,cyl,wpcom,lzone,ctl;
  82         };
  83 static struct hd_driveid *hd_ident_info[MAX_HD];
  84         
  85 #ifdef HD_TYPE
  86 static struct hd_i_struct hd_info[] = { HD_TYPE };
  87 struct hd_i_struct bios_info[] = { HD_TYPE };
  88 static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
  89 #else
  90 static struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
  91 struct hd_i_struct bios_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
  92 static int NR_HD = 0;
  93 #endif
  94 
  95 static struct hd_struct hd[MAX_HD<<6]={{0,0},};
  96 static int hd_sizes[MAX_HD<<6] = {0, };
  97 static int hd_blocksizes[MAX_HD<<6] = {0, };
  98 
  99 #if (HD_DELAY > 0)
 100 unsigned long last_req;
 101 
 102 unsigned long read_timer(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 103 {
 104         unsigned long t, flags;
 105         int i;
 106 
 107         save_flags(flags);
 108         cli();
 109         t = jiffies * 11932;
 110         outb_p(0, 0x43);
 111         i = inb_p(0x40);
 112         i |= inb(0x40) << 8;
 113         restore_flags(flags);
 114         return(t - i);
 115 }
 116 #endif
 117 
 118 void hd_setup(char *str, int *ints)
     /* [previous][next][first][last][top][bottom][index][help] */
 119 {
 120         int hdind = 0;
 121 
 122         if (ints[0] != 3)
 123                 return;
 124         if (bios_info[0].head != 0)
 125                 hdind=1;
 126         bios_info[hdind].head  = hd_info[hdind].head = ints[2];
 127         bios_info[hdind].sect  = hd_info[hdind].sect = ints[3];
 128         bios_info[hdind].cyl   = hd_info[hdind].cyl = ints[1];
 129         bios_info[hdind].wpcom = hd_info[hdind].wpcom = 0;
 130         bios_info[hdind].lzone = hd_info[hdind].lzone = ints[1];
 131         bios_info[hdind].ctl   = hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
 132         NR_HD = hdind+1;
 133 }
 134 
 135 static int win_result(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 136 {
 137         int i=inb_p(HD_STATUS);
 138 
 139         if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
 140                 == (READY_STAT | SEEK_STAT)) {
 141                 hd_error = 0;
 142                 return 0; /* ok */
 143         }
 144         printk("HD: win_result: status = 0x%02x\n",i);
 145         if (i&1) {
 146                 hd_error = inb(HD_ERROR);
 147                 printk("HD: win_result: error = 0x%02x\n",hd_error);
 148         }       
 149         return 1;
 150 }
 151 
 152 static int controller_busy(void);
 153 static int status_ok(void);
 154 
 155 static int controller_ready(unsigned int drive, unsigned int head)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157         int retry = 100;
 158 
 159         do {
 160                 if (controller_busy() & BUSY_STAT)
 161                         return 0;
 162                 outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
 163                 if (status_ok())
 164                         return 1;
 165         } while (--retry);
 166         return 0;
 167 }
 168 
 169 static int status_ok(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 170 {
 171         unsigned char status = inb_p(HD_STATUS);
 172 
 173         if (status & BUSY_STAT)
 174                 return 1;
 175         if (status & WRERR_STAT)
 176                 return 0;
 177         if (!(status & READY_STAT))
 178                 return 0;
 179         if (!(status & SEEK_STAT))
 180                 return 0;
 181         return 1;
 182 }
 183 
 184 static int controller_busy(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186         int retries = 100000;
 187         unsigned char status;
 188 
 189         do {
 190                 status = inb_p(HD_STATUS);
 191         } while ((status & BUSY_STAT) && --retries);
 192         return status;
 193 }
 194 
 195 static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
     /* [previous][next][first][last][top][bottom][index][help] */
 196                 unsigned int head,unsigned int cyl,unsigned int cmd,
 197                 void (*intr_addr)(void))
 198 {
 199         unsigned short port;
 200 
 201 #ifdef DEBUG
 202         if (drive>1 || head>15) {
 203                 printk("bad drive mapping, trying to access drive=%d, cyl=%d, head=%d, sect=%d\n",
 204                         drive, cyl, head, sect);
 205                 panic("harddisk driver problem");
 206         }
 207 #endif
 208 #if (HD_DELAY > 0)
 209         while (read_timer() - last_req < HD_DELAY)
 210                 /* nothing */;
 211 #endif
 212         if (reset)
 213                 return;
 214         if (!controller_ready(drive, head)) {
 215                 special_op[drive] += reset = 1;
 216                 return;
 217         }
 218         SET_INTR(intr_addr);
 219         outb_p(hd_info[drive].ctl,HD_CMD);
 220         port=HD_DATA;
 221         outb_p(hd_info[drive].wpcom>>2,++port);
 222         outb_p(nsect,++port);
 223         outb_p(sect,++port);
 224         outb_p(cyl,++port);
 225         outb_p(cyl>>8,++port);
 226         outb_p(0xA0|(drive<<4)|head,++port);
 227         outb_p(cmd,++port);
 228 }
 229 
 230 static void hd_request (void);
 231 static unsigned int identified  [MAX_HD] = {0,}; /* 1 = drive ID already displayed   */
 232 static unsigned int unmask_intr [MAX_HD] = {0,}; /* 1 = unmask IRQs during I/O       */
 233 static unsigned int max_mult    [MAX_HD] = {0,}; /* max sectors for MultMode         */
 234 static unsigned int mult_req    [MAX_HD] = {0,}; /* requested MultMode count         */
 235 static unsigned int mult_count  [MAX_HD] = {0,}; /* currently enabled MultMode count */
 236 static struct request WCURRENT;
 237 
 238 static void fixstring(unsigned char *s, int n)
     /* [previous][next][first][last][top][bottom][index][help] */
 239 {
 240         int i;
 241         unsigned short *ss = (unsigned short *) s;
 242 
 243         /* convert from big-endian to little-endian */
 244         for (i = n ; (i -= 2) >= 0 ; ss++)
 245                 *ss = (*ss >> 8) | (*ss << 8);
 246 
 247         /* "strnlen()" */
 248         for (i = 0 ; i < n ; i++) {
 249                 if (!s[i]) {
 250                         n = i;
 251                         break;
 252                 }
 253         }
 254 
 255         /* wipe out trailing spaces */
 256         while (n > 0) {
 257                 if (s[n-1] != ' ')
 258                         break;
 259                 n--;
 260                 s[n] = '\0';
 261         }
 262 
 263         /* wipe out leading spaces */
 264         if (*s == ' ') {
 265                 unsigned char *t = s;
 266                 while (n-- && *++s == ' ');
 267                 while (n-- >= 0) {
 268                         *t++ = *s;
 269                         *s++ = '\0';
 270                 }
 271         }
 272 }
 273 
 274 static void identify_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 275 {
 276         unsigned int dev = DEVICE_NR(CURRENT->dev);
 277         unsigned short stat = inb_p(HD_STATUS);
 278         struct hd_driveid id;
 279 
 280         if (unmask_intr[dev])
 281                 sti();
 282         if (stat & (BUSY_STAT|ERR_STAT))
 283                 printk ("  hd%c: identity unknown\n", dev+'a');
 284         else {
 285                 insw(HD_DATA, (char *)&id, sizeof(id)/2); /* get ID bytes */
 286                 max_mult[dev] = id.max_multsect;
 287                 if ((id.cur_valid&1) && id.cur_cyls && id.cur_heads && (id.cur_heads <= 16) && id.cur_sectors) {
 288                         /*
 289                          * Extract the physical drive geometry for our use.
 290                          * Note that we purposely do *not* update the bios_info.
 291                          * This way, programs that use it (like fdisk) will 
 292                          * still have the same logical view as the BIOS does,
 293                          * which keeps the partition table from being screwed.
 294                          */
 295                         hd_info[dev].cyl  = id.cur_cyls;
 296                         hd_info[dev].head = id.cur_heads;
 297                         hd_info[dev].sect = id.cur_sectors; 
 298                 }
 299                 fixstring (id.serial_no, sizeof(id.serial_no));
 300                 fixstring (id.fw_rev, sizeof(id.fw_rev));
 301                 fixstring (id.model, sizeof(id.model));
 302                 printk ("  hd%c: %.40s, %dMB w/%dKB Cache, CHS=%d/%d/%d, MaxMult=%d\n",
 303                         dev+'a', id.model, id.cyls*id.heads*id.sectors/2048,
 304                         id.buf_size/2, hd_info[dev].cyl, hd_info[dev].head,
 305                         hd_info[dev].sect, id.max_multsect);
 306                 /* save drive info for later query via HDIO_GETIDENTITY */
 307                 if (NULL != (hd_ident_info[dev] = (struct hd_driveid *)kmalloc(sizeof(id),GFP_ATOMIC)))
 308                         *hd_ident_info[dev] = id;
 309                 
 310                 /* Quantum drives go weird at this point, so reset them! */
 311                 /* In fact, we should probably do a reset in any case in */
 312                 /* case we changed the geometry */
 313                 if (!strncmp(id.model, "QUANTUM", 7))
 314                         special_op[dev] += reset = 1;
 315 
 316                 /* flush remaining 384 (reserved/undefined) ID bytes: */
 317                 insw(HD_DATA,(char *)&id,sizeof(id)/2);
 318                 insw(HD_DATA,(char *)&id,sizeof(id)/2);
 319                 insw(HD_DATA,(char *)&id,sizeof(id)/2);
 320         }
 321 #if (HD_DELAY > 0)
 322         last_req = read_timer();
 323 #endif
 324         hd_request();
 325         return;
 326 }
 327 
 328 static void set_multmode_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 329 {
 330         unsigned int dev = DEVICE_NR(CURRENT->dev), stat = inb_p(HD_STATUS);
 331 
 332         if (unmask_intr[dev])
 333                 sti();
 334         if (stat & (BUSY_STAT|ERR_STAT)) {
 335                 mult_req[dev] = mult_count[dev] = 0;
 336                 printk ("  hd%c: set multiple mode failed\n", dev+'a');
 337         } else {
 338                 if ((mult_count[dev] = mult_req[dev]))
 339                         printk ("  hd%c: enabled %d-sector multiple mode\n",
 340                                 dev+'a', mult_count[dev]);
 341                 else
 342                         printk ("  hd%c: disabled multiple mode\n", dev+'a');
 343         }
 344 #if (HD_DELAY > 0)
 345         last_req = read_timer();
 346 #endif
 347         hd_request();
 348         return;
 349 }
 350 
 351 static int drive_busy(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 352 {
 353         unsigned int i;
 354         unsigned char c;
 355 
 356         for (i = 0; i < 500000 ; i++) {
 357                 c = inb_p(HD_STATUS);
 358                 c &= (BUSY_STAT | READY_STAT | SEEK_STAT);
 359                 if (c == (READY_STAT | SEEK_STAT))
 360                         return 0;
 361         }
 362         printk("HD controller times out, status = 0x%02x\n",c);
 363         return 1;
 364 }
 365 
 366 static void reset_controller(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 367 {
 368         int     i;
 369 
 370         outb_p(4,HD_CMD);
 371         for(i = 0; i < 1000; i++) nop();
 372         outb_p(hd_info[0].ctl & 0x0f,HD_CMD);
 373         for(i = 0; i < 1000; i++) nop();
 374         if (drive_busy())
 375                 printk("HD-controller still busy\n");
 376         if ((hd_error = inb(HD_ERROR)) != 1)
 377                 printk("HD-controller reset failed: %02x\n",hd_error);
 378 }
 379 
 380 static void reset_hd(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 381 {
 382         static int i;
 383 
 384 repeat:
 385         if (reset) {
 386                 reset = 0;
 387                 i = -1;
 388                 reset_controller();
 389         } else if (win_result()) {
 390                 bad_rw_intr();
 391                 if (reset)
 392                         goto repeat;
 393         }
 394         if (++i < NR_HD) {
 395                 if (unmask_intr[i]) {
 396                         unmask_intr[i] = DEFAULT_UNMASK_INTR;
 397                         printk("hd%c: reset irq-unmasking to %d\n",i+'a',
 398                                 DEFAULT_UNMASK_INTR);
 399                 }
 400                 if (mult_req[i] || mult_count[i]) {
 401                         mult_count[i] = 0;
 402                         mult_req[i] = DEFAULT_MULT_COUNT;
 403                         printk("hd%c: reset multiple mode to %d\n",i+'a',
 404                                 DEFAULT_MULT_COUNT);
 405                 }
 406                 hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
 407                         hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
 408                 if (reset)
 409                         goto repeat;
 410         } else
 411                 hd_request();
 412 }
 413 
 414 /*
 415  * Ok, don't know what to do with the unexpected interrupts: on some machines
 416  * doing a reset and a retry seems to result in an eternal loop. Right now I
 417  * ignore it, and just set the timeout.
 418  */
 419 void unexpected_hd_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 420 {
 421         sti();
 422         printk(KERN_DEBUG "Unexpected HD interrupt\n");
 423         SET_TIMER;
 424 }
 425 
 426 /*
 427  * bad_rw_intr() now tries to be a bit smarter and does things
 428  * according to the error returned by the controller.
 429  * -Mika Liljeberg (liljeber@cs.Helsinki.FI)
 430  */
 431 static void bad_rw_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 432 {
 433         int dev;
 434 
 435         if (!CURRENT)
 436                 return;
 437         dev = DEVICE_NR(CURRENT->dev);
 438         if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
 439                 end_request(0);
 440                 special_op[dev] += recalibrate[dev] = 1;
 441         } else if (CURRENT->errors % RESET_FREQ == 0)
 442                 special_op[dev] += reset = 1;
 443         else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
 444                 special_op[dev] += recalibrate[dev] = 1;
 445         /* Otherwise just retry */
 446 }
 447 
 448 static inline int wait_DRQ(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 449 {
 450         int retries = 100000;
 451 
 452         while (--retries > 0)
 453                 if (inb_p(HD_STATUS) & DRQ_STAT)
 454                         return 0;
 455         return -1;
 456 }
 457 
 458 #define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
 459 #define STAT_OK (READY_STAT | SEEK_STAT)
 460 
 461 static void read_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 462 {
 463         unsigned int dev = DEVICE_NR(CURRENT->dev);
 464         int i, retries = 100000, msect = mult_count[dev], nsect;
 465 
 466         if (unmask_intr[dev])
 467                 sti();                  /* permit other IRQs during xfer */
 468         do {
 469                 i = (unsigned) inb_p(HD_STATUS);
 470                 if (i & BUSY_STAT)
 471                         continue;
 472                 if ((i & STAT_MASK) != STAT_OK)
 473                         break;
 474                 if (i & DRQ_STAT)
 475                         goto ok_to_read;
 476         } while (--retries > 0);
 477         sti();
 478         printk("hd%c: read_intr: status = 0x%02x\n",dev+'a',i);
 479         if (i & ERR_STAT) {
 480                 hd_error = (unsigned) inb(HD_ERROR);
 481                 printk("hd%c: read_intr: error = 0x%02x\n",dev+'a',hd_error);
 482         }
 483         bad_rw_intr();
 484         cli();
 485         hd_request();
 486         return;
 487 ok_to_read:
 488         if (msect) {
 489                 if ((nsect = CURRENT->current_nr_sectors) > msect)
 490                         nsect = msect;
 491                 msect -= nsect;
 492         } else
 493                 nsect = 1;
 494         insw(HD_DATA,CURRENT->buffer,nsect<<8);
 495         CURRENT->sector += nsect;
 496         CURRENT->buffer += nsect<<9;
 497         CURRENT->errors = 0;
 498         i = (CURRENT->nr_sectors -= nsect);
 499 
 500 #ifdef DEBUG
 501         printk("hd%c: read: sectors(%ld-%ld), remaining=%ld, buffer=%08lx\n",
 502                 dev+'a', CURRENT->sector, CURRENT->sector+nsect,
 503                 CURRENT->nr_sectors, (long) CURRENT->buffer+(nsect<<9));
 504 #endif
 505         if ((CURRENT->current_nr_sectors -= nsect) <= 0)
 506                 end_request(1);
 507         if (i > 0) {
 508                 if (msect)
 509                         goto ok_to_read;
 510                 SET_INTR(&read_intr);
 511                 return;
 512         }
 513         (void) inb_p(HD_STATUS);
 514 #if (HD_DELAY > 0)
 515         last_req = read_timer();
 516 #endif
 517         if (CURRENT)
 518                 hd_request();
 519         return;
 520 }
 521 
 522 static inline void multwrite (unsigned int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 523 {
 524         unsigned int mcount = mult_count[dev];
 525 
 526         while (mcount--) {
 527                 outsw(HD_DATA,WCURRENT.buffer,256);
 528                 if (!--WCURRENT.nr_sectors)
 529                         return;
 530                 WCURRENT.buffer += 512;
 531                 if (!--WCURRENT.current_nr_sectors) {
 532                         WCURRENT.bh = WCURRENT.bh->b_reqnext;
 533                         if (WCURRENT.bh == NULL)
 534                                 panic("buffer list corrupted\n");
 535                         WCURRENT.current_nr_sectors = WCURRENT.bh->b_size>>9;
 536                         WCURRENT.buffer             = WCURRENT.bh->b_data;
 537                 }
 538         }
 539 }
 540 
 541 static void multwrite_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 542 {
 543         int i;
 544         unsigned int dev = DEVICE_NR(WCURRENT.dev);
 545 
 546         if (unmask_intr[dev])
 547                 sti();
 548         if (((i = inb_p(HD_STATUS)) & STAT_MASK) == STAT_OK) {
 549                 if (i & DRQ_STAT) {
 550                         if (WCURRENT.nr_sectors) {
 551                                 multwrite(dev);
 552                                 SET_INTR(&multwrite_intr);
 553                                 return;
 554                         }
 555                 } else {
 556                         if (!WCURRENT.nr_sectors) {     /* all done? */
 557                                 for (i = CURRENT->nr_sectors; i > 0;){
 558                                         i -= CURRENT->current_nr_sectors;
 559                                         end_request(1);
 560                                 }
 561 #if (HD_DELAY > 0)
 562                                 last_req = read_timer();
 563 #endif
 564                                 if (CURRENT)
 565                                         hd_request();
 566                                 return;
 567                         }
 568                 }
 569         }
 570         sti();
 571         printk("hd%c: multwrite_intr: status = 0x%02x\n",dev+'a',i);
 572         if (i & ERR_STAT) {
 573                 hd_error = (unsigned) inb(HD_ERROR);
 574                 printk("hd:%c multwrite_intr: error = 0x%02x\n",dev+'a',hd_error);
 575         }
 576         bad_rw_intr();
 577         cli();
 578         hd_request();
 579 }
 580 
 581 static void write_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 582 {
 583         int i;
 584         int retries = 100000;
 585 
 586         if (unmask_intr[DEVICE_NR(WCURRENT.dev)])
 587                 sti();
 588         do {
 589                 i = (unsigned) inb_p(HD_STATUS);
 590                 if (i & BUSY_STAT)
 591                         continue;
 592                 if ((i & STAT_MASK) != STAT_OK)
 593                         break;
 594                 if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
 595                         goto ok_to_write;
 596         } while (--retries > 0);
 597         sti();
 598         printk("HD: write_intr: status = 0x%02x\n",i);
 599         if (i & ERR_STAT) {
 600                 hd_error = (unsigned) inb(HD_ERROR);
 601                 printk("HD: write_intr: error = 0x%02x\n",hd_error);
 602         }
 603         bad_rw_intr();
 604         cli();
 605         hd_request();
 606         return;
 607 ok_to_write:
 608         CURRENT->sector++;
 609         i = --CURRENT->nr_sectors;
 610         --CURRENT->current_nr_sectors;
 611         CURRENT->buffer += 512;
 612         if (!i || (CURRENT->bh && !SUBSECTOR(i)))
 613                 end_request(1);
 614         if (i > 0) {
 615                 SET_INTR(&write_intr);
 616                 outsw(HD_DATA,CURRENT->buffer,256);
 617                 sti();
 618         } else {
 619 #if (HD_DELAY > 0)
 620                 last_req = read_timer();
 621 #endif
 622                 hd_request();
 623         }
 624         return;
 625 }
 626 
 627 static void recal_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 628 {
 629         if (win_result())
 630                 bad_rw_intr();
 631 #if (HD_DELAY > 0)
 632         last_req = read_timer();
 633 #endif
 634         hd_request();
 635 }
 636 
 637 /*
 638  * This is another of the error-routines I don't know what to do with. The
 639  * best idea seems to just set reset, and start all over again.
 640  */
 641 static void hd_times_out(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 642 {
 643         DEVICE_INTR = NULL;
 644         sti();
 645         if (!CURRENT)
 646                 return;
 647         special_op [DEVICE_NR(CURRENT->dev)] += reset = 1;
 648         printk(KERN_DEBUG "HD timeout\n");
 649         cli();
 650         if (++CURRENT->errors >= MAX_ERRORS) {
 651 #ifdef DEBUG
 652                 printk("hd : too many errors.\n");
 653 #endif
 654                 end_request(0);
 655         }
 656 
 657         hd_request();
 658 }
 659 
 660 /*
 661  * The driver has been modified to enable interrupts a bit more: in order to
 662  * do this we first (a) disable the timeout-interrupt and (b) clear the
 663  * device-interrupt. This way the interrupts won't mess with out code (the
 664  * worst that can happen is that an unexpected HD-interrupt comes in and
 665  * sets the "reset" variable and starts the timer)
 666  */
 667 static void hd_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 668 {
 669         unsigned int block,dev;
 670         unsigned int sec,head,cyl,track;
 671         unsigned int nsect;
 672 
 673         if (CURRENT && CURRENT->dev < 0) return;
 674 
 675         if (DEVICE_INTR)
 676                 return;
 677 repeat:
 678         timer_active &= ~(1<<HD_TIMER);
 679         sti();
 680         INIT_REQUEST;
 681         dev = MINOR(CURRENT->dev);
 682         block = CURRENT->sector;
 683         nsect = CURRENT->nr_sectors;
 684         if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
 685 #ifdef DEBUG
 686                 printk("hd : attempted read for sector %d past end of device at sector %d.\n",
 687                         block, hd[dev].nr_sects);
 688 #endif
 689                 end_request(0);
 690                 goto repeat;
 691         }
 692         block += hd[dev].start_sect;
 693         dev >>= 6;
 694         sec = block % hd_info[dev].sect + 1;
 695         track = block / hd_info[dev].sect;
 696         head = track % hd_info[dev].head;
 697         cyl = track / hd_info[dev].head;
 698 #ifdef DEBUG
 699         printk("hd%c : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
 700                 dev+'a', cyl, head, sec, CURRENT->buffer);
 701 #endif
 702         if (!unmask_intr[dev])
 703                 cli();
 704         if (special_op[dev]) {  /* we use "special_op" to reduce overhead on r/w */
 705                 if (reset) {
 706                         int i;
 707         
 708                         for (i=0; i < NR_HD; i++)
 709                                 special_op[i] = recalibrate[i] = 1;
 710                         cli(); /* better play it safe, as resets are the last resort */
 711                         reset_hd();
 712                         return;
 713                 }
 714                 if (recalibrate[dev]) {
 715                         recalibrate[dev] = 0;
 716                         hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
 717                         if (reset)
 718                                 goto repeat;
 719                         return;
 720                 }       
 721                 if (!identified[dev]) {
 722                         identified[dev]  = 1;
 723                         unmask_intr[dev] = DEFAULT_UNMASK_INTR;
 724                         mult_req[dev]    = DEFAULT_MULT_COUNT;
 725                         hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
 726                         if (reset)
 727                                 goto repeat;
 728                         return;
 729                 }
 730                 if (mult_req[dev] != mult_count[dev]) {
 731                         hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
 732                         if (reset)
 733                                 goto repeat;
 734                         return;
 735                 }
 736                 if (hd_info[dev].head > 16) {
 737                         printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
 738                         end_request(0);
 739                         goto repeat;
 740                 }
 741                 --special_op[dev];
 742         } /* special_op[dev] */
 743         if (CURRENT->cmd == READ) {
 744                 unsigned int cmd = mult_count[dev] > 1 ? WIN_MULTREAD : WIN_READ;
 745                 hd_out(dev,nsect,sec,head,cyl,cmd,&read_intr);
 746                 if (reset)
 747                         goto repeat;
 748 #ifdef DEBUG
 749                 printk("hd%c: reading %d sectors(%ld-%ld), buffer=%08lx\n",
 750                         dev+'a', nsect, CURRENT->sector,
 751                         CURRENT->sector+nsect-1, (long) CURRENT->buffer);
 752 #endif
 753                 return;
 754         }
 755         if (CURRENT->cmd == WRITE) {
 756                 if (mult_count[dev])
 757                         hd_out(dev,nsect,sec,head,cyl,WIN_MULTWRITE,&multwrite_intr);
 758                 else
 759                         hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
 760                 if (reset)
 761                         goto repeat;
 762 #ifdef DEBUG
 763                 printk("hd%c: writing %d sectors(%ld-%ld), buffer=%08lx\n",
 764                         dev+'a', nsect, CURRENT->sector,
 765                         CURRENT->sector+nsect-1, (long) CURRENT->buffer);
 766 #endif
 767                 if (wait_DRQ()) {
 768                         printk("hd%c: hd_request: no DRQ\n", dev+'a');
 769                         bad_rw_intr();
 770                         goto repeat;
 771                 }
 772                 if (mult_count[dev]) {
 773                         WCURRENT = *CURRENT;
 774                         multwrite(dev);
 775                 } else {
 776                         outsw(HD_DATA,CURRENT->buffer,256);
 777                 }
 778                 return;
 779         }
 780         panic("unknown hd-command");
 781 }
 782 
 783 static void do_hd_request (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 784 {
 785         disable_irq(HD_IRQ);
 786         hd_request();
 787         enable_irq(HD_IRQ);
 788 }
 789 
 790 static int hd_ioctl(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 791         unsigned int cmd, unsigned long arg)
 792 {
 793         struct hd_geometry *loc = (struct hd_geometry *) arg;
 794         int dev, err;
 795 
 796         if ((!inode) || (!inode->i_rdev))
 797                 return -EINVAL;
 798         dev = DEVICE_NR(inode->i_rdev);
 799         if (dev >= NR_HD)
 800                 return -EINVAL;
 801         switch (cmd) {
 802                 case HDIO_GETGEO:
 803                         if (!loc)  return -EINVAL;
 804                         err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
 805                         if (err)
 806                                 return err;
 807                         put_fs_byte(bios_info[dev].head,
 808                                 (char *) &loc->heads);
 809                         put_fs_byte(bios_info[dev].sect,
 810                                 (char *) &loc->sectors);
 811                         put_fs_word(bios_info[dev].cyl,
 812                                 (short *) &loc->cylinders);
 813                         put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
 814                                 (long *) &loc->start);
 815                         return 0;
 816                 case BLKRASET:
 817                         if(!suser())  return -EACCES;
 818                         if(arg > 0xff) return -EINVAL;
 819                         read_ahead[MAJOR(inode->i_rdev)] = arg;
 820                         return 0;
 821                 case BLKRAGET:
 822                         if (!arg)  return -EINVAL;
 823                         err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
 824                         if (err)
 825                                 return err;
 826                         put_fs_long(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
 827                         return 0;
 828                 case BLKGETSIZE:   /* Return device size */
 829                         if (!arg)  return -EINVAL;
 830                         err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
 831                         if (err)
 832                                 return err;
 833                         put_fs_long(hd[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
 834                         return 0;
 835                 case BLKFLSBUF:
 836                         if(!suser())  return -EACCES;
 837                         fsync_dev(inode->i_rdev);
 838                         invalidate_buffers(inode->i_rdev);
 839                         return 0;
 840 
 841                 case BLKRRPART: /* Re-read partition tables */
 842                         return revalidate_hddisk(inode->i_rdev, 1);
 843 
 844                 case HDIO_SETUNMASKINTR:
 845                         if (!suser()) return -EACCES;
 846                         if (!arg)  return -EINVAL;
 847                         if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
 848                         err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
 849                         if (err)
 850                                 return err;
 851                         unmask_intr[dev] = get_fs_long((long *) arg);
 852                         return 0;
 853 
 854                 case HDIO_GETUNMASKINTR:
 855                         if (!arg)  return -EINVAL;
 856                         err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
 857                         if (err)
 858                                 return err;
 859                         put_fs_long(unmask_intr[dev], (long *) arg);
 860                         return 0;
 861 
 862                 case HDIO_GETMULTCOUNT:
 863                         if (!arg)  return -EINVAL;
 864                         err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
 865                         if (err)
 866                                 return err;
 867                         put_fs_long(mult_count[dev], (long *) arg);
 868                         return 0;
 869 
 870                 case HDIO_SETMULTCOUNT:
 871                 {
 872                         unsigned long flags;
 873                         if (!suser()) return -EACCES;
 874                         if (!arg)  return -EINVAL;
 875                         if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
 876                         err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
 877                         if (err)
 878                                 return err;
 879                         arg = get_fs_long((long *) arg);
 880                         save_flags(flags);
 881                         cli();  /* a prior request might still be in progress */
 882                         if (arg > max_mult[dev])
 883                                 err = -EINVAL;  /* out of range for device */
 884                         else if (mult_req[dev] != mult_count[dev]) {
 885                                 ++special_op[dev];
 886                                 err = -EBUSY;   /* busy, try again */
 887                         } else {
 888                                 mult_req[dev] = arg;
 889                                 ++special_op[dev];
 890                                 err = 0;
 891                         }
 892                         restore_flags(flags);
 893                         return err;
 894                 }
 895                 case HDIO_GETIDENTITY:
 896                         if (!arg)  return -EINVAL;
 897                         if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
 898                         if (hd_ident_info[dev] == NULL)  return -ENOMSG;
 899                         err = verify_area(VERIFY_WRITE, (char *) arg, sizeof(struct hd_driveid));
 900                         if (err)
 901                                 return err;
 902                         memcpy_tofs((char *)arg, (char *) hd_ident_info[dev], sizeof(struct hd_driveid));
 903                         return 0;
 904 
 905                 RO_IOCTLS(inode->i_rdev,arg);
 906                 default:
 907                         return -EINVAL;
 908         }
 909 }
 910 
 911 static int hd_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 912 {
 913         int target;
 914         target =  DEVICE_NR(inode->i_rdev);
 915 
 916         while (busy[target])
 917                 sleep_on(&busy_wait);
 918         access_count[target]++;
 919         return 0;
 920 }
 921 
 922 /*
 923  * Releasing a block device means we sync() it, so that it can safely
 924  * be forgotten about...
 925  */
 926 static void hd_release(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 927 {
 928         int target;
 929         sync_dev(inode->i_rdev);
 930 
 931         target =  DEVICE_NR(inode->i_rdev);
 932         access_count[target]--;
 933 
 934 }
 935 
 936 static void hd_geninit(void);
 937 
 938 static struct gendisk hd_gendisk = {
 939         MAJOR_NR,       /* Major number */      
 940         "hd",           /* Major name */
 941         6,              /* Bits to shift to get real from partition */
 942         1 << 6,         /* Number of partitions per real */
 943         MAX_HD,         /* maximum number of real */
 944         hd_geninit,     /* init function */
 945         hd,             /* hd struct */
 946         hd_sizes,       /* block sizes */
 947         0,              /* number */
 948         (void *) bios_info,     /* internal */
 949         NULL            /* next */
 950 };
 951         
 952 static void hd_interrupt(int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
 953 {
 954         void (*handler)(void) = DEVICE_INTR;
 955 
 956         DEVICE_INTR = NULL;
 957         timer_active &= ~(1<<HD_TIMER);
 958         if (!handler)
 959                 handler = unexpected_hd_interrupt;
 960         handler();
 961         sti();
 962 }
 963 
 964 /*
 965  * This is the harddisk IRQ description. The SA_INTERRUPT in sa_flags
 966  * means we run the IRQ-handler with interrupts disabled: this is bad for
 967  * interrupt latency, but anything else has led to problems on some
 968  * machines...
 969  *
 970  * We enable interrupts in some of the routines after making sure it's
 971  * safe.
 972  */
 973 static void hd_geninit(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 974 {
 975         int drive, i;
 976         extern struct drive_info drive_info;
 977         unsigned char *BIOS = (unsigned char *) &drive_info;
 978         int cmos_disks;
 979 
 980         if (!NR_HD) {      
 981                 for (drive=0 ; drive<2 ; drive++) {
 982                         bios_info[drive].cyl   = hd_info[drive].cyl = *(unsigned short *) BIOS;
 983                         bios_info[drive].head  = hd_info[drive].head = *(2+BIOS);
 984                         bios_info[drive].wpcom = hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
 985                         bios_info[drive].ctl   = hd_info[drive].ctl = *(8+BIOS);
 986                         bios_info[drive].lzone = hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
 987                         bios_info[drive].sect  = hd_info[drive].sect = *(14+BIOS);
 988 #ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp
 989                         if (hd_info[drive].cyl && NR_HD == drive)
 990                                 NR_HD++;
 991 #endif
 992                         BIOS += 16;
 993                 }
 994 
 995         /*
 996                 We query CMOS about hard disks : it could be that 
 997                 we have a SCSI/ESDI/etc controller that is BIOS
 998                 compatible with ST-506, and thus showing up in our
 999                 BIOS table, but not register compatible, and therefore
1000                 not present in CMOS.
1001 
1002                 Furthermore, we will assume that our ST-506 drives
1003                 <if any> are the primary drives in the system, and 
1004                 the ones reflected as drive 1 or 2.
1005 
1006                 The first drive is stored in the high nibble of CMOS
1007                 byte 0x12, the second in the low nibble.  This will be
1008                 either a 4 bit drive type or 0xf indicating use byte 0x19 
1009                 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
1010 
1011                 Needless to say, a non-zero value means we have 
1012                 an AT controller hard disk for that drive.
1013 
1014                 
1015         */
1016 
1017                 if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
1018                         if (cmos_disks & 0x0f)
1019                                 NR_HD = 2;
1020                         else
1021                                 NR_HD = 1;
1022         }
1023         i = NR_HD;
1024         while (i-- > 0) {
1025                 hd[i<<6].nr_sects = 0;
1026                 if (bios_info[i].head > 16) {
1027                         /*
1028                          * The newer E-IDE BIOSs handle drives larger than 1024
1029                          * cylinders by increasing the number of logical heads
1030                          * to keep the number of logical cylinders below the
1031                          * sacred INT13 limit of 1024 (10 bits).  If that is
1032                          * what's happening here, we'll find out and correct
1033                          * it later when "identifying" the drive.
1034                          */
1035                         printk("hd.c: IDE/ST-506 disk with more than 16 heads detected.\n");
1036                         printk("  (hd%c: cyl=%d, sect=%d, head=%d)\n", i+'a',
1037                                 bios_info[i].cyl,
1038                                 bios_info[i].sect,
1039                                 bios_info[i].head);
1040                 }
1041                 hd[i<<6].nr_sects = bios_info[i].head *
1042                                 bios_info[i].sect * bios_info[i].cyl;
1043                 hd_ident_info[i] = NULL;
1044                 special_op[i] = 1;
1045         }
1046         if (NR_HD) {
1047                 if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")) {
1048                         printk("hd.c: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
1049                         NR_HD = 0;
1050                 }
1051         }
1052         hd_gendisk.nr_real = NR_HD;
1053 
1054         for(i=0;i<(MAX_HD << 6);i++) hd_blocksizes[i] = 1024;
1055         blksize_size[MAJOR_NR] = hd_blocksizes;
1056 }
1057 
1058 static struct file_operations hd_fops = {
1059         NULL,                   /* lseek - default */
1060         block_read,             /* read - general block-dev read */
1061         block_write,            /* write - general block-dev write */
1062         NULL,                   /* readdir - bad */
1063         NULL,                   /* select */
1064         hd_ioctl,               /* ioctl */
1065         NULL,                   /* mmap */
1066         hd_open,                /* open */
1067         hd_release,             /* release */
1068         block_fsync             /* fsync */
1069 };
1070 
1071 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
1072 {
1073         if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
1074                 printk("Unable to get major %d for harddisk\n",MAJOR_NR);
1075                 return mem_start;
1076         }
1077         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1078         read_ahead[MAJOR_NR] = 8;               /* 8 sector (4kB) read-ahead */
1079         hd_gendisk.next = gendisk_head;
1080         gendisk_head = &hd_gendisk;
1081         timer_table[HD_TIMER].fn = hd_times_out;
1082         return mem_start;
1083 }
1084 
1085 #define DEVICE_BUSY busy[target]
1086 #define USAGE access_count[target]
1087 #define CAPACITY (bios_info[target].head*bios_info[target].sect*bios_info[target].cyl)
1088 /* We assume that the the bios parameters do not change, so the disk capacity
1089    will not change */
1090 #undef MAYBE_REINIT
1091 #define GENDISK_STRUCT hd_gendisk
1092 
1093 /*
1094  * This routine is called to flush all partitions and partition tables
1095  * for a changed scsi disk, and then re-read the new partition table.
1096  * If we are revalidating a disk because of a media change, then we
1097  * enter with usage == 0.  If we are using an ioctl, we automatically have
1098  * usage == 1 (we need an open channel to use an ioctl :-), so this
1099  * is our limit.
1100  */
1101 static int revalidate_hddisk(int dev, int maxusage)
     /* [previous][next][first][last][top][bottom][index][help] */
1102 {
1103         int target, major;
1104         struct gendisk * gdev;
1105         int max_p;
1106         int start;
1107         int i;
1108         long flags;
1109 
1110         target =  DEVICE_NR(dev);
1111         gdev = &GENDISK_STRUCT;
1112 
1113         save_flags(flags);
1114         cli();
1115         if (DEVICE_BUSY || USAGE > maxusage) {
1116                 restore_flags(flags);
1117                 return -EBUSY;
1118         };
1119         DEVICE_BUSY = 1;
1120         restore_flags(flags);
1121 
1122         max_p = gdev->max_p;
1123         start = target << gdev->minor_shift;
1124         major = MAJOR_NR << 8;
1125 
1126         for (i=max_p - 1; i >=0 ; i--) {
1127                 sync_dev(major | start | i);
1128                 invalidate_inodes(major | start | i);
1129                 invalidate_buffers(major | start | i);
1130                 gdev->part[start+i].start_sect = 0;
1131                 gdev->part[start+i].nr_sects = 0;
1132         };
1133 
1134 #ifdef MAYBE_REINIT
1135         MAYBE_REINIT;
1136 #endif
1137 
1138         gdev->part[start].nr_sects = CAPACITY;
1139         resetup_one_dev(gdev, target);
1140 
1141         DEVICE_BUSY = 0;
1142         wake_up(&busy_wait);
1143         return 0;
1144 }
1145 

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