Changeset 211 for trunk/src/os2ahci/ahci.c
- Timestamp:
- Jul 24, 2023, 5:51:46 PM (2 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/os2ahci/ahci.c
r209 r211 4 4 * Copyright (c) 2011 thi.guten Software Development 5 5 * Copyright (c) 2011 Mensys B.V. 6 * Copyright (c) 2013-202 1David Azarewicz <david@88watts.net>6 * Copyright (c) 2013-2023 David Azarewicz <david@88watts.net> 7 7 * 8 8 * Authors: Christian Mueller, Markus Thielen … … 36 36 ? atapi_##func : ata_##func 37 37 38 39 /* Initial driver status flags indexed by the board_* constants in os2ahci.h40 *41 * NOTE: The Linux AHCI driver uses a combination of board-specific quirk42 * flags and overriding certain libata service functions to handle43 * adapter flaws. However, there were only three overrides at the time44 * os2ahci was written, one for hard adapter resets and two for port45 * resets, and we can easily implement those within the corresponding46 * reset handlers. If this becomes more complex, this array of flags47 * should be converted into a structure array which contains function48 * pointers to all handler functions which may need to be overridden.49 */50 u16 initial_flags[] =51 {52 0, /* board_ahci */53 AHCI_HFLAG_NO_NCQ | /* board_ahci_vt8251 */54 AHCI_HFLAG_NO_PMP,55 AHCI_HFLAG_IGN_IRQ_IF_ERR, /* board_ahci_ign_iferr */56 AHCI_HFLAG_IGN_SERR_INTERNAL | /* board_ahci_sb600 */57 AHCI_HFLAG_NO_MSI |58 AHCI_HFLAG_SECT255 |59 AHCI_HFLAG_32BIT_ONLY,60 AHCI_HFLAG_NO_NCQ | /* board_ahci_mv */61 AHCI_HFLAG_NO_MSI |62 AHCI_HFLAG_MV_PATA |63 AHCI_HFLAG_NO_PMP,64 AHCI_HFLAG_IGN_SERR_INTERNAL, /* board_ahci_sb700 */65 AHCI_HFLAG_YES_NCQ, /* board_ahci_mcp65 */66 AHCI_HFLAG_NO_PMP, /* board_ahci_nopmp */67 AHCI_HFLAG_YES_NCQ, /* board_ahci_yesncq */68 AHCI_HFLAG_NO_SNTF, /* board_ahci_nosntf */69 };70 71 38 #define MAX_IRQ_HANDLERS 8 /* This is the maximum number of handlers that Dev32Help_SetIRQ can register */ 72 39 static u16 irq_used[MAX_IRQ_HANDLERS]; /* IRQ level for each used IRQ */ … … 81 48 dprintf(0,"AHCI global registers for adapter %d %d:%d:%d irq=%d addr=0x%x\n", 82 49 ad_no(ai), 83 PCI_BUS_FROM_BDF(ai-> bus_dev_func), PCI_DEV_FROM_BDF(ai->bus_dev_func),84 PCI_FUNC_FROM_BDF(ai-> bus_dev_func), ai->irq, ai->mmio_phys);50 PCI_BUS_FROM_BDF(ai->BusDevFunc), PCI_DEV_FROM_BDF(ai->BusDevFunc), 51 PCI_FUNC_FROM_BDF(ai->BusDevFunc), ai->irq, ai->mmio_phys); 85 52 86 53 for (i = 0; i <= HOST_CAP2; i += sizeof(u32)) … … 180 147 if (readl(ai->mmio + HOST_VERSION) >= 0x00010200L) ai->cap2 = readl(ai->mmio + HOST_CAP2); 181 148 182 if (ai->pci->board >= sizeof(initial_flags) / sizeof(*initial_flags))183 {184 dprintf(0,"error: invalid board index in PCI info\n");185 return(-1);186 }187 ai->flags = initial_flags[ai->pci->board];188 149 ai->hw_ports = (ai->cap & 0x1f) + 1; 189 150 190 if ((ai->cap & HOST_CAP_64) && (ai-> flags & AHCI_HFLAG_32BIT_ONLY))151 if ((ai->cap & HOST_CAP_64) && (ai->quirks & AHCI_HFLAG_32BIT_ONLY)) 191 152 { 192 153 /* disable 64-bit support for faulty controllers; OS/2 can't do 64 bits at … … 200 161 * around quirks and faulty hardware is hard to come by... 201 162 */ 202 if ((ai->cap & HOST_CAP_NCQ) && (ai-> flags & AHCI_HFLAG_NO_NCQ))163 if ((ai->cap & HOST_CAP_NCQ) && (ai->quirks & AHCI_HFLAG_NO_NCQ)) 203 164 { 204 165 DPRINTF(DBG_INIT, DBG_PREFIX": controller can't do NCQ, turning off CAP_NCQ\n"); … … 206 167 } 207 168 208 if (!(ai->cap & HOST_CAP_NCQ) && (ai-> flags & AHCI_HFLAG_YES_NCQ))169 if (!(ai->cap & HOST_CAP_NCQ) && (ai->quirks & AHCI_HFLAG_YES_NCQ)) 209 170 { 210 171 DPRINTF(DBG_INIT, DBG_PREFIX": controller can do NCQ, turning on CAP_NCQ\n"); … … 212 173 } 213 174 214 if ((ai->cap & HOST_CAP_PMP) && (ai-> flags & AHCI_HFLAG_NO_PMP))175 if ((ai->cap & HOST_CAP_PMP) && (ai->quirks & AHCI_HFLAG_NO_PMP)) 215 176 { 216 177 DPRINTF(DBG_INIT, DBG_PREFIX": controller can't do PMP, turning off CAP_PMP\n"); … … 218 179 } 219 180 220 if ((ai->cap & HOST_CAP_SNTF) && (ai-> flags & AHCI_HFLAG_NO_SNTF))181 if ((ai->cap & HOST_CAP_SNTF) && (ai->quirks & AHCI_HFLAG_NO_SNTF)) 221 182 { 222 183 DPRINTF(DBG_INIT, DBG_PREFIX": controller can't do SNTF, turning off CAP_SNTF\n"); … … 224 185 } 225 186 226 if (ai-> pci_vendor == PCI_VENDOR_ID_JMICRON && ai->pci_device == 0x2361 && ai->port_map != 1)187 if (ai->PciVendor == PCI_VENDOR_ID_JMICRON && ai->PciDevice == 0x2361 && ai->port_map != 1) 227 188 { 228 189 DPRINTF(DBG_INIT, DBG_PREFIX": JMB361 has only one port, port_map 0x%x -> 0x%x\n", ai->port_map, 1); … … 276 237 DPRINTF(DBG_DETAILED, DBG_PREFIX": BIOS AHCI mode is %d\n", ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN); 277 238 278 if ((ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN) == 0 && ai-> pci_vendor == PCI_VENDOR_ID_INTEL)239 if ((ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN) == 0 && ai->PciVendor == PCI_VENDOR_ID_INTEL) 279 240 { 280 241 /* Adapter is not in AHCI mode and the spec says a COMRESET is … … 309 270 readl(ai->mmio + HOST_CTL); 310 271 311 if ((ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN) == 0 && ai-> pci_vendor == PCI_VENDOR_ID_INTEL)272 if ((ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN) == 0 && ai->PciVendor == PCI_VENDOR_ID_INTEL) 312 273 { 313 274 /* This BIOS apparently accesses the controller via SATA registers and … … 400 361 while (((tmp = readl(ai->mmio + HOST_CTL)) & HOST_RESET) != 0) { 401 362 if (TimerCheckAndBlock(&Timer)) { 402 dprintf(0, "controller reset failed (0x%x)\n", tmp);363 dprintf(0, DBG_PREFIX": controller reset failed (0x%x)\n", tmp); 403 364 return(-1); 404 365 } … … 411 372 ahci_restore_initial_config(ai); 412 373 413 if (ai-> pci_vendor == PCI_VENDOR_ID_INTEL) {374 if (ai->PciVendor == PCI_VENDOR_ID_INTEL) { 414 375 u32 tmp16 = 0; 415 376 … … 498 459 } 499 460 500 if (ai-> pci_vendor == PCI_VENDOR_ID_INTEL)461 if (ai->PciVendor == PCI_VENDOR_ID_INTEL) 501 462 { 502 463 /* Adapter is not in AHCI mode and the spec says a COMRESET is … … 520 481 521 482 /* couldn't enable AHCI mode */ 522 dprintf(0, "failed to enable AHCI mode on adapter %d\n", ad_no(ai));483 dprintf(0, DBG_PREFIX": failed to enable AHCI mode on adapter %d\n", ad_no(ai)); 523 484 return(1); 524 485 } … … 541 502 /* register IRQ handler; each IRQ level is registered only once */ 542 503 p = 1; /* int count */ 543 if (!(ai-> flags & AHCI_HFLAG_NO_MSI))544 { 545 if (PsdMsiAlloc(ai-> bus_dev_func, &p, &ai->irq)) p = 1; /* shared flag */504 if (!(ai->quirks & AHCI_HFLAG_NO_MSI)) 505 { 506 if (PsdMsiAlloc(ai->BusDevFunc, &p, &ai->irq)) p = 1; /* shared flag */ 546 507 else 547 508 { … … 569 530 if (rc) 570 531 { 571 dprintf(0, "failed to register interrupt %d\n", ai->irq);532 dprintf(0, DBG_PREFIX": failed to register interrupt %d\n", ai->irq); 572 533 return(-1); 573 534 } … … 612 573 readl(ai->mmio + HOST_CTL); /* flush */ 613 574 614 /* enable interrupts on PCI-level (PCI 2.3 added a feature to disable INTs) */615 /* pci_enable_int(ai->bus, ai->dev_func); */616 617 575 DPRINTF(DBG_INIT|DBG_FUNCEND, DBG_PREFIX": END\n"); 618 576 return(0); … … 686 644 if (ai->port_max < p) ai->port_max = p; 687 645 if (ai->ports[p].dev_max < d) ai->ports[p].dev_max = d; 688 memset(ai->ports[p].devs + d, 0 x00, sizeof(*ai->ports[p].devs));646 memset(ai->ports[p].devs + d, 0, sizeof(*ai->ports[p].devs)); 689 647 690 648 /* set generic device information (assuming an ATA disk device for now) */ … … 699 657 /* this is an ATAPI device; augment device information */ 700 658 ai->ports[p].devs[d].atapi = 1; 701 ai->ports[p].devs[d].atapi_16 = (id_buf[ATA_ID_CONFIG] & 0x0001 U) != 0;702 ai->ports[p].devs[d].dev_type = (id_buf[ATA_ID_CONFIG] & 0x1f00 U) >> 8;659 ai->ports[p].devs[d].atapi_16 = (id_buf[ATA_ID_CONFIG] & 0x0001) != 0; 660 ai->ports[p].devs[d].dev_type = (id_buf[ATA_ID_CONFIG] & 0x1f00) >> 8; 703 661 ai->ports[p].devs[d].ncq_max = 1; 704 662 … … 709 667 if (enable_ncq[ad_no(ai)][p]) 710 668 { 711 ai->ports[p].devs[d].ncq_max = id_buf[ATA_ID_QUEUE_DEPTH] & 0x001f U;669 ai->ports[p].devs[d].ncq_max = id_buf[ATA_ID_QUEUE_DEPTH] & 0x001f; 712 670 } 713 671 if (ai->ports[p].devs[d].ncq_max < 1) … … 716 674 ai->ports[p].devs[d].ncq_max = 1; 717 675 } 718 if (id_buf[ATA_ID_CFS_ENABLE_2] & 0x0400 U)719 { 720 ai->ports[p].devs[d].lba48 676 if (id_buf[ATA_ID_CFS_ENABLE_2] & 0x0400) 677 { 678 ai->ports[p].devs[d].lba48 = 1; 721 679 } 722 680 } … … 760 718 761 719 /* try to detect virtualbox environment to enable a hack for IRQ routing */ 762 if (ai == ad_infos && ai-> pci_vendor == 0x8086 && ai->pci_device == 0x2829 &&720 if (ai == ad_infos && ai->PciVendor == 0x8086 && ai->PciDevice == 0x2829 && 763 721 !memcmp(pDevName, "VBOX HARDDISK", 13)) 764 722 { … … 933 891 /* set link speed and power management options */ 934 892 DPRINTF(DBG_DETAILED, DBG_PREFIX": setting link speed and power management options\n"); 935 tmp = readl(port_mmio + PORT_SCR_CTL) & ~0x00000fff UL;893 tmp = readl(port_mmio + PORT_SCR_CTL) & ~0x00000fff; 936 894 tmp |= (link_speed[ad_no(ai)][p] & 0x0f) << 4; 937 895 tmp |= (link_power[ad_no(ai)][p] & 0x0f) << 8; … … 1098 1056 if ((rc = ahci_stop_fis_rx(ai, p)) != 0) 1099 1057 { 1100 dprintf(0, __func__": failed to stop FIS receive (%d)\n", rc);1058 dprintf(0, DBG_PREFIX": failed to stop FIS receive (%d)\n", rc); 1101 1059 return(rc); 1102 1060 } … … 1105 1063 if ((rc = ahci_stop_engine(ai, p)) != 0) 1106 1064 { 1107 dprintf(0, __func__": failed to stop port HW engine (%d)\n", rc);1065 dprintf(0, DBG_PREFIX": failed to stop port HW engine (%d)\n", rc); 1108 1066 return(rc); 1109 1067 } … … 1408 1366 writel(port_mmio + PORT_CMD_ISSUE, 1); 1409 1367 TimerInit(&Timer, timeout); 1368 rc = 0; 1410 1369 while (readl(port_mmio + PORT_CMD_ISSUE) & 1) 1411 1370 { … … 1417 1376 if (rc) 1418 1377 { 1419 DPRINTF(DBG_DETAILED, " timeout for IORB %x port=%x", vIorb, p);1378 DPRINTF(DBG_DETAILED, " timeout %x for IORB %x port=%x", timeout, vIorb, p); 1420 1379 iorb_seterr(pIorb, IOERR_ADAPTER_TIMEOUT); 1421 1380 } … … 1731 1690 iorb_queue_del(&ai->ports[p].iorb_queue, vIorb); 1732 1691 iorb_queue_add(&done_queue, vIorb, pIorb); 1692 /* If we failed a NCQ command and then succeeded with a standard command, disable NCQ for this port */ 1693 if (add_workspace(pIorb)->no_ncq) ai->ports[p].devs[iorb_unit_device(pIorb)].ncq_max = 1; 1733 1694 aws_free(add_workspace(pIorb)); 1734 1695 } … … 1775 1736 #ifdef DEBUG 1776 1737 u32 *unk = (u32 *) (port_dma_base(ai, p)->rx_fis + RX_FIS_UNK); 1777 dprintf(0, "warning: unknown FIS %08lx %08lx %08lx %08lx\n", unk[0], unk[1], unk[2], unk[3]);1738 dprintf(0, DBG_PREFIX": warning: unknown FIS %08lx %08lx %08x %08x\n", unk[0], unk[1], unk[2], unk[3]); 1778 1739 #endif 1779 1740 reset_port = 1; … … 1781 1742 if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) 1782 1743 { 1783 dprintf(0, "warning: host bus [data] error for port #%d\n", p);1744 dprintf(0, DBG_PREFIX": warning: host bus [data] error port=%d\n", p); 1784 1745 reset_port = 1; 1785 1746 } 1786 if (irq_stat & PORT_IRQ_IF_ERR && !(ai-> flags & AHCI_HFLAG_IGN_IRQ_IF_ERR))1787 { 1788 dprintf(0, "warning: interface fatal error for port #%d\n", p);1747 if (irq_stat & PORT_IRQ_IF_ERR && !(ai->quirks & AHCI_HFLAG_IGN_IRQ_IF_ERR)) 1748 { 1749 dprintf(0, DBG_PREFIX": warning: interface fatal error port=%d\n", p); 1789 1750 reset_port = 1; 1790 1751 } … … 1794 1755 1795 1756 ports_to_reset[ad_no(ai)] |= 1UL << p; 1796 KernArmHook(reset_ctxhook_h, 0, 0);1757 SafeArmCtxHook(ResetCtxHook_h, 0); 1797 1758 1798 1759 /* no point analyzing device errors after a reset... */ … … 1800 1761 } 1801 1762 1802 #ifdef DEBUG 1803 dprintf(0,"port #%d interrupt error status: 0x%08x; restarting port\n", p, irq_stat); 1804 #else 1763 #ifndef DEBUG 1805 1764 if (!ai->ports[p].devs[0].atapi) 1806 {1807 dprintf(0,"port #%d interrupt error status: 0x%08x; restarting port\n", p, irq_stat);1808 }1809 1765 #endif 1766 { 1767 dprintf(0,DBG_PREFIX": Port=%d status=%08x; restarting port\n", p, irq_stat); 1768 } 1810 1769 1811 1770 /* Handle device-specific errors. Those errors typically involve restarting … … 1814 1773 */ 1815 1774 ports_to_restart[ad_no(ai)] |= 1UL << p; 1816 KernArmHook(restart_ctxhook_h, 0, 0);1775 SafeArmCtxHook(RestartCtxHook_h, 0); 1817 1776 } 1818 1777
Note:
See TracChangeset
for help on using the changeset viewer.