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

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