Ignore:
Timestamp:
Jul 24, 2023, 5:51:46 PM (2 years ago)
Author:
David Azarewicz
Message:

Added workaround to help with VirtualBox issues.
Improved diagnostic messages.
Changed how timeouts are reset and how ctx hooks are triggered.
Added quirk for devices with issues executing some standard commands.
Changed to make /N the default.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/os2ahci/ahci.c

    r209 r211  
    44 * Copyright (c) 2011 thi.guten Software Development
    55 * Copyright (c) 2011 Mensys B.V.
    6  * Copyright (c) 2013-2021 David Azarewicz <david@88watts.net>
     6 * Copyright (c) 2013-2023 David Azarewicz <david@88watts.net>
    77 *
    88 * Authors: Christian Mueller, Markus Thielen
     
    3636                              ? atapi_##func : ata_##func
    3737
    38 
    39 /* Initial driver status flags indexed by the board_* constants in os2ahci.h
    40  *
    41  * NOTE: The Linux AHCI driver uses a combination of board-specific quirk
    42  *       flags and overriding certain libata service functions to handle
    43  *       adapter flaws. However, there were only three overrides at the time
    44  *       os2ahci was written, one for hard adapter resets and two for port
    45  *       resets, and we can easily implement those within the corresponding
    46  *       reset handlers. If this becomes more complex, this array of flags
    47  *       should be converted into a structure array which contains function
    48  *       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 
    7138#define MAX_IRQ_HANDLERS 8 /* This is the maximum number of handlers that Dev32Help_SetIRQ can register */
    7239static u16 irq_used[MAX_IRQ_HANDLERS]; /* IRQ level for each used IRQ */
     
    8148  dprintf(0,"AHCI global registers for adapter %d %d:%d:%d irq=%d addr=0x%x\n",
    8249      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);
    8552
    8653  for (i = 0; i <= HOST_CAP2; i += sizeof(u32))
     
    180147  if (readl(ai->mmio + HOST_VERSION) >= 0x00010200L) ai->cap2 = readl(ai->mmio + HOST_CAP2);
    181148
    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];
    188149  ai->hw_ports = (ai->cap & 0x1f) + 1;
    189150
    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))
    191152  {
    192153    /* disable 64-bit support for faulty controllers; OS/2 can't do 64 bits at
     
    200161   * around quirks and faulty hardware is hard to come by...
    201162   */
    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))
    203164  {
    204165    DPRINTF(DBG_INIT, DBG_PREFIX": controller can't do NCQ, turning off CAP_NCQ\n");
     
    206167  }
    207168
    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))
    209170  {
    210171    DPRINTF(DBG_INIT, DBG_PREFIX": controller can do NCQ, turning on CAP_NCQ\n");
     
    212173  }
    213174
    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))
    215176  {
    216177    DPRINTF(DBG_INIT, DBG_PREFIX": controller can't do PMP, turning off CAP_PMP\n");
     
    218179  }
    219180
    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))
    221182  {
    222183    DPRINTF(DBG_INIT, DBG_PREFIX": controller can't do SNTF, turning off CAP_SNTF\n");
     
    224185  }
    225186
    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)
    227188  {
    228189    DPRINTF(DBG_INIT, DBG_PREFIX": JMB361 has only one port, port_map 0x%x -> 0x%x\n", ai->port_map, 1);
     
    276237  DPRINTF(DBG_DETAILED, DBG_PREFIX": BIOS AHCI mode is %d\n", ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN);
    277238
    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)
    279240  {
    280241    /* Adapter is not in AHCI mode and the spec says a COMRESET is
     
    309270  readl(ai->mmio + HOST_CTL);
    310271
    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)
    312273  {
    313274    /* This BIOS apparently accesses the controller via SATA registers and
     
    400361    while (((tmp = readl(ai->mmio + HOST_CTL)) & HOST_RESET) != 0) {
    401362      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);
    403364        return(-1);
    404365      }
     
    411372    ahci_restore_initial_config(ai);
    412373
    413     if (ai->pci_vendor == PCI_VENDOR_ID_INTEL) {
     374    if (ai->PciVendor == PCI_VENDOR_ID_INTEL) {
    414375      u32 tmp16 = 0;
    415376
     
    498459  }
    499460
    500   if (ai->pci_vendor == PCI_VENDOR_ID_INTEL)
     461  if (ai->PciVendor == PCI_VENDOR_ID_INTEL)
    501462  {
    502463    /* Adapter is not in AHCI mode and the spec says a COMRESET is
     
    520481
    521482  /* 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));
    523484  return(1);
    524485}
     
    541502    /* register IRQ handler; each IRQ level is registered only once */
    542503    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 */
    546507      else
    547508      {
     
    569530      if (rc)
    570531      {
    571         dprintf(0,"failed to register interrupt %d\n", ai->irq);
     532        dprintf(0, DBG_PREFIX": failed to register interrupt %d\n", ai->irq);
    572533        return(-1);
    573534      }
     
    612573  readl(ai->mmio + HOST_CTL); /* flush */
    613574
    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 
    617575  DPRINTF(DBG_INIT|DBG_FUNCEND, DBG_PREFIX": END\n");
    618576  return(0);
     
    686644  if (ai->port_max < p) ai->port_max = p;
    687645  if (ai->ports[p].dev_max < d) ai->ports[p].dev_max = d;
    688   memset(ai->ports[p].devs + d, 0x00, sizeof(*ai->ports[p].devs));
     646  memset(ai->ports[p].devs + d, 0, sizeof(*ai->ports[p].devs));
    689647
    690648  /* set generic device information (assuming an ATA disk device for now) */
     
    699657    /* this is an ATAPI device; augment device information */
    700658    ai->ports[p].devs[d].atapi     = 1;
    701     ai->ports[p].devs[d].atapi_16  = (id_buf[ATA_ID_CONFIG] & 0x0001U) != 0;
    702     ai->ports[p].devs[d].dev_type  = (id_buf[ATA_ID_CONFIG] & 0x1f00U) >> 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;
    703661    ai->ports[p].devs[d].ncq_max   = 1;
    704662
     
    709667    if (enable_ncq[ad_no(ai)][p])
    710668    {
    711       ai->ports[p].devs[d].ncq_max = id_buf[ATA_ID_QUEUE_DEPTH] & 0x001fU;
     669      ai->ports[p].devs[d].ncq_max = id_buf[ATA_ID_QUEUE_DEPTH] & 0x001f;
    712670    }
    713671    if (ai->ports[p].devs[d].ncq_max < 1)
     
    716674      ai->ports[p].devs[d].ncq_max = 1;
    717675    }
    718     if (id_buf[ATA_ID_CFS_ENABLE_2] & 0x0400U)
    719     {
    720       ai->ports[p].devs[d].lba48   = 1;
     676    if (id_buf[ATA_ID_CFS_ENABLE_2] & 0x0400)
     677    {
     678      ai->ports[p].devs[d].lba48 = 1;
    721679    }
    722680  }
     
    760718
    761719  /* 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 &&
    763721      !memcmp(pDevName, "VBOX HARDDISK", 13))
    764722  {
     
    933891  /* set link speed and power management options */
    934892  DPRINTF(DBG_DETAILED, DBG_PREFIX": setting link speed and power management options\n");
    935   tmp = readl(port_mmio + PORT_SCR_CTL) & ~0x00000fffUL;
     893  tmp = readl(port_mmio + PORT_SCR_CTL) & ~0x00000fff;
    936894  tmp |= (link_speed[ad_no(ai)][p] & 0x0f) << 4;
    937895  tmp |= (link_power[ad_no(ai)][p] & 0x0f) << 8;
     
    10981056  if ((rc = ahci_stop_fis_rx(ai, p)) != 0)
    10991057  {
    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);
    11011059    return(rc);
    11021060  }
     
    11051063  if ((rc = ahci_stop_engine(ai, p)) != 0)
    11061064  {
    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);
    11081066    return(rc);
    11091067  }
     
    14081366    writel(port_mmio + PORT_CMD_ISSUE, 1);
    14091367    TimerInit(&Timer, timeout);
     1368    rc = 0;
    14101369    while (readl(port_mmio + PORT_CMD_ISSUE) & 1)
    14111370    {
     
    14171376    if (rc)
    14181377    {
    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);
    14201379      iorb_seterr(pIorb, IOERR_ADAPTER_TIMEOUT);
    14211380    }
     
    17311690        iorb_queue_del(&ai->ports[p].iorb_queue, vIorb);
    17321691        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;
    17331694        aws_free(add_workspace(pIorb));
    17341695      }
     
    17751736    #ifdef DEBUG
    17761737    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]);
    17781739    #endif
    17791740    reset_port = 1;
     
    17811742  if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR))
    17821743  {
    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);
    17841745    reset_port = 1;
    17851746  }
    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);
    17891750    reset_port = 1;
    17901751  }
     
    17941755
    17951756    ports_to_reset[ad_no(ai)] |= 1UL << p;
    1796     KernArmHook(reset_ctxhook_h, 0, 0);
     1757    SafeArmCtxHook(ResetCtxHook_h, 0);
    17971758
    17981759    /* no point analyzing device errors after a reset... */
     
    18001761  }
    18011762
    1802   #ifdef DEBUG
    1803   dprintf(0,"port #%d interrupt error status: 0x%08x; restarting port\n", p, irq_stat);
    1804   #else
     1763  #ifndef DEBUG
    18051764  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   }
    18091765  #endif
     1766  {
     1767    dprintf(0,DBG_PREFIX": Port=%d status=%08x; restarting port\n", p, irq_stat);
     1768  }
    18101769
    18111770  /* Handle device-specific errors. Those errors typically involve restarting
     
    18141773   */
    18151774  ports_to_restart[ad_no(ai)] |= 1UL << p;
    1816   KernArmHook(restart_ctxhook_h, 0, 0);
     1775  SafeArmCtxHook(RestartCtxHook_h, 0);
    18171776}
    18181777
Note: See TracChangeset for help on using the changeset viewer.