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

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