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

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