|
|
1.1 ! root 1: // Low level ATA disk access ! 2: // ! 3: // Copyright (C) 2008,2009 Kevin O'Connor <[email protected]> ! 4: // Copyright (C) 2002 MandrakeSoft S.A. ! 5: // ! 6: // This file may be distributed under the terms of the GNU LGPLv3 license. ! 7: ! 8: #include "types.h" // u8 ! 9: #include "ioport.h" // inb ! 10: #include "util.h" // dprintf ! 11: #include "cmos.h" // inb_cmos ! 12: #include "pic.h" // enable_hwirq ! 13: #include "biosvar.h" // GET_EBDA ! 14: #include "pci.h" // foreachpci ! 15: #include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER ! 16: #include "pci_regs.h" // PCI_INTERRUPT_LINE ! 17: #include "boot.h" // add_bcv_hd ! 18: #include "disk.h" // struct ata_s ! 19: #include "ata.h" // ATA_CB_STAT ! 20: ! 21: #define IDE_TIMEOUT 32000 //32 seconds max for IDE ops ! 22: ! 23: struct ata_channel_s ATA_channels[CONFIG_MAX_ATA_INTERFACES] VAR16VISIBLE; ! 24: ! 25: ! 26: /**************************************************************** ! 27: * Helper functions ! 28: ****************************************************************/ ! 29: ! 30: // Wait for the specified ide state ! 31: static inline int ! 32: await_ide(u8 mask, u8 flags, u16 base, u16 timeout) ! 33: { ! 34: u64 end = calc_future_tsc(timeout); ! 35: for (;;) { ! 36: u8 status = inb(base+ATA_CB_STAT); ! 37: if ((status & mask) == flags) ! 38: return status; ! 39: if (check_time(end)) { ! 40: dprintf(1, "IDE time out\n"); ! 41: return -1; ! 42: } ! 43: yield(); ! 44: } ! 45: } ! 46: ! 47: // Wait for the device to be not-busy. ! 48: static int ! 49: await_not_bsy(u16 base) ! 50: { ! 51: return await_ide(ATA_CB_STAT_BSY, 0, base, IDE_TIMEOUT); ! 52: } ! 53: ! 54: // Wait for the device to be ready. ! 55: static int ! 56: await_rdy(u16 base) ! 57: { ! 58: return await_ide(ATA_CB_STAT_RDY, ATA_CB_STAT_RDY, base, IDE_TIMEOUT); ! 59: } ! 60: ! 61: // Wait for ide state - pauses for one ata cycle first. ! 62: static inline int ! 63: pause_await_not_bsy(u16 iobase1, u16 iobase2) ! 64: { ! 65: // Wait one PIO transfer cycle. ! 66: inb(iobase2 + ATA_CB_ASTAT); ! 67: ! 68: return await_not_bsy(iobase1); ! 69: } ! 70: ! 71: // Wait for ide state - pause for 400ns first. ! 72: static inline int ! 73: ndelay_await_not_bsy(u16 iobase1) ! 74: { ! 75: ndelay(400); ! 76: return await_not_bsy(iobase1); ! 77: } ! 78: ! 79: // Reset a drive ! 80: static void ! 81: ata_reset(struct drive_s *drive_g) ! 82: { ! 83: u8 ataid = GET_GLOBAL(drive_g->cntl_id); ! 84: u8 channel = ataid / 2; ! 85: u8 slave = ataid % 2; ! 86: u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1); ! 87: u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2); ! 88: ! 89: dprintf(6, "ata_reset drive=%p\n", drive_g); ! 90: // Pulse SRST ! 91: outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST, iobase2+ATA_CB_DC); ! 92: udelay(5); ! 93: outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC); ! 94: msleep(2); ! 95: ! 96: // wait for device to become not busy. ! 97: int status = await_not_bsy(iobase1); ! 98: if (status < 0) ! 99: goto done; ! 100: if (slave) { ! 101: // Change device. ! 102: u64 end = calc_future_tsc(IDE_TIMEOUT); ! 103: for (;;) { ! 104: outb(ATA_CB_DH_DEV1, iobase1 + ATA_CB_DH); ! 105: status = ndelay_await_not_bsy(iobase1); ! 106: if (status < 0) ! 107: goto done; ! 108: if (inb(iobase1 + ATA_CB_DH) == ATA_CB_DH_DEV1) ! 109: break; ! 110: // Change drive request failed to take effect - retry. ! 111: if (check_time(end)) { ! 112: dprintf(1, "ata_reset slave time out\n"); ! 113: goto done; ! 114: } ! 115: } ! 116: } else { ! 117: // QEMU doesn't reset dh on reset, so set it explicitly. ! 118: outb(ATA_CB_DH_DEV0, iobase1 + ATA_CB_DH); ! 119: } ! 120: ! 121: // On a user-reset request, wait for RDY if it is an ATA device. ! 122: u8 type=GET_GLOBAL(drive_g->type); ! 123: if (type == DTYPE_ATA) ! 124: status = await_rdy(iobase1); ! 125: ! 126: done: ! 127: // Enable interrupts ! 128: outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC); ! 129: ! 130: dprintf(6, "ata_reset exit status=%x\n", status); ! 131: } ! 132: ! 133: static int ! 134: isready(struct drive_s *drive_g) ! 135: { ! 136: // Read the status from controller ! 137: u8 ataid = GET_GLOBAL(drive_g->cntl_id); ! 138: u8 channel = ataid / 2; ! 139: u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1); ! 140: u8 status = inb(iobase1 + ATA_CB_STAT); ! 141: if ((status & (ATA_CB_STAT_BSY|ATA_CB_STAT_RDY)) == ATA_CB_STAT_RDY) ! 142: return DISK_RET_SUCCESS; ! 143: return DISK_RET_ENOTREADY; ! 144: } ! 145: ! 146: static int ! 147: process_ata_misc_op(struct disk_op_s *op) ! 148: { ! 149: if (!CONFIG_ATA) ! 150: return 0; ! 151: ! 152: switch (op->command) { ! 153: case CMD_RESET: ! 154: ata_reset(op->drive_g); ! 155: return DISK_RET_SUCCESS; ! 156: case CMD_ISREADY: ! 157: return isready(op->drive_g); ! 158: case CMD_FORMAT: ! 159: case CMD_VERIFY: ! 160: case CMD_SEEK: ! 161: return DISK_RET_SUCCESS; ! 162: default: ! 163: op->count = 0; ! 164: return DISK_RET_EPARAM; ! 165: } ! 166: } ! 167: ! 168: ! 169: /**************************************************************** ! 170: * ATA send command ! 171: ****************************************************************/ ! 172: ! 173: struct ata_pio_command { ! 174: u8 feature; ! 175: u8 sector_count; ! 176: u8 lba_low; ! 177: u8 lba_mid; ! 178: u8 lba_high; ! 179: u8 device; ! 180: u8 command; ! 181: ! 182: u8 sector_count2; ! 183: u8 lba_low2; ! 184: u8 lba_mid2; ! 185: u8 lba_high2; ! 186: }; ! 187: ! 188: // Send an ata command to the drive. ! 189: static int ! 190: send_cmd(struct drive_s *drive_g, struct ata_pio_command *cmd) ! 191: { ! 192: u8 ataid = GET_GLOBAL(drive_g->cntl_id); ! 193: u8 channel = ataid / 2; ! 194: u8 slave = ataid % 2; ! 195: u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1); ! 196: ! 197: // Select device ! 198: int status = await_not_bsy(iobase1); ! 199: if (status < 0) ! 200: return status; ! 201: u8 newdh = ((cmd->device & ~ATA_CB_DH_DEV1) ! 202: | (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0)); ! 203: u8 olddh = inb(iobase1 + ATA_CB_DH); ! 204: outb(newdh, iobase1 + ATA_CB_DH); ! 205: if ((olddh ^ newdh) & (1<<4)) { ! 206: // Was a device change - wait for device to become not busy. ! 207: status = ndelay_await_not_bsy(iobase1); ! 208: if (status < 0) ! 209: return status; ! 210: } ! 211: ! 212: if (cmd->command == ATA_CMD_READ_SECTORS_EXT ! 213: || cmd->command == ATA_CMD_WRITE_SECTORS_EXT) { ! 214: outb(0x00, iobase1 + ATA_CB_FR); ! 215: outb(cmd->sector_count2, iobase1 + ATA_CB_SC); ! 216: outb(cmd->lba_low2, iobase1 + ATA_CB_SN); ! 217: outb(cmd->lba_mid2, iobase1 + ATA_CB_CL); ! 218: outb(cmd->lba_high2, iobase1 + ATA_CB_CH); ! 219: } ! 220: outb(cmd->feature, iobase1 + ATA_CB_FR); ! 221: outb(cmd->sector_count, iobase1 + ATA_CB_SC); ! 222: outb(cmd->lba_low, iobase1 + ATA_CB_SN); ! 223: outb(cmd->lba_mid, iobase1 + ATA_CB_CL); ! 224: outb(cmd->lba_high, iobase1 + ATA_CB_CH); ! 225: outb(cmd->command, iobase1 + ATA_CB_CMD); ! 226: ! 227: status = ndelay_await_not_bsy(iobase1); ! 228: if (status < 0) ! 229: return status; ! 230: ! 231: if (status & ATA_CB_STAT_ERR) { ! 232: dprintf(6, "send_cmd : read error (status=%02x err=%02x)\n" ! 233: , status, inb(iobase1 + ATA_CB_ERR)); ! 234: return -4; ! 235: } ! 236: if (!(status & ATA_CB_STAT_DRQ)) { ! 237: dprintf(6, "send_cmd : DRQ not set (status %02x)\n", status); ! 238: return -5; ! 239: } ! 240: ! 241: return 0; ! 242: } ! 243: ! 244: ! 245: /**************************************************************** ! 246: * ATA transfers ! 247: ****************************************************************/ ! 248: ! 249: // Transfer 'op->count' blocks (of 'blocksize' bytes) to/from drive ! 250: // 'op->drive_g'. ! 251: static int ! 252: ata_transfer(struct disk_op_s *op, int iswrite, int blocksize) ! 253: { ! 254: dprintf(16, "ata_transfer id=%p write=%d count=%d bs=%d buf=%p\n" ! 255: , op->drive_g, iswrite, op->count, blocksize, op->buf_fl); ! 256: ! 257: u8 ataid = GET_GLOBAL(op->drive_g->cntl_id); ! 258: u8 channel = ataid / 2; ! 259: u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1); ! 260: u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2); ! 261: int count = op->count; ! 262: void *buf_fl = op->buf_fl; ! 263: int status; ! 264: for (;;) { ! 265: if (iswrite) { ! 266: // Write data to controller ! 267: dprintf(16, "Write sector id=%p dest=%p\n", op->drive_g, buf_fl); ! 268: if (CONFIG_ATA_PIO32) ! 269: outsl_fl(iobase1, buf_fl, blocksize / 4); ! 270: else ! 271: outsw_fl(iobase1, buf_fl, blocksize / 2); ! 272: } else { ! 273: // Read data from controller ! 274: dprintf(16, "Read sector id=%p dest=%p\n", op->drive_g, buf_fl); ! 275: if (CONFIG_ATA_PIO32) ! 276: insl_fl(iobase1, buf_fl, blocksize / 4); ! 277: else ! 278: insw_fl(iobase1, buf_fl, blocksize / 2); ! 279: } ! 280: buf_fl += blocksize; ! 281: ! 282: status = pause_await_not_bsy(iobase1, iobase2); ! 283: if (status < 0) { ! 284: // Error ! 285: op->count -= count; ! 286: return status; ! 287: } ! 288: ! 289: count--; ! 290: if (!count) ! 291: break; ! 292: status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR); ! 293: if (status != ATA_CB_STAT_DRQ) { ! 294: dprintf(6, "ata_transfer : more sectors left (status %02x)\n" ! 295: , status); ! 296: op->count -= count; ! 297: return -6; ! 298: } ! 299: } ! 300: ! 301: status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ ! 302: | ATA_CB_STAT_ERR); ! 303: if (!iswrite) ! 304: status &= ~ATA_CB_STAT_DF; ! 305: if (status != 0) { ! 306: dprintf(6, "ata_transfer : no sectors left (status %02x)\n", status); ! 307: return -7; ! 308: } ! 309: ! 310: return 0; ! 311: } ! 312: ! 313: ! 314: /**************************************************************** ! 315: * ATA hard drive functions ! 316: ****************************************************************/ ! 317: ! 318: // Read/write count blocks from a harddrive. ! 319: static int ! 320: ata_cmd_data(struct disk_op_s *op, int iswrite, int command) ! 321: { ! 322: u8 ataid = GET_GLOBAL(op->drive_g->cntl_id); ! 323: u8 channel = ataid / 2; ! 324: u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2); ! 325: u64 lba = op->lba; ! 326: ! 327: struct ata_pio_command cmd; ! 328: memset(&cmd, 0, sizeof(cmd)); ! 329: ! 330: cmd.command = command; ! 331: if (op->count >= (1<<8) || lba + op->count >= (1<<28)) { ! 332: cmd.sector_count2 = op->count >> 8; ! 333: cmd.lba_low2 = lba >> 24; ! 334: cmd.lba_mid2 = lba >> 32; ! 335: cmd.lba_high2 = lba >> 40; ! 336: ! 337: cmd.command |= 0x04; ! 338: lba &= 0xffffff; ! 339: } ! 340: ! 341: cmd.feature = 0; ! 342: cmd.sector_count = op->count; ! 343: cmd.lba_low = lba; ! 344: cmd.lba_mid = lba >> 8; ! 345: cmd.lba_high = lba >> 16; ! 346: cmd.device = ((lba >> 24) & 0xf) | ATA_CB_DH_LBA; ! 347: ! 348: // Disable interrupts ! 349: outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC); ! 350: ! 351: int ret = send_cmd(op->drive_g, &cmd); ! 352: if (ret) ! 353: goto fail; ! 354: ret = ata_transfer(op, iswrite, DISK_SECTOR_SIZE); ! 355: ! 356: fail: ! 357: // Enable interrupts ! 358: outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC); ! 359: return ret; ! 360: } ! 361: ! 362: int ! 363: process_ata_op(struct disk_op_s *op) ! 364: { ! 365: if (!CONFIG_ATA) ! 366: return 0; ! 367: ! 368: int ret; ! 369: switch (op->command) { ! 370: case CMD_READ: ! 371: ret = ata_cmd_data(op, 0, ATA_CMD_READ_SECTORS); ! 372: break; ! 373: case CMD_WRITE: ! 374: ret = ata_cmd_data(op, 1, ATA_CMD_WRITE_SECTORS); ! 375: break; ! 376: default: ! 377: return process_ata_misc_op(op); ! 378: } ! 379: if (ret) ! 380: return DISK_RET_EBADTRACK; ! 381: return DISK_RET_SUCCESS; ! 382: } ! 383: ! 384: ! 385: /**************************************************************** ! 386: * ATAPI functions ! 387: ****************************************************************/ ! 388: ! 389: // Low-level atapi command transmit function. ! 390: static int ! 391: atapi_cmd_data(struct disk_op_s *op, u8 *cmdbuf, u8 cmdlen, u16 blocksize) ! 392: { ! 393: u8 ataid = GET_GLOBAL(op->drive_g->cntl_id); ! 394: u8 channel = ataid / 2; ! 395: u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1); ! 396: u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2); ! 397: ! 398: struct ata_pio_command cmd; ! 399: cmd.sector_count = 0; ! 400: cmd.feature = 0; ! 401: cmd.lba_low = 0; ! 402: cmd.lba_mid = blocksize; ! 403: cmd.lba_high = blocksize >> 8; ! 404: cmd.device = 0; ! 405: cmd.command = ATA_CMD_PACKET; ! 406: ! 407: // Disable interrupts ! 408: outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC); ! 409: ! 410: int ret = send_cmd(op->drive_g, &cmd); ! 411: if (ret) ! 412: goto fail; ! 413: ! 414: // Send command to device ! 415: outsw_fl(iobase1, MAKE_FLATPTR(GET_SEG(SS), cmdbuf), cmdlen / 2); ! 416: ! 417: int status = pause_await_not_bsy(iobase1, iobase2); ! 418: if (status < 0) { ! 419: ret = status; ! 420: goto fail; ! 421: } ! 422: ! 423: if (status & ATA_CB_STAT_ERR) { ! 424: u8 err = inb(iobase1 + ATA_CB_ERR); ! 425: // skip "Not Ready" ! 426: if (err != 0x20) ! 427: dprintf(6, "send_atapi_cmd : read error (status=%02x err=%02x)\n" ! 428: , status, err); ! 429: ret = -2; ! 430: goto fail; ! 431: } ! 432: if (!(status & ATA_CB_STAT_DRQ)) { ! 433: dprintf(6, "send_atapi_cmd : DRQ not set (status %02x)\n", status); ! 434: ret = -3; ! 435: goto fail; ! 436: } ! 437: ! 438: ret = ata_transfer(op, 0, blocksize); ! 439: ! 440: fail: ! 441: // Enable interrupts ! 442: outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC); ! 443: return ret; ! 444: } ! 445: ! 446: // Read sectors from the cdrom. ! 447: int ! 448: cdrom_read(struct disk_op_s *op) ! 449: { ! 450: u8 atacmd[12]; ! 451: memset(atacmd, 0, sizeof(atacmd)); ! 452: atacmd[0]=0x28; // READ command ! 453: atacmd[7]=(op->count & 0xff00) >> 8; // Sectors ! 454: atacmd[8]=(op->count & 0x00ff); ! 455: atacmd[2]=(op->lba & 0xff000000) >> 24; // LBA ! 456: atacmd[3]=(op->lba & 0x00ff0000) >> 16; ! 457: atacmd[4]=(op->lba & 0x0000ff00) >> 8; ! 458: atacmd[5]=(op->lba & 0x000000ff); ! 459: ! 460: return atapi_cmd_data(op, atacmd, sizeof(atacmd), CDROM_SECTOR_SIZE); ! 461: } ! 462: ! 463: int ! 464: process_atapi_op(struct disk_op_s *op) ! 465: { ! 466: int ret; ! 467: switch (op->command) { ! 468: case CMD_READ: ! 469: ret = cdrom_read(op); ! 470: break; ! 471: case CMD_FORMAT: ! 472: case CMD_WRITE: ! 473: return DISK_RET_EWRITEPROTECT; ! 474: default: ! 475: return process_ata_misc_op(op); ! 476: } ! 477: if (ret) ! 478: return DISK_RET_EBADTRACK; ! 479: return DISK_RET_SUCCESS; ! 480: } ! 481: ! 482: // Send a simple atapi command to a drive. ! 483: int ! 484: ata_cmd_packet(struct drive_s *drive_g, u8 *cmdbuf, u8 cmdlen ! 485: , u32 length, void *buf_fl) ! 486: { ! 487: struct disk_op_s dop; ! 488: memset(&dop, 0, sizeof(dop)); ! 489: dop.drive_g = drive_g; ! 490: dop.count = 1; ! 491: dop.buf_fl = buf_fl; ! 492: ! 493: return atapi_cmd_data(&dop, cmdbuf, cmdlen, length); ! 494: } ! 495: ! 496: ! 497: /**************************************************************** ! 498: * ATA detect and init ! 499: ****************************************************************/ ! 500: ! 501: // Extract the ATA/ATAPI version info. ! 502: static int ! 503: extract_version(u16 *buffer) ! 504: { ! 505: // Extract ATA/ATAPI version. ! 506: u16 ataversion = buffer[80]; ! 507: u8 version; ! 508: for (version=15; version>0; version--) ! 509: if (ataversion & (1<<version)) ! 510: break; ! 511: return version; ! 512: } ! 513: ! 514: // Extract common information from IDENTIFY commands. ! 515: static void ! 516: extract_identify(struct drive_s *drive_g, u16 *buffer) ! 517: { ! 518: dprintf(3, "Identify w0=%x w2=%x\n", buffer[0], buffer[2]); ! 519: ! 520: // Read model name ! 521: char *model = drive_g->model; ! 522: int maxsize = ARRAY_SIZE(drive_g->model); ! 523: int i; ! 524: for (i=0; i<maxsize/2; i++) { ! 525: u16 v = buffer[27+i]; ! 526: model[i*2] = v >> 8; ! 527: model[i*2+1] = v & 0xff; ! 528: } ! 529: model[maxsize-1] = 0x00; ! 530: ! 531: // Trim trailing spaces from model name. ! 532: for (i=maxsize-2; i>0 && model[i] == 0x20; i--) ! 533: model[i] = 0x00; ! 534: ! 535: // Common flags. ! 536: SET_GLOBAL(drive_g->removable, (buffer[0] & 0x80) ? 1 : 0); ! 537: SET_GLOBAL(drive_g->cntl_info, extract_version(buffer)); ! 538: } ! 539: ! 540: void ! 541: describe_atapi(struct drive_s *drive_g) ! 542: { ! 543: u8 ataid = drive_g->cntl_id; ! 544: u8 channel = ataid / 2; ! 545: u8 slave = ataid % 2; ! 546: u8 version = drive_g->cntl_info; ! 547: int iscd = drive_g->floppy_type; ! 548: printf("ata%d-%d: %s ATAPI-%d %s", channel, slave ! 549: , drive_g->model, version ! 550: , (iscd ? "CD-Rom/DVD-Rom" : "Device")); ! 551: } ! 552: ! 553: static struct drive_s * ! 554: init_drive_atapi(struct drive_s *dummy, u16 *buffer) ! 555: { ! 556: // Send an IDENTIFY_DEVICE_PACKET command to device ! 557: memset(buffer, 0, DISK_SECTOR_SIZE); ! 558: struct disk_op_s dop; ! 559: memset(&dop, 0, sizeof(dop)); ! 560: dop.drive_g = dummy; ! 561: dop.count = 1; ! 562: dop.lba = 1; ! 563: dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer); ! 564: int ret = ata_cmd_data(&dop, 0, ATA_CMD_IDENTIFY_DEVICE_PACKET); ! 565: if (ret) ! 566: return NULL; ! 567: ! 568: // Success - setup as ATAPI. ! 569: struct drive_s *drive_g = allocDrive(); ! 570: if (! drive_g) ! 571: return NULL; ! 572: SET_GLOBAL(drive_g->cntl_id, dummy->cntl_id); ! 573: extract_identify(drive_g, buffer); ! 574: SET_GLOBAL(drive_g->type, DTYPE_ATAPI); ! 575: SET_GLOBAL(drive_g->blksize, CDROM_SECTOR_SIZE); ! 576: SET_GLOBAL(drive_g->sectors, (u64)-1); ! 577: u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05; ! 578: SET_GLOBAL(drive_g->floppy_type, iscd); ! 579: ! 580: // fill cdidmap ! 581: if (iscd) ! 582: map_cd_drive(drive_g); ! 583: ! 584: return drive_g; ! 585: } ! 586: ! 587: void ! 588: describe_ata(struct drive_s *drive_g) ! 589: { ! 590: u8 ataid = drive_g->cntl_id; ! 591: u8 channel = ataid / 2; ! 592: u8 slave = ataid % 2; ! 593: u64 sectors = drive_g->sectors; ! 594: u8 version = drive_g->cntl_info; ! 595: char *model = drive_g->model; ! 596: printf("ata%d-%d: %s ATA-%d Hard-Disk", channel, slave, model, version); ! 597: u64 sizeinmb = sectors >> 11; ! 598: if (sizeinmb < (1 << 16)) ! 599: printf(" (%u MiBytes)", (u32)sizeinmb); ! 600: else ! 601: printf(" (%u GiBytes)", (u32)(sizeinmb >> 10)); ! 602: } ! 603: ! 604: static struct drive_s * ! 605: init_drive_ata(struct drive_s *dummy, u16 *buffer) ! 606: { ! 607: // Send an IDENTIFY_DEVICE command to device ! 608: memset(buffer, 0, DISK_SECTOR_SIZE); ! 609: struct disk_op_s dop; ! 610: memset(&dop, 0, sizeof(dop)); ! 611: dop.drive_g = dummy; ! 612: dop.count = 1; ! 613: dop.lba = 1; ! 614: dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer); ! 615: int ret = ata_cmd_data(&dop, 0, ATA_CMD_IDENTIFY_DEVICE); ! 616: if (ret) ! 617: return NULL; ! 618: ! 619: // Success - setup as ATA. ! 620: struct drive_s *drive_g = allocDrive(); ! 621: if (! drive_g) ! 622: return NULL; ! 623: SET_GLOBAL(drive_g->cntl_id, dummy->cntl_id); ! 624: extract_identify(drive_g, buffer); ! 625: SET_GLOBAL(drive_g->type, DTYPE_ATA); ! 626: SET_GLOBAL(drive_g->blksize, DISK_SECTOR_SIZE); ! 627: ! 628: SET_GLOBAL(drive_g->pchs.cylinders, buffer[1]); ! 629: SET_GLOBAL(drive_g->pchs.heads, buffer[3]); ! 630: SET_GLOBAL(drive_g->pchs.spt, buffer[6]); ! 631: ! 632: u64 sectors; ! 633: if (buffer[83] & (1 << 10)) // word 83 - lba48 support ! 634: sectors = *(u64*)&buffer[100]; // word 100-103 ! 635: else ! 636: sectors = *(u32*)&buffer[60]; // word 60 and word 61 ! 637: SET_GLOBAL(drive_g->sectors, sectors); ! 638: ! 639: // Setup disk geometry translation. ! 640: setup_translation(drive_g); ! 641: ! 642: // Register with bcv system. ! 643: add_bcv_internal(drive_g); ! 644: ! 645: return drive_g; ! 646: } ! 647: ! 648: static u64 SpinupEnd; ! 649: ! 650: static int ! 651: powerup_await_non_bsy(u16 base) ! 652: { ! 653: u8 orstatus = 0; ! 654: u8 status; ! 655: for (;;) { ! 656: status = inb(base+ATA_CB_STAT); ! 657: if (!(status & ATA_CB_STAT_BSY)) ! 658: break; ! 659: orstatus |= status; ! 660: if (orstatus == 0xff) { ! 661: dprintf(1, "powerup IDE floating\n"); ! 662: return orstatus; ! 663: } ! 664: if (check_time(SpinupEnd)) { ! 665: dprintf(1, "powerup IDE time out\n"); ! 666: return -1; ! 667: } ! 668: yield(); ! 669: } ! 670: dprintf(6, "powerup iobase=%x st=%x\n", base, status); ! 671: return status; ! 672: } ! 673: ! 674: static void ! 675: ata_detect(void *data) ! 676: { ! 677: struct ata_channel_s *atachannel = data; ! 678: int startid = (atachannel - ATA_channels) * 2; ! 679: struct drive_s dummy; ! 680: memset(&dummy, 0, sizeof(dummy)); ! 681: // Device detection ! 682: int ataid, last_reset_ataid=-1; ! 683: for (ataid=startid; ataid<startid+2; ataid++) { ! 684: u8 channel = ataid / 2; ! 685: u8 slave = ataid % 2; ! 686: ! 687: u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1); ! 688: if (!iobase1) ! 689: break; ! 690: ! 691: // Wait for not-bsy. ! 692: int status = powerup_await_non_bsy(iobase1); ! 693: if (status < 0) ! 694: continue; ! 695: u8 newdh = slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0; ! 696: outb(newdh, iobase1+ATA_CB_DH); ! 697: ndelay(400); ! 698: status = powerup_await_non_bsy(iobase1); ! 699: if (status < 0) ! 700: continue; ! 701: ! 702: // Check if ioport registers look valid. ! 703: outb(newdh, iobase1+ATA_CB_DH); ! 704: u8 dh = inb(iobase1+ATA_CB_DH); ! 705: outb(0x55, iobase1+ATA_CB_SC); ! 706: outb(0xaa, iobase1+ATA_CB_SN); ! 707: u8 sc = inb(iobase1+ATA_CB_SC); ! 708: u8 sn = inb(iobase1+ATA_CB_SN); ! 709: dprintf(6, "ata_detect ataid=%d sc=%x sn=%x dh=%x\n" ! 710: , ataid, sc, sn, dh); ! 711: if (sc != 0x55 || sn != 0xaa || dh != newdh) ! 712: continue; ! 713: ! 714: // Prepare new drive. ! 715: dummy.cntl_id = ataid; ! 716: ! 717: // reset the channel ! 718: if (slave && ataid == last_reset_ataid + 1) { ! 719: // The drive was just reset - no need to reset it again. ! 720: } else { ! 721: ata_reset(&dummy); ! 722: last_reset_ataid = ataid; ! 723: } ! 724: ! 725: // check for ATAPI ! 726: u16 buffer[256]; ! 727: struct drive_s *drive_g = init_drive_atapi(&dummy, buffer); ! 728: if (!drive_g) { ! 729: // Didn't find an ATAPI drive - look for ATA drive. ! 730: u8 st = inb(iobase1+ATA_CB_STAT); ! 731: if (!st) ! 732: // Status not set - can't be a valid drive. ! 733: continue; ! 734: ! 735: // Wait for RDY. ! 736: int ret = await_rdy(iobase1); ! 737: if (ret < 0) ! 738: continue; ! 739: ! 740: // check for ATA. ! 741: drive_g = init_drive_ata(&dummy, buffer); ! 742: if (!drive_g) ! 743: // No ATA drive found ! 744: continue; ! 745: } ! 746: ! 747: u16 resetresult = buffer[93]; ! 748: dprintf(6, "ata_detect resetresult=%04x\n", resetresult); ! 749: if (!slave && (resetresult & 0xdf61) == 0x4041) ! 750: // resetresult looks valid and device 0 is responding to ! 751: // device 1 requests - device 1 must not be present - skip ! 752: // detection. ! 753: ataid++; ! 754: } ! 755: } ! 756: ! 757: static void ! 758: init_controller(struct ata_channel_s *atachannel ! 759: , int bdf, int irq, u32 port1, u32 port2) ! 760: { ! 761: SET_GLOBAL(atachannel->irq, irq); ! 762: SET_GLOBAL(atachannel->pci_bdf, bdf); ! 763: SET_GLOBAL(atachannel->iobase1, port1); ! 764: SET_GLOBAL(atachannel->iobase2, port2); ! 765: dprintf(1, "ATA controller %d at %x/%x (irq %d dev %x)\n" ! 766: , atachannel - ATA_channels, port1, port2, irq, bdf); ! 767: run_thread(ata_detect, atachannel); ! 768: } ! 769: ! 770: #define IRQ_ATA1 14 ! 771: #define IRQ_ATA2 15 ! 772: ! 773: static void ! 774: ata_init() ! 775: { ! 776: // Scan PCI bus for ATA adapters ! 777: int count=0, pcicount=0; ! 778: int bdf, max; ! 779: foreachpci(bdf, max) { ! 780: pcicount++; ! 781: if (pci_config_readw(bdf, PCI_CLASS_DEVICE) != PCI_CLASS_STORAGE_IDE) ! 782: continue; ! 783: if (count >= ARRAY_SIZE(ATA_channels)) ! 784: break; ! 785: ! 786: u8 pciirq = pci_config_readb(bdf, PCI_INTERRUPT_LINE); ! 787: u8 prog_if = pci_config_readb(bdf, PCI_CLASS_PROG); ! 788: u32 port1, port2, irq; ! 789: if (prog_if & 1) { ! 790: port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) & ~3; ! 791: port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_1) & ~3; ! 792: irq = pciirq; ! 793: } else { ! 794: port1 = PORT_ATA1_CMD_BASE; ! 795: port2 = PORT_ATA1_CTRL_BASE; ! 796: irq = IRQ_ATA1; ! 797: } ! 798: init_controller(&ATA_channels[count], bdf, irq, port1, port2); ! 799: count++; ! 800: ! 801: if (prog_if & 4) { ! 802: port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_2) & ~3; ! 803: port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_3) & ~3; ! 804: irq = pciirq; ! 805: } else { ! 806: port1 = PORT_ATA2_CMD_BASE; ! 807: port2 = PORT_ATA2_CTRL_BASE; ! 808: irq = IRQ_ATA2; ! 809: } ! 810: init_controller(&ATA_channels[count], bdf, irq, port1, port2); ! 811: count++; ! 812: } ! 813: ! 814: if (!CONFIG_COREBOOT && !pcicount && ARRAY_SIZE(ATA_channels) >= 2) { ! 815: // No PCI devices found - probably a QEMU "-M isapc" machine. ! 816: // Try using ISA ports for ATA controllers. ! 817: init_controller(&ATA_channels[0] ! 818: , -1, IRQ_ATA1, PORT_ATA1_CMD_BASE, PORT_ATA1_CTRL_BASE); ! 819: init_controller(&ATA_channels[1] ! 820: , -1, IRQ_ATA2, PORT_ATA2_CMD_BASE, PORT_ATA2_CTRL_BASE); ! 821: } ! 822: } ! 823: ! 824: void ! 825: ata_setup() ! 826: { ! 827: if (!CONFIG_ATA) ! 828: return; ! 829: ! 830: dprintf(3, "init hard drives\n"); ! 831: ! 832: SpinupEnd = calc_future_tsc(IDE_TIMEOUT); ! 833: ata_init(); ! 834: ! 835: SET_BDA(disk_control_byte, 0xc0); ! 836: ! 837: enable_hwirq(14, entry_76); ! 838: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.