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

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