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

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