1: /* This file contains the device dependent part of a driver for the IBM-AT 2: * winchester controller. 3: * It was written by Adri Koppes. 4: * 5: * The file contains one entry point: 6: * 7: * at_winchester_task: main entry when system is brought up 8: * 9: * 10: * Changes: 11: * 13 Apr 1992 by Kees J. Bot: device dependent/independent split. 12: * 14 May 2000 by Kees J. Bot: d-d/i rewrite. 13: * 23 Mar 2000 by Michael Temari: added ATAPI CDROM support. 14: */ 15: 16: #include "kernel.h" 17: #include "driver.h" 18: #include "drvlib.h" 19: 20: #if ENABLE_AT_WINI 21: 22: #define ATAPI_DEBUG 0 /* To debug ATAPI code. */ 23: 24: /* I/O Ports used by winchester disk controllers. */ 25: 26: /* Read and write registers */ 27: #define REG_BASE0 0x1F0 /* base register of controller 0 */ 28: #define REG_BASE1 0x170 /* base register of controller 1 */ 29: #define REG_DATA 0 /* data register (offset from the base reg.) */ 30: #define REG_PRECOMP 1 /* start of write precompensation */ 31: #define REG_COUNT 2 /* sectors to transfer */ 32: #define REG_SECTOR 3 /* sector number */ 33: #define REG_CYL_LO 4 /* low byte of cylinder number */ 34: #define REG_CYL_HI 5 /* high byte of cylinder number */ 35: #define REG_LDH 6 /* lba, drive and head */ 36: #define LDH_DEFAULT 0xA0 /* ECC enable, 512 bytes per sector */ 37: #define LDH_LBA 0x40 /* Use LBA addressing */ 38: #define ldh_init(drive) (LDH_DEFAULT | ((drive) << 4)) 39: 40: /* Read only registers */ 41: #define REG_STATUS 7 /* status */ 42: #define STATUS_BSY 0x80 /* controller busy */ 43: #define STATUS_RDY 0x40 /* drive ready */ 44: #define STATUS_WF 0x20 /* write fault */ 45: #define STATUS_SC 0x10 /* seek complete (obsolete) */ 46: #define STATUS_DRQ 0x08 /* data transfer request */ 47: #define STATUS_CRD 0x04 /* corrected data */ 48: #define STATUS_IDX 0x02 /* index pulse */ 49: #define STATUS_ERR 0x01 /* error */ 50: #define STATUS_ADMBSY 0x100 /* administratively busy (software) */ 51: #define REG_ERROR 1 /* error code */ 52: #define ERROR_BB 0x80 /* bad block */ 53: #define ERROR_ECC 0x40 /* bad ecc bytes */ 54: #define ERROR_ID 0x10 /* id not found */ 55: #define ERROR_AC 0x04 /* aborted command */ 56: #define ERROR_TK 0x02 /* track zero error */ 57: #define ERROR_DM 0x01 /* no data address mark */ 58: 59: /* Write only registers */ 60: #define REG_COMMAND 7 /* command */ 61: #define CMD_IDLE 0x00 /* for w_command: drive idle */ 62: #define CMD_RECALIBRATE 0x10 /* recalibrate drive */ 63: #define CMD_READ 0x20 /* read data */ 64: #define CMD_WRITE 0x30 /* write data */ 65: #define CMD_READVERIFY 0x40 /* read verify */ 66: #define CMD_FORMAT 0x50 /* format track */ 67: #define CMD_SEEK 0x70 /* seek cylinder */ 68: #define CMD_DIAG 0x90 /* execute device diagnostics */ 69: #define CMD_SPECIFY 0x91 /* specify parameters */ 70: #define ATA_IDENTIFY 0xEC /* identify drive */ 71: #define REG_CTL 0x206 /* control register */ 72: #define CTL_NORETRY 0x80 /* disable access retry */ 73: #define CTL_NOECC 0x40 /* disable ecc retry */ 74: #define CTL_EIGHTHEADS 0x08 /* more than eight heads */ 75: #define CTL_RESET 0x04 /* reset controller */ 76: #define CTL_INTDISABLE 0x02 /* disable interrupts */ 77: 78: #if ENABLE_ATAPI 79: #define ERROR_SENSE 0xF0 /* sense key mask */ 80: #define SENSE_NONE 0x00 /* no sense key */ 81: #define SENSE_RECERR 0x10 /* recovered error */ 82: #define SENSE_NOTRDY 0x20 /* not ready */ 83: #define SENSE_MEDERR 0x30 /* medium error */ 84: #define SENSE_HRDERR 0x40 /* hardware error */ 85: #define SENSE_ILRQST 0x50 /* illegal request */ 86: #define SENSE_UATTN 0x60 /* unit attention */ 87: #define SENSE_DPROT 0x70 /* data protect */ 88: #define SENSE_ABRT 0xb0 /* aborted command */ 89: #define SENSE_MISCOM 0xe0 /* miscompare */ 90: #define ERROR_MCR 0x08 /* media change requested */ 91: #define ERROR_ABRT 0x04 /* aborted command */ 92: #define ERROR_EOM 0x02 /* end of media detected */ 93: #define ERROR_ILI 0x01 /* illegal length indication */ 94: #define REG_FEAT 1 /* features */ 95: #define FEAT_OVERLAP 0x02 /* overlap */ 96: #define FEAT_DMA 0x01 /* dma */ 97: #define REG_IRR 2 /* interrupt reason register */ 98: #define IRR_REL 0x04 /* release */ 99: #define IRR_IO 0x02 /* direction for xfer */ 100: #define IRR_COD 0x01 /* command or data */ 101: #define REG_SAMTAG 3 102: #define REG_CNT_LO 4 /* low byte of cylinder number */ 103: #define REG_CNT_HI 5 /* high byte of cylinder number */ 104: #define REG_DRIVE 6 /* drive select */ 105: #define REG_STATUS 7 /* status */ 106: #define STATUS_BSY 0x80 /* controller busy */ 107: #define STATUS_DRDY 0x40 /* drive ready */ 108: #define STATUS_DMADF 0x20 /* dma ready/drive fault */ 109: #define STATUS_SRVCDSC 0x10 /* service or dsc */ 110: #define STATUS_DRQ 0x08 /* data transfer request */ 111: #define STATUS_CORR 0x04 /* correctable error occurred */ 112: #define STATUS_CHECK 0x01 /* check error */ 113: 114: #define ATAPI_PACKETCMD 0xA0 /* packet command */ 115: #define ATAPI_IDENTIFY 0xA1 /* identify drive */ 116: #define SCSI_READ10 0x28 /* read from disk */ 117: 118: #define CD_SECTOR_SIZE 2048 /* sector size of a CD-ROM */ 119: #endif /* ATAPI */ 120: 121: /* Interrupt request lines. */ 122: #define NO_IRQ 0 /* no IRQ set yet */ 123: #define AT_IRQ0 14 /* interrupt number for controller 0 */ 124: #define AT_IRQ1 15 /* interrupt number for controller 1 */ 125: 126: /* Common command block */ 127: struct command { 128: u8_t precomp; /* REG_PRECOMP, etc. */ 129: u8_t count; 130: u8_t sector; 131: u8_t cyl_lo; 132: u8_t cyl_hi; 133: u8_t ldh; 134: u8_t command; 135: }; 136: 137: 138: /* Error codes */ 139: #define ERR (-1) /* general error */ 140: #define ERR_BAD_SECTOR (-2) /* block marked bad detected */ 141: 142: /* Some controllers don't interrupt, the clock will wake us up. */ 143: #define WAKEUP (32*HZ) /* drive may be out for 31 seconds max */ 144: 145: /* Miscellaneous. */ 146: #define MAX_DRIVES 4 /* this driver supports 4 drives (d0 - d3) */ 147: #if _WORD_SIZE > 2 148: #define MAX_SECS 256 /* controller can transfer this many sectors */ 149: #else 150: #define MAX_SECS 127 /* but not to a 16 bit process */ 151: #endif 152: #define MAX_ERRORS 4 /* how often to try rd/wt before quitting */ 153: #define NR_DEVICES (MAX_DRIVES * DEV_PER_DRIVE) 154: #define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS) 155: #define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE) 156: #define TIMEOUT 5000000 /* controller timeout in us */ 157: #define RECOVERYTIME 500000 /* controller recovery time in us */ 158: #define INITIALIZED 0x01 /* drive is initialized */ 159: #define DEAF 0x02 /* controller must be reset */ 160: #define SMART 0x04 /* drive supports ATA commands */ 161: #if ENABLE_ATAPI 162: #define ATAPI 0x08 /* it is an ATAPI device */ 163: #else 164: #define ATAPI 0 /* don't bother with ATAPI; optimise out */ 165: #endif 166: 167: 168: /* Variables. */ 169: PRIVATE struct wini { /* main drive struct, one entry per drive */ 170: unsigned state; /* drive state: deaf, initialized, dead */ 171: unsigned base; /* base register of the register file */ 172: unsigned irq; /* interrupt request line */ 173: unsigned lcylinders; /* logical number of cylinders (BIOS) */ 174: unsigned lheads; /* logical number of heads */ 175: unsigned lsectors; /* logical number of sectors per track */ 176: unsigned pcylinders; /* physical number of cylinders (translated) */ 177: unsigned pheads; /* physical number of heads */ 178: unsigned psectors; /* physical number of sectors per track */ 179: unsigned ldhpref; /* top four bytes of the LDH (head) register */ 180: unsigned precomp; /* write precompensation cylinder / 4 */ 181: unsigned max_count; /* max request for this drive */ 182: unsigned open_ct; /* in-use count */ 183: irq_hook_t hook; /* interrupt hook */ 184: struct device part[DEV_PER_DRIVE]; /* disks and partitions */ 185: struct device subpart[SUB_PER_DRIVE]; /* subpartitions */ 186: } wini[MAX_DRIVES], *w_wn; 187: 188: PRIVATE int win_tasknr; /* my task number */ 189: PRIVATE int w_command; /* current command in execution */ 190: PRIVATE int w_status; /* status after interrupt */ 191: PRIVATE int w_drive; /* selected drive */ 192: PRIVATE struct device *w_dv; /* device's base and size */ 193: PRIVATE timer_t w_tmr_timeout; /* timer for w_timeout */ 194: 195: FORWARD _PROTOTYPE( void init_params, (void) ); 196: FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) ); 197: FORWARD _PROTOTYPE( struct device *w_prepare, (int device) ); 198: FORWARD _PROTOTYPE( int w_identify, (void) ); 199: FORWARD _PROTOTYPE( char *w_name, (void) ); 200: FORWARD _PROTOTYPE( int w_specify, (void) ); 201: FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position, 202: iovec_t *iov, unsigned nr_req) ); 203: FORWARD _PROTOTYPE( int com_out, (struct command *cmd) ); 204: FORWARD _PROTOTYPE( void w_need_reset, (void) ); 205: FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) ); 206: FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) ); 207: FORWARD _PROTOTYPE( void w_timeout, (timer_t *tp) ); 208: FORWARD _PROTOTYPE( int w_reset, (void) ); 209: FORWARD _PROTOTYPE( void w_intr_wait, (void) ); 210: FORWARD _PROTOTYPE( int at_intr_wait, (void) ); 211: FORWARD _PROTOTYPE( int w_waitfor, (int mask, int value) ); 212: FORWARD _PROTOTYPE( int w_handler, (irq_hook_t *hook) ); 213: FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry) ); 214: #if ENABLE_ATAPI 215: FORWARD _PROTOTYPE( int atapi_sendpacket, (u8_t *packet, unsigned cnt) ); 216: FORWARD _PROTOTYPE( int atapi_intr_wait, (void) ); 217: FORWARD _PROTOTYPE( int atapi_open, (void) ); 218: FORWARD _PROTOTYPE( void atapi_close, (void) ); 219: FORWARD _PROTOTYPE( int atapi_transfer, (int proc_nr, int opcode, 220: off_t position, iovec_t *iov, unsigned nr_req) ); 221: #endif 222: 223: 224: /* Entry points to this driver. */ 225: PRIVATE struct driver w_dtab = { 226: w_name, /* current device's name */ 227: w_do_open, /* open or mount request, initialize device */ 228: w_do_close, /* release device */ 229: do_diocntl, /* get or set a partition's geometry */ 230: w_prepare, /* prepare for I/O on a given minor device */ 231: w_transfer, /* do the I/O */ 232: nop_cleanup, /* nothing to clean up */ 233: w_geometry, /* tell the geometry of the disk */ 234: }; 235: 236: 237: /*===========================================================================* 238: * at_winchester_task * 239: *===========================================================================*/ 240: PUBLIC void at_winchester_task() 241: { 242: /* Set special disk parameters then call the generic main loop. */ 243: 244: win_tasknr = proc_number(proc_ptr); 245: 246: init_params(); 247: 248: driver_task(&w_dtab); 249: } 250: 251: 252: /*============================================================================* 253: * init_params * 254: *============================================================================*/ 255: PRIVATE void init_params() 256: { 257: /* This routine is called at startup to initialize the drive parameters. */ 258: 259: u16_t parv[2]; 260: unsigned int vector; 261: int drive, nr_drives; 262: struct wini *wn; 263: u8_t params[16]; 264: phys_bytes param_phys = vir2phys(params); 265: 266: /* Get the number of drives from the BIOS data area */ 267: phys_copy(0x475L, param_phys, 1L); 268: if ((nr_drives = params[0]) > 2) nr_drives = 2; 269: 270: for (drive = 0, wn = wini; drive < MAX_DRIVES; drive++, wn++) { 271: if (drive < nr_drives) { 272: /* Copy the BIOS parameter vector */ 273: vector = drive == 0 ? WINI_0_PARM_VEC : WINI_1_PARM_VEC; 274: phys_copy(vector * 4L, vir2phys(parv), 4L); 275: 276: /* Calculate the address of the parameters and copy them */ 277: phys_copy(hclick_to_physb(parv[1]) + parv[0], param_phys, 16L); 278: 279: /* Copy the parameters to the structures of the drive */ 280: wn->lcylinders = bp_cylinders(params); 281: wn->lheads = bp_heads(params); 282: wn->lsectors = bp_sectors(params); 283: wn->precomp = bp_precomp(params) >> 2; 284: } 285: wn->ldhpref = ldh_init(drive); 286: wn->max_count = MAX_SECS << SECTOR_SHIFT; 287: 288: /* Base I/O register to address controller. */ 289: wn->base = drive < 2 ? REG_BASE0 : REG_BASE1; 290: } 291: } 292: 293: 294: /*============================================================================* 295: * w_do_open * 296: *============================================================================*/ 297: PRIVATE int w_do_open(dp, m_ptr) 298: struct driver *dp; 299: message *m_ptr; 300: { 301: /* Device open: Initialize the controller and read the partition table. */ 302: 303: struct wini *wn; 304: 305: if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO); 306: wn = w_wn; 307: 308: if (wn->state == 0) { 309: /* Try to identify the device. */ 310: if (w_identify() != OK) { 311: printf("%s: probe failed\n", w_name()); 312: if (wn->state & DEAF) w_reset(); 313: wn->state = 0; 314: return(ENXIO); 315: } 316: } 317: if (wn->open_ct == 0) { 318: #if ENABLE_ATAPI 319: if (wn->state & ATAPI) { 320: int r; 321: 322: if (m_ptr->COUNT & W_BIT) return(EACCES); 323: if ((r = atapi_open()) != OK) return(r); 324: } 325: #endif 326: /* Partition the disk. */ 327: partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY); 328: wn->open_ct++; 329: } 330: return(OK); 331: } 332: 333: 334: /*===========================================================================* 335: * w_prepare * 336: *===========================================================================*/ 337: PRIVATE struct device *w_prepare(device) 338: int device; 339: { 340: /* Prepare for I/O on a device. */ 341: 342: if (device < NR_DEVICES) { /* d0, d0p[0-3], d1, ... */ 343: w_drive = device / DEV_PER_DRIVE; /* save drive number */ 344: w_wn = &wini[w_drive]; 345: w_dv = &w_wn->part[device % DEV_PER_DRIVE]; 346: } else 347: if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/ 348: w_drive = device / SUB_PER_DRIVE; 349: w_wn = &wini[w_drive]; 350: w_dv = &w_wn->subpart[device % SUB_PER_DRIVE]; 351: } else { 352: return(NIL_DEV); 353: } 354: return(w_dv); 355: } 356: 357: 358: /*===========================================================================* 359: * w_identify * 360: *===========================================================================*/ 361: PRIVATE int w_identify() 362: { 363: /* Find out if a device exists, if it is an old AT disk, or a newer ATA 364: * drive, a removable media device, etc. 365: */ 366: 367: struct wini *wn = w_wn; 368: struct command cmd; 369: char id_string[40]; 370: int i, r; 371: unsigned long size; 372: #define id_byte(n) (&tmp_buf[2 * (n)]) 373: #define id_word(n) (((u16_t) id_byte(n)[0] << 0) \ 374: |((u16_t) id_byte(n)[1] << 8)) 375: #define id_longword(n) (((u32_t) id_byte(n)[0] << 0) \ 376: |((u32_t) id_byte(n)[1] << 8) \ 377: |((u32_t) id_byte(n)[2] << 16) \ 378: |((u32_t) id_byte(n)[3] << 24)) 379: 380: /* Try to identify the device. */ 381: cmd.ldh = wn->ldhpref; 382: cmd.command = ATA_IDENTIFY; 383: if (com_simple(&cmd) == OK) { 384: /* This is an ATA device. */ 385: wn->state |= SMART; 386: 387: /* Device information. */ 388: phys_insw(wn->base + REG_DATA, tmp_phys, SECTOR_SIZE); 389: 390: /* Why are the strings byte swapped??? */ 391: for (i = 0; i < 40; i++) id_string[i] = id_byte(27)[i^1]; 392: 393: /* Preferred CHS translation mode. */ 394: wn->pcylinders = id_word(1); 395: wn->pheads = id_word(3); 396: wn->psectors = id_word(6); 397: size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors; 398: 399: if ((id_byte(49)[1] & 0x02) && size > 512L*1024*2) { 400: /* Drive is LBA capable and is big enough to trust it to 401: * not make a mess of it. 402: */ 403: wn->ldhpref |= LDH_LBA; 404: size = id_longword(60); 405: } 406: 407: if (wn->lcylinders == 0) { 408: /* No BIOS parameters? Then make some up. */ 409: wn->lcylinders = wn->pcylinders; 410: wn->lheads = wn->pheads; 411: wn->lsectors = wn->psectors; 412: while (wn->lcylinders > 1024) { 413: wn->lheads *= 2; 414: wn->lcylinders /= 2; 415: } 416: } 417: #if ENABLE_ATAPI 418: } else 419: if (cmd.command = ATAPI_IDENTIFY, com_simple(&cmd) == OK) { 420: /* An ATAPI device. */ 421: wn->state |= ATAPI; 422: 423: /* Device information. */ 424: phys_insw(wn->base + REG_DATA, tmp_phys, 512); 425: 426: /* Why are the strings byte swapped??? */ 427: for (i = 0; i < 40; i++) id_string[i] = id_byte(27)[i^1]; 428: 429: size = 0; /* Size set later. */ 430: #endif 431: } else { 432: /* Not an ATA device; no translations, no special features. Don't 433: * touch it unless the BIOS knows about it. 434: */ 435: if (wn->lcylinders == 0) return(ERR); /* no BIOS parameters */ 436: wn->pcylinders = wn->lcylinders; 437: wn->pheads = wn->lheads; 438: wn->psectors = wn->lsectors; 439: size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors; 440: } 441: 442: /* Size of the whole drive */ 443: wn->part[0].dv_size = mul64u(size, SECTOR_SIZE); 444: 445: if (w_specify() != OK && w_specify() != OK) return(ERR); 446: 447: printf("%s: ", w_name()); 448: if (wn->state & (SMART|ATAPI)) { 449: printf("%.40s\n", id_string); 450: } else { 451: printf("%ux%ux%u\n", wn->pcylinders, wn->pheads, wn->psectors); 452: } 453: 454: /* Everything looks OK; register IRQ so we can stop polling. */ 455: wn->irq = w_drive < 2 ? AT_IRQ0 : AT_IRQ1; 456: put_irq_handler(&wn->hook, wn->irq, w_handler); 457: enable_irq(&wn->hook); 458: 459: return(OK); 460: } 461: 462: 463: /*===========================================================================* 464: * w_name * 465: *===========================================================================*/ 466: PRIVATE char *w_name() 467: { 468: /* Return a name for the current device. */ 469: static char name[] = "at-d0"; 470: 471: name[4] = '0' + w_drive; 472: return name; 473: } 474: 475: 476: /*===========================================================================* 477: * w_specify * 478: *===========================================================================*/ 479: PRIVATE int w_specify() 480: { 481: /* Routine to initialize the drive after boot or when a reset is needed. */ 482: 483: struct wini *wn = w_wn; 484: struct command cmd; 485: 486: if ((wn->state & DEAF) && w_reset() != OK) return(ERR); 487: 488: if (!(wn->state & ATAPI)) { 489: /* Specify parameters: precompensation, number of heads and sectors. */ 490: cmd.precomp = wn->precomp; 491: cmd.count = wn->psectors; 492: cmd.ldh = w_wn->ldhpref | (wn->pheads - 1); 493: cmd.command = CMD_SPECIFY; /* Specify some parameters */ 494: 495: /* Output command block and see if controller accepts the parameters. */ 496: if (com_simple(&cmd) != OK) return(ERR); 497: 498: if (!(wn->state & SMART)) { 499: /* Calibrate an old disk. */ 500: cmd.sector = 0; 501: cmd.cyl_lo = 0; 502: cmd.cyl_hi = 0; 503: cmd.ldh = w_wn->ldhpref; 504: cmd.command = CMD_RECALIBRATE; 505: 506: if (com_simple(&cmd) != OK) return(ERR); 507: } 508: } 509: wn->state |= INITIALIZED; 510: return(OK); 511: } 512: 513: 514: /*===========================================================================* 515: * w_transfer * 516: *===========================================================================*/ 517: PRIVATE int w_transfer(proc_nr, opcode, position, iov, nr_req) 518: int proc_nr; /* process doing the request */ 519: int opcode; /* DEV_GATHER or DEV_SCATTER */ 520: off_t position; /* offset on device to read or write */ 521: iovec_t *iov; /* pointer to read or write request vector */ 522: unsigned nr_req; /* length of request vector */ 523: { 524: struct wini *wn = w_wn; 525: iovec_t *iop, *iov_end = iov + nr_req; 526: int r, errors; 527: unsigned long block; 528: unsigned long dv_size = cv64ul(w_dv->dv_size); 529: struct command cmd; 530: unsigned cylinder, head, sector, nbytes, count, chunk; 531: unsigned secspcyl = wn->pheads * wn->psectors; 532: phys_bytes user_base = proc_vir2phys(proc_addr(proc_nr), 0); 533: 534: #if ENABLE_ATAPI 535: if (w_wn->state & ATAPI) { 536: return atapi_transfer(proc_nr, opcode, position, iov, nr_req); 537: } 538: #endif 539: 540: /* Check disk address. */ 541: if ((position & SECTOR_MASK) != 0) return(EINVAL); 542: 543: errors = 0; 544: 545: while (nr_req > 0) { 546: /* How many bytes to transfer? */ 547: nbytes = 0; 548: for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size; 549: if ((nbytes & SECTOR_MASK) != 0) return(EINVAL); 550: 551: /* Which block on disk and how close to EOF? */ 552: if (position >= dv_size) return(OK); /* At EOF */ 553: if (position + nbytes > dv_size) nbytes = dv_size - position; 554: block = div64u(add64ul(w_dv->dv_base, position), SECTOR_SIZE); 555: 556: if (nbytes >= wn->max_count) { 557: /* The drive can't do more then max_count at once. */ 558: nbytes = wn->max_count; 559: } 560: 561: /* First check to see if a reinitialization is needed. */ 562: if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO); 563: 564: /* Tell the controller to transfer nbytes bytes. */ 565: cmd.precomp = wn->precomp; 566: cmd.count = (nbytes >> SECTOR_SHIFT) & BYTE; 567: if (wn->ldhpref & LDH_LBA) { 568: cmd.sector = (block >> 0) & 0xFF; 569: cmd.cyl_lo = (block >> 8) & 0xFF; 570: cmd.cyl_hi = (block >> 16) & 0xFF; 571: cmd.ldh = wn->ldhpref | ((block >> 24) & 0xF); 572: } else { 573: cylinder = block / secspcyl; 574: head = (block % secspcyl) / wn->psectors; 575: sector = block % wn->psectors; 576: cmd.sector = sector + 1; 577: cmd.cyl_lo = cylinder & BYTE; 578: cmd.cyl_hi = (cylinder >> 8) & BYTE; 579: cmd.ldh = wn->ldhpref | head; 580: } 581: cmd.command = opcode == DEV_SCATTER ? CMD_WRITE : CMD_READ; 582: 583: r = com_out(&cmd); 584: 585: while (r == OK && nbytes > 0) { 586: /* For each sector, wait for an interrupt and fetch the data 587: * (read), or supply data to the controller and wait for an 588: * interrupt (write). 589: */ 590: 591: if (opcode == DEV_GATHER) { 592: /* First an interrupt, then data. */ 593: if ((r = at_intr_wait()) != OK) { 594: /* An error, send data to the bit bucket. */ 595: if (w_status & STATUS_DRQ) { 596: phys_insw(w_wn->base + REG_DATA, 597: tmp_phys, SECTOR_SIZE); 598: } 599: break; 600: } 601: } 602: 603: /* Wait for data transfer requested. */ 604: if (!w_waitfor(STATUS_DRQ, STATUS_DRQ)) { r = ERR; break; } 605: 606: /* Copy bytes to or from the device's buffer. */ 607: if (opcode == DEV_GATHER) { 608: phys_insw(w_wn->base + REG_DATA, 609: user_base + iov->iov_addr, SECTOR_SIZE); 610: } else { 611: phys_outsw(w_wn->base + REG_DATA, 612: user_base + iov->iov_addr, SECTOR_SIZE); 613: 614: /* Data sent, wait for an interrupt. */ 615: if ((r = at_intr_wait()) != OK) break; 616: } 617: 618: /* Book the bytes successfully transferred. */ 619: nbytes -= SECTOR_SIZE; 620: position += SECTOR_SIZE; 621: iov->iov_addr += SECTOR_SIZE; 622: if ((iov->iov_size -= SECTOR_SIZE) == 0) { iov++; nr_req--; } 623: } 624: 625: /* Any errors? */ 626: if (r != OK) { 627: /* Don't retry if sector marked bad or too many errors. */ 628: if (r == ERR_BAD_SECTOR || ++errors == MAX_ERRORS) { 629: w_command = CMD_IDLE; 630: return(EIO); 631: } 632: } 633: } 634: 635: w_command = CMD_IDLE; 636: return(OK); 637: } 638: 639: 640: /*============================================================================* 641: * com_out * 642: *============================================================================*/ 643: PRIVATE int com_out(cmd) 644: struct command *cmd; /* Command block */ 645: { 646: /* Output the command block to the winchester controller and return status */ 647: 648: struct wini *wn = w_wn; 649: unsigned base = wn->base; 650: 651: if (!w_waitfor(STATUS_BSY, 0)) { 652: printf("%s: controller not ready\n", w_name()); 653: return(ERR); 654: } 655: 656: /* Select drive. */ 657: outb(base + REG_LDH, cmd->ldh); 658: 659: if (!w_waitfor(STATUS_BSY, 0)) { 660: printf("%s: drive not ready\n", w_name()); 661: return(ERR); 662: } 663: 664: /* Schedule a wakeup call, some controllers are flaky. */ 665: tmr_settimer(&w_tmr_timeout, CLOCK, get_uptime() + WAKEUP, w_timeout); 666: 667: outb(base + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0); 668: outb(base + REG_PRECOMP, cmd->precomp); 669: outb(base + REG_COUNT, cmd->count); 670: outb(base + REG_SECTOR, cmd->sector); 671: outb(base + REG_CYL_LO, cmd->cyl_lo); 672: outb(base + REG_CYL_HI, cmd->cyl_hi); 673: w_status = STATUS_ADMBSY; 674: outb(base + REG_COMMAND, w_command = cmd->command); 675: return(OK); 676: } 677: 678: 679: /*===========================================================================* 680: * w_need_reset * 681: *===========================================================================*/ 682: PRIVATE void w_need_reset() 683: { 684: /* The controller needs to be reset. */ 685: struct wini *wn; 686: 687: for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) { 688: wn->state |= DEAF; 689: wn->state &= ~INITIALIZED; 690: } 691: } 692: 693: 694: /*============================================================================* 695: * w_do_close * 696: *============================================================================*/ 697: PRIVATE int w_do_close(dp, m_ptr) 698: struct driver *dp; 699: message *m_ptr; 700: { 701: /* Device close: Release a device. */ 702: 703: if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO); 704: w_wn->open_ct--; 705: #if ENABLE_ATAPI 706: if (w_wn->open_ct == 0 && (w_wn->state & ATAPI)) atapi_close(); 707: #endif 708: return(OK); 709: } 710: 711: 712: /*============================================================================* 713: * com_simple * 714: *============================================================================*/ 715: PRIVATE int com_simple(cmd) 716: struct command *cmd; /* Command block */ 717: { 718: /* A simple controller command, only one interrupt and no data-out phase. */ 719: int r; 720: 721: if ((r = com_out(cmd)) == OK) r = at_intr_wait(); 722: w_command = CMD_IDLE; 723: return(r); 724: } 725: 726: 727: /*===========================================================================* 728: * w_timeout * 729: *===========================================================================*/ 730: PRIVATE void w_timeout(tp) 731: timer_t *tp; 732: { 733: struct wini *wn = w_wn; 734: 735: switch (w_command) { 736: case CMD_IDLE: 737: break; /* fine */ 738: case CMD_READ: 739: case CMD_WRITE: 740: /* Impossible, but not on PC's: The controller does not respond. */ 741: 742: /* Limiting multisector I/O seems to help. */ 743: if (wn->max_count > 8 * SECTOR_SIZE) { 744: wn->max_count = 8 * SECTOR_SIZE; 745: } else { 746: wn->max_count = SECTOR_SIZE; 747: } 748: /*FALL THROUGH*/ 749: default: 750: /* Some other command. */ 751: printf("%s: timeout on command %02x\n", w_name(), w_command); 752: w_need_reset(); 753: w_status = 0; 754: interrupt(win_tasknr); 755: } 756: } 757: 758: 759: /*===========================================================================* 760: * w_reset * 761: *===========================================================================*/ 762: PRIVATE int w_reset() 763: { 764: /* Issue a reset to the controller. This is done after any catastrophe, 765: * like the controller refusing to respond. 766: */ 767: 768: struct wini *wn; 769: 770: /* Wait for any internal drive recovery. */ 771: micro_delay(RECOVERYTIME); 772: 773: /* Strobe reset bit */ 774: outb(w_wn->base + REG_CTL, CTL_RESET); 775: micro_delay(1000L); 776: outb(w_wn->base + REG_CTL, 0); 777: micro_delay(1000L); 778: 779: /* Wait for controller ready */ 780: if (!w_waitfor(STATUS_BSY, 0)) { 781: printf("%s: reset failed, drive busy\n", w_name()); 782: return(ERR); 783: } 784: 785: /* The error register should be checked now, but some drives mess it up. */ 786: 787: for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) { 788: if (wn->base == w_wn->base) wn->state &= ~DEAF; 789: } 790: return(OK); 791: } 792: 793: 794: /*============================================================================* 795: * w_intr_wait * 796: *============================================================================*/ 797: PRIVATE void w_intr_wait() 798: { 799: /* Wait for a task completion interrupt. */ 800: 801: message mess; 802: 803: if (w_wn->irq != NO_IRQ) { 804: /* Wait for an interrupt that sets w_status to "not busy". */ 805: while (w_status & (STATUS_ADMBSY|STATUS_BSY)) receive(HARDWARE, &mess); 806: } else { 807: /* Interrupt not yet allocated; use polling. */ 808: (void) w_waitfor(STATUS_BSY, 0); 809: } 810: } 811: 812: 813: /*============================================================================* 814: * at_intr_wait * 815: *============================================================================*/ 816: PRIVATE int at_intr_wait() 817: { 818: /* Wait for an interrupt, study the status bits and return error/success. */ 819: int r; 820: 821: w_intr_wait(); 822: if ((w_status & (STATUS_BSY | STATUS_WF | STATUS_ERR)) == 0) { 823: r = OK; 824: } else 825: if ((w_status & STATUS_ERR) && (inb(w_wn->base + REG_ERROR) & ERROR_BB)) { 826: r = ERR_BAD_SECTOR; /* sector marked bad, retries won't help */ 827: } else { 828: r = ERR; /* any other error */ 829: } 830: w_status |= STATUS_ADMBSY; /* assume still busy with I/O */ 831: return(r); 832: } 833: 834: 835: /*==========================================================================* 836: * w_waitfor * 837: *==========================================================================*/ 838: PRIVATE int w_waitfor(mask, value) 839: int mask; /* status mask */ 840: int value; /* required status */ 841: { 842: /* Wait until controller is in the required state. Return zero on timeout. */ 843: 844: struct micro_state ms; 845: 846: micro_start(&ms); 847: do { 848: w_status = inb(w_wn->base + REG_STATUS); 849: if ((w_status & mask) == value) return 1; 850: } while (micro_elapsed(&ms) < TIMEOUT); 851: 852: w_need_reset(); /* Controller gone deaf. */ 853: return(0); 854: } 855: 856: 857: /*==========================================================================* 858: * w_handler * 859: *==========================================================================*/ 860: PRIVATE int w_handler(hook) 861: irq_hook_t *hook; 862: { 863: /* Disk interrupt, send message to winchester task and reenable interrupts. */ 864: 865: w_status = inb(w_wn->base + REG_STATUS); /* acknowledge interrupt */ 866: interrupt(win_tasknr); 867: return 1; 868: } 869: 870: 871: /*============================================================================* 872: * w_geometry * 873: *============================================================================*/ 874: PRIVATE void w_geometry(entry) 875: struct partition *entry; 876: { 877: struct wini *wn = w_wn; 878: 879: if (wn->state & ATAPI) { /* Make up some numbers. */ 880: entry->cylinders = div64u(wn->part[0].dv_size, SECTOR_SIZE) / (64*32); 881: entry->heads = 64; 882: entry->sectors = 32; 883: } else { /* Return logical geometry. */ 884: entry->cylinders = wn->lcylinders; 885: entry->heads = wn->lheads; 886: entry->sectors = wn->lsectors; 887: } 888: } 889: 890: 891: #if ENABLE_ATAPI 892: /*===========================================================================* 893: * atapi_open * 894: *===========================================================================*/ 895: PRIVATE int atapi_open() 896: { 897: /* Should load and lock the device and obtain its size. For now just set the 898: * size of the device to something big. What is really needed is a generic 899: * SCSI layer that does all this stuff for ATAPI and SCSI devices (kjb). (XXX) 900: */ 901: w_wn->part[0].dv_size = mul64u(800L*1024, 1024); 902: return(OK); 903: } 904: 905: /*===========================================================================* 906: * atapi_close * 907: *===========================================================================*/ 908: PRIVATE void atapi_close() 909: { 910: /* Should unlock the device. For now do nothing. (XXX) */ 911: } 912: 913: /*===========================================================================* 914: * atapi_transfer * 915: *===========================================================================*/ 916: PRIVATE int atapi_transfer(proc_nr, opcode, position, iov, nr_req) 917: int proc_nr; /* process doing the request */ 918: int opcode; /* DEV_GATHER or DEV_SCATTER */ 919: off_t position; /* offset on device to read or write */ 920: iovec_t *iov; /* pointer to read or write request vector */ 921: unsigned nr_req; /* length of request vector */ 922: { 923: struct wini *wn = w_wn; 924: iovec_t *iop, *iov_end = iov + nr_req; 925: int r, errors, fresh; 926: u64_t pos; 927: unsigned long block; 928: unsigned long dv_size = cv64ul(w_dv->dv_size); 929: unsigned nbytes, nblocks, count, before, chunk; 930: phys_bytes user_base = proc_vir2phys(proc_addr(proc_nr), 0); 931: u8_t packet[12]; 932: 933: errors = fresh = 0; 934: 935: while (nr_req > 0 && !fresh) { 936: /* The Minix block size is smaller than the CD block size, so we 937: * may have to read extra before or after the good data. 938: */ 939: pos = add64ul(w_dv->dv_base, position); 940: block = div64u(pos, CD_SECTOR_SIZE); 941: before = rem64u(pos, CD_SECTOR_SIZE); 942: 943: /* How many bytes to transfer? */ 944: nbytes = count = 0; 945: for (iop = iov; iop < iov_end; iop++) { 946: nbytes += iop->iov_size; 947: if ((before + nbytes) % CD_SECTOR_SIZE == 0) count = nbytes; 948: } 949: 950: /* Does one of the memory chunks end nicely on a CD sector multiple? */ 951: if (count != 0) nbytes = count; 952: 953: /* Data comes in as words, so we have to enforce even byte counts. */ 954: if ((before | nbytes) & 1) return(EINVAL); 955: 956: /* Which block on disk and how close to EOF? */ 957: if (position >= dv_size) return(OK); /* At EOF */ 958: if (position + nbytes > dv_size) nbytes = dv_size - position; 959: 960: nblocks = (before + nbytes + CD_SECTOR_SIZE - 1) / CD_SECTOR_SIZE; 961: if (ATAPI_DEBUG) { 962: printf("block=%lu, before=%u, nbytes=%u, nblocks=%u\n", 963: block, before, nbytes, nblocks); 964: } 965: 966: /* First check to see if a reinitialization is needed. */ 967: if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO); 968: 969: /* Build an ATAPI command packet. */ 970: packet[0] = SCSI_READ10; 971: packet[1] = 0; 972: packet[2] = (block >> 24) & 0xFF; 973: packet[3] = (block >> 16) & 0xFF; 974: packet[4] = (block >> 8) & 0xFF; 975: packet[5] = (block >> 0) & 0xFF; 976: packet[7] = (nblocks >> 8) & 0xFF; 977: packet[8] = (nblocks >> 0) & 0xFF; 978: packet[9] = 0; 979: packet[10] = 0; 980: packet[11] = 0; 981: 982: /* Tell the controller to execute the packet command. */ 983: r = atapi_sendpacket(packet, nblocks * CD_SECTOR_SIZE); 984: if (r != OK) goto err; 985: 986: /* Read chunks of data. */ 987: while ((r = atapi_intr_wait()) > 0) { 988: count = r; 989: 990: if (ATAPI_DEBUG) { 991: printf("before=%u, nbytes=%u, count=%u\n", 992: before, nbytes, count); 993: } 994: 995: while (before > 0 && count > 0) { /* Discard before. */ 996: chunk = before; 997: if (chunk > count) chunk = count; 998: if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE; 999: phys_insw(w_wn->base + REG_DATA, tmp_phys, chunk); 1000: before -= chunk; 1001: count -= chunk; 1002: } 1003: 1004: while (nbytes > 0 && count > 0) { /* Requested data. */ 1005: chunk = nbytes; 1006: if (chunk > count) chunk = count; 1007: if (chunk > iov->iov_size) chunk = iov->iov_size; 1008: phys_insw(w_wn->base + REG_DATA, 1009: user_base + iov->iov_addr, chunk); 1010: position += chunk; 1011: nbytes -= chunk; 1012: count -= chunk; 1013: iov->iov_addr += chunk; 1014: fresh = 0; 1015: if ((iov->iov_size -= chunk) == 0) { 1016: iov++; 1017: nr_req--; 1018: fresh = 1; /* new element is optional */ 1019: } 1020: } 1021: 1022: while (count > 0) { /* Excess data. */ 1023: chunk = count; 1024: if (chunk > DMA_BUF_SIZE) chunk = DMA_BUF_SIZE; 1025: phys_insw(w_wn->base + REG_DATA, tmp_phys, chunk); 1026: count -= chunk; 1027: } 1028: } 1029: 1030: if (r < 0) { 1031: err: /* Don't retry if too many errors. */ 1032: if (++errors == MAX_ERRORS) { 1033: w_command = CMD_IDLE; 1034: return(EIO); 1035: } 1036: } 1037: } 1038: 1039: w_command = CMD_IDLE; 1040: return(OK); 1041: } 1042: 1043: /*===========================================================================* 1044: * atapi_sendpacket * 1045: *===========================================================================*/ 1046: PRIVATE int atapi_sendpacket(packet, cnt) 1047: u8_t *packet; 1048: unsigned cnt; 1049: { 1050: /* Send an Atapi Packet Command */ 1051: struct wini *wn = w_wn; 1052: message mess; 1053: 1054: /* Select Master/Slave drive */ 1055: outb(wn->base + REG_DRIVE, wn->ldhpref); 1056: 1057: if (!w_waitfor(STATUS_BSY | STATUS_DRQ, 0)) { 1058: printf("%s: drive not ready\n", w_name()); 1059: return(ERR); 1060: } 1061: 1062: /* Schedule wakeup call. */ 1063: tmr_settimer(&w_tmr_timeout, CLOCK, get_uptime() + WAKEUP, w_timeout); 1064: 1065: #if _WORD_SIZE > 2 1066: if (cnt > 0xFFFE) cnt = 0xFFFE; /* Max data per interrupt. */ 1067: #endif 1068: 1069: outb(wn->base + REG_FEAT, 0); 1070: outb(wn->base + REG_IRR, 0); 1071: outb(wn->base + REG_SAMTAG, 0); 1072: outb(wn->base + REG_CNT_LO, (cnt >> 0) & 0xFF); 1073: outb(wn->base + REG_CNT_HI, (cnt >> 8) & 0xFF); 1074: outb(wn->base + REG_COMMAND, w_command = ATAPI_PACKETCMD); 1075: 1076: if (!w_waitfor(STATUS_BSY | STATUS_DRQ, STATUS_DRQ)) { 1077: printf("%s: timeout (BSY|DRQ -> DRQ)\n"); 1078: return(ERR); 1079: } 1080: w_status |= STATUS_ADMBSY; /* Command not at all done yet. */ 1081: 1082: /* Send the command packet to the device. */ 1083: outsw(wn->base + REG_DATA, packet, 12); 1084: return(OK); 1085: } 1086: 1087: /*============================================================================* 1088: * atapi_intr_wait * 1089: *============================================================================*/ 1090: PRIVATE int atapi_intr_wait() 1091: { 1092: /* Wait for an interrupt and study the results. Returns a number of bytes 1093: * that need to be transferred, or an error code. 1094: */ 1095: struct wini *wn = w_wn; 1096: int e; 1097: int len; 1098: int irr; 1099: int r; 1100: int phase; 1101: 1102: w_intr_wait(); 1103: 1104: e = inb(wn->base + REG_ERROR); 1105: len = inb(wn->base + REG_CNT_LO); 1106: len |= inb(wn->base + REG_CNT_HI) << 8; 1107: irr = inb(wn->base + REG_IRR); 1108: if (ATAPI_DEBUG) { 1109: printf("S=%02x E=%02x L=%04x I=%02x\n", w_status, e, len, irr); 1110: } 1111: if (w_status & (STATUS_BSY | STATUS_CHECK)) return ERR; 1112: 1113: phase = (w_status & STATUS_DRQ) | (irr & (IRR_COD | IRR_IO)); 1114: 1115: switch (phase) { 1116: case IRR_COD | IRR_IO: 1117: if (ATAPI_DEBUG) printf("ACD: Phase Command Complete\n"); 1118: r = OK; 1119: break; 1120: case 0: 1121: if (ATAPI_DEBUG) printf("ACD: Phase Command Aborted\n"); 1122: r = ERR; 1123: break; 1124: case STATUS_DRQ | IRR_COD: 1125: if (ATAPI_DEBUG) printf("ACD: Phase Command Out\n"); 1126: r = ERR; 1127: break; 1128: case STATUS_DRQ: 1129: if (ATAPI_DEBUG) printf("ACD: Phase Data Out %d\n", len); 1130: r = len; 1131: break; 1132: case STATUS_DRQ | IRR_IO: 1133: if (ATAPI_DEBUG) printf("ACD: Phase Data In %d\n", len); 1134: r = len; 1135: break; 1136: default: 1137: if (ATAPI_DEBUG) printf("ACD: Phase Unknown\n"); 1138: r = ERR; 1139: break; 1140: } 1141: 1142: #if 0 1143: /* retry if the media changed */ 1144: XXX while (phase == (IRR_IO | IRR_COD) && (w_status & STATUS_CHECK) 1145: && (e & ERROR_SENSE) == SENSE_UATTN && --try > 0); 1146: #endif 1147: 1148: w_status |= STATUS_ADMBSY; /* Assume not done yet. */ 1149: return(r); 1150: } 1151: #endif /* ENABLE_ATAPI */ 1152: #endif /* ENABLE_AT_WINI */