Changeset 80


Ignore:
Timestamp:
Mar 1, 2011, 10:10:11 AM (14 years ago)
Author:
chris
Message:

Version 1.06
============

  • Finally came across a BIOS which accesses the ICH7/8 controller via SATA registers (i.e. not AHCI mode). This required a few changes to the code at boot time because it turned out that COMRESETs are required whenever switching to/from AHCI mode to allow the AHCI or SATA controller to re-discover the attached devices:
  • 'init_reset' will now be forced on when finding a controller in non-AHCI mode at boot time.
  • A COMRESET is initiated for each implemented port after turning off AHCI mode when restoring the BIOS configuration; this is done only for Intel controllers at this point because they map the AHCI port SCR MMIO registers even when not in AHCI mode.
  • apm_suspend() has been adjusted to restore the BIOS configuration to prevent needless timeouts when the BIOS takes over during suspend or power-off operations.
  • Small changes to the functions which save/restore BIOS/port settings to avoid pitfalls; among others, the port save/restore code now also saves and restores the port's engine status.
  • Improvements to debug logging around port resets.
  • Moved code to clear pending interrupts from ahci_reset_port() to ahci_stop_port() because both need it and resetting a port involves stopping it, first.
  • NCQ mode has found to cause problems on a Dell D630. This may be related to the hard disk used for the test but since I've never seen more than one queued command regardless of the I/O load (even during simulaneous xcopy operations), NCQ mode is now off by default and needs to be turned on via the /N switch (i.e. the the /N switch now has a reversed meaning).
  • Removed the code which attempts to establish another MMIO base address in case the one assigned by the BIOS can't be reserved via resource manager; if there's a conflict, it's extremely unlikely we would ever be able to restore the BIOS MMIO address at boot time without the BIOS clashing with whatever conflicts with the MMIO address, thus there's no point trying to do any of this.
  • Implemented a reset context hook watchdog; in the early boot phase, some components apparently don't yield the CPU so the context hook will never execute without the watchdog. Now we'll give the context hook 10 seconds to execute, otherwise the watchdog will expire and we'll call the context hook directly from the corresponding timer callback.
Location:
trunk/src/os2ahci
Files:
9 edited

Legend:

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

    r79 r80  
    135135  for (i = 0; i < HOST_CAP2; i += sizeof(u32)) {
    136136    ai->bios_config[i / sizeof(u32)] = readl(ai->mmio + i);
     137  }
     138
     139  if ((ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN) == 0 &&
     140      ai->pci->vendor == PCI_VENDOR_ID_INTEL) {
     141    /* Adapter is not in AHCI mode and the spec says a COMRESET is
     142     * required when switching from SATA to AHCI mode and vice versa.
     143     */
     144    init_reset = 1;
    137145  }
    138146
     
    184192        if (val & HOST_CAP2_NVMHCI)    printf(" nvmhci");
    185193        if (val & HOST_CAP2_APST)      printf(" apst");
    186 
    187194      }
    188195      printf("\n");
     
    277284  ddprintf("restoring AHCI BIOS configuration\n");
    278285
    279   /* restore saved BIOS configuration */
    280   writel(ai->mmio + HOST_CTL,       ai->bios_config[HOST_CTL / sizeof(u32)]);
     286  /* Restore saved BIOS configuration; please note that HOST_CTL is restored
     287   * last because it may cause AHCI mode to be turned off again.
     288   */
    281289  writel(ai->mmio + HOST_CCC,       ai->bios_config[HOST_CCC / sizeof(u32)]);
    282290  writel(ai->mmio + HOST_CCC_PORTS, ai->bios_config[HOST_CCC_PORTS / sizeof(u32)]);
    283291  writel(ai->mmio + HOST_EM_CTL,    ai->bios_config[HOST_EM_CTL / sizeof(u32)]);
     292  writel(ai->mmio + HOST_CTL,       ai->bios_config[HOST_CTL / sizeof(u32)]);
    284293
    285294  /* flush PCI MMIO delayed write buffers */
    286   readl(ai->mmio + HOST_EM_CTL);
     295  readl(ai->mmio + HOST_CTL);
     296
     297  if ((ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN) == 0 &&
     298      ai->pci->vendor == PCI_VENDOR_ID_INTEL) {
     299
     300    /* This BIOS apparently accesses this controller via SATA registers and
     301     * the AHCI spec says that we should issue a COMRESET on each port after
     302     * disabling AHCI mode to allow the SATA controller to re-recognize attached
     303     * devices. How to do this depends on the controller, of course, but so
     304     * far I've only seen Dell notebook BIOSs with Intel chipsets to behave
     305     * like this; all other BIOS implementations I've seen so far seem to take
     306     * AHCI mode literally and operate the controller in AHCI mode from the
     307     * beginning.
     308     *
     309     * We'll use a feature on Intel ICH7/8 controllers which provides MMIO
     310     * mappings for the AHCI SCR registers even when not in AHCI mode.
     311     */
     312    int p;
     313
     314    for (p = 0; p < AHCI_MAX_PORTS; p++) {
     315      if (ai->port_map & (1UL << p)) {
     316        u8 _far *port_mmio = port_base(ai, p);
     317        u32 tmp;
     318
     319        tmp = readl(port_mmio + PORT_SCR_CTL) & ~0x0000000fUL;
     320        writel(port_mmio + PORT_SCR_CTL, tmp | 1);
     321        readl(port_mmio + PORT_SCR_CTL);  /* flush */
     322
     323        /* spec says "leave reset bit on for at least 1ms"; make it 2ms */
     324        mdelay(2);
     325
     326        writel(port_mmio + PORT_SCR_CTL, tmp);
     327        readl(port_mmio + PORT_SCR_CTL);  /* flush */
     328      }
     329    }
     330
     331    /* Wait some time to give the COMRESET a chance to complete (usually, at
     332     * least hard disks complete the reset within a few milliseonds)
     333     */
     334    mdelay(20);
     335  }
    287336
    288337  return(0);
     
    298347
    299348  /* restore saved BIOS configuration */
    300   writel(ai->mmio + HOST_CTL,       ai->bios_config[HOST_CTL / sizeof(u32)]);
    301349  writel(ai->mmio + HOST_CCC,       ai->bios_config[HOST_CCC / sizeof(u32)]);
    302350  writel(ai->mmio + HOST_CCC_PORTS, ai->bios_config[HOST_CCC_PORTS / sizeof(u32)]);
    303351  writel(ai->mmio + HOST_EM_CTL,    ai->bios_config[HOST_EM_CTL / sizeof(u32)]);
     352  writel(ai->mmio + HOST_CTL,       ai->bios_config[HOST_CTL / sizeof(u32)]);
    304353
    305354  /* flush PCI MMIO delayed write buffers */
    306   readl(ai->mmio + HOST_EM_CTL);
     355  readl(ai->mmio + HOST_CTL);
    307356
    308357  /* (re-)enable AHCI mode */
     
    333382  pc->fis_rx_h   = readl(port_mmio + PORT_FIS_ADDR_HI);
    334383  pc->irq_mask   = readl(port_mmio + PORT_IRQ_MASK);
     384  pc->port_cmd   = readl(port_mmio + PORT_CMD);
    335385
    336386  return(pc);
     
    341391 * configuration (command list and FIS buffers and the IRQ mask).
    342392 *
    343  * The port configuration automatically freed.
     393 * The port configuration is automatically freed.
    344394 */
    345395void ahci_restore_port_config(AD_INFO *ai, int p, AHCI_PORT_CFG *pc)
     
    347397  u8 _far *port_mmio = port_base(ai, p);
    348398
    349   writel(port_mmio + PORT_LST_ADDR,    pc->cmd_list);
    350   writel(port_mmio + PORT_LST_ADDR_HI, pc->cmd_list_h);
    351   writel(port_mmio + PORT_FIS_ADDR,    pc->fis_rx);
    352   writel(port_mmio + PORT_FIS_ADDR_HI, pc->fis_rx_h);
    353   writel(port_mmio + PORT_IRQ_MASK,    pc->irq_mask);
    354 
    355   readl(port_base(ai, p) + PORT_IRQ_MASK); /* flush */
     399  /* stop the port, first */
     400  ahci_stop_port(ai, p);
     401
     402  if (ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN) {
     403    /* BIOS uses AHCI, too, so we need to restore the port settings;
     404     * restoring PORT_CMD way well start the port again but that's what
     405     * this function is all about.
     406     */
     407    writel(port_mmio + PORT_LST_ADDR,    pc->cmd_list);
     408    writel(port_mmio + PORT_LST_ADDR_HI, pc->cmd_list_h);
     409    writel(port_mmio + PORT_FIS_ADDR,    pc->fis_rx);
     410    writel(port_mmio + PORT_FIS_ADDR_HI, pc->fis_rx_h);
     411    writel(port_mmio + PORT_IRQ_MASK,    pc->irq_mask);
     412    writel(port_mmio + PORT_CMD,         pc->port_cmd);
     413
     414    readl(port_base(ai, p) + PORT_IRQ_MASK); /* flush */
     415  }
    356416
    357417  free(pc);
     
    439499      /* start/reset port; if no device is attached, this is expected to fail */
    440500      if (init_reset) {
    441         ddprintf("init-resetting port #%d\n", p);
    442501        rc = ahci_reset_port(ai, p, 0);
    443502      } else {
     
    547606  for (p = 0; p < AHCI_MAX_PORTS; p++) {
    548607    if (ai->port_map & (1UL << p)) {
    549       dprintf("restarting port #%d\n", p);
    550       ahci_stop_port(ai, p);
    551       ahci_start_port(ai, p, 1);
     608      if (init_reset) {
     609        ahci_reset_port(ai, p, 1);
     610      } else {
     611        dprintf("restarting port #%d\n", p);
     612        ahci_stop_port(ai, p);
     613        ahci_start_port(ai, p, 1);
     614      }
    552615    }
    553616  }
     
    561624  readl(ai->mmio + HOST_CTL); /* flush */
    562625
    563   /* enable interrupts on PCI-level (PCI 2.3 added a feature to disable ints) */
     626  /* enable interrupts on PCI-level (PCI 2.3 added a feature to disable INTs) */
    564627  /* pci_enable_int(ai->bus, ai->dev_func); */
    565628
     
    586649
    587650  dprintf("resetting port %d.%d\n", ad_no(ai), p);
    588   ddprintf(" PORT_CMD_ISSUE = 0x%lx\n", readl(port_mmio + PORT_CMD_ISSUE));
    589   ddprintf(" PORT_SCR_ACT   = 0x%lx\n", readl(port_mmio + PORT_SCR_ACT));
    590   ddprintf(" PORT_SCR_ERR   = 0x%lx\n", readl(port_mmio + PORT_SCR_ERR));
    591   ddprintf(" PORT_TFDATA    = 0x%lx\n", readl(port_mmio + PORT_TFDATA));
    592   ddprintf(" PORT_IRQ_STAT  = 0x%lx\n", readl(port_mmio + PORT_IRQ_STAT));
    593   ddprintf(" PORT_IRQ_MASK  = 0x%lx\n", readl(port_mmio + PORT_IRQ_MASK));
    594   ddprintf(" HOST_IRQ_STAT  = 0x%lx\n", readl(ai->mmio + HOST_IRQ_STAT));
     651  if (debug > 1) {
     652    printf("command engine status:\n");
     653    printf(" PORT_SCR_ACT   = 0x%lx\n", readl(port_mmio + PORT_SCR_ACT));
     654    printf(" PORT_CMD_ISSUE = 0x%lx\n", readl(port_mmio + PORT_CMD_ISSUE));
     655    printf("link/device status:\n");
     656    printf(" PORT_SCR_STAT  = 0x%lx\n", readl(port_mmio + PORT_SCR_STAT));
     657    printf(" PORT_SCR_CTL   = 0x%lx\n", readl(port_mmio + PORT_SCR_CTL));
     658    printf(" PORT_SCR_ERR   = 0x%lx\n", readl(port_mmio + PORT_SCR_ERR));
     659    printf(" PORT_TFDATA    = 0x%lx\n", readl(port_mmio + PORT_TFDATA));
     660    printf("interrupt status:\n");
     661    printf(" PORT_IRQ_STAT  = 0x%lx\n", readl(port_mmio + PORT_IRQ_STAT));
     662    printf(" PORT_IRQ_MASK  = 0x%lx\n", readl(port_mmio + PORT_IRQ_MASK));
     663    printf(" HOST_IRQ_STAT  = 0x%lx\n", readl(ai->mmio + HOST_IRQ_STAT));
     664  }
    595665
    596666  /* stop port engines (we don't care whether there is an error doing so) */
     
    600670  tmp = readl(port_mmio + PORT_SCR_ERR);
    601671  writel(port_mmio + PORT_SCR_ERR, tmp);
    602 
    603   /* clear pending port IRQs */
    604   tmp = readl(port_mmio + PORT_IRQ_STAT);
    605   if (tmp) {
    606     writel(port_mmio + PORT_IRQ_STAT, tmp);
    607   }
    608   writel(ai->mmio + HOST_IRQ_STAT, 1UL << p);
    609672
    610673  /* set link speed and power management options */
     
    721784  u32 tmp;
    722785
    723   /* set comand header and FIS address registers */
     786  /* set command header and FIS address registers */
    724787  writel(port_mmio + PORT_LST_ADDR, port_dma + offsetof(AHCI_PORT_DMA, cmd_hdr));
    725788  writel(port_mmio + PORT_LST_ADDR_HI, 0);
     
    757820{
    758821  u8 _far *port_mmio = port_base(ai, p);
     822  u32 tmp;
    759823  int rc;
    760824
     
    773837    return(rc);
    774838  }
     839
     840  /* clear any pending port IRQs */
     841  tmp = readl(port_mmio + PORT_IRQ_STAT);
     842  if (tmp) {
     843    writel(port_mmio + PORT_IRQ_STAT, tmp);
     844  }
     845  writel(ai->mmio + HOST_IRQ_STAT, 1UL << p);
    775846
    776847  /* reset PxSACT register (tagged command queues, not reset by COMRESET) */
     
    10231094  }
    10241095
    1025   /* restart port (includes the necessary port configuration) */
    1026   if (ahci_stop_port(ai, p) || ahci_start_port(ai, p, 0)) {
     1096  /* restart/reset port (includes the necessary port configuration) */
     1097  if ((ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN) == 0 &&
     1098      ai->pci->vendor == PCI_VENDOR_ID_INTEL) {
     1099    /* As outlined in ahci_restore_bios_config(), switching back and
     1100     * forth between SATA and AHCI mode requires a COMRESET to force
     1101     * the corresponding controller subsystem to rediscover attached
     1102     * devices. Thus, we'll reset the port instead of stopping and
     1103     * starting it.
     1104     */
     1105    if (ahci_reset_port(ai, p, 0)) {
     1106      iorb_seterr(iorb, IOERR_ADAPTER_NONSPECIFIC);
     1107      goto restore_bios_config;
     1108    }
     1109
     1110  } else if (ahci_stop_port(ai, p) || ahci_start_port(ai, p, 0)) {
    10271111    iorb_seterr(iorb, IOERR_ADAPTER_NONSPECIFIC);
    10281112    goto restore_bios_config;
     
    15001584  } else {
    15011585    /* complete ATA-specific device information */
    1502     if (disable_ncq[ad_no(ai)][p]) {
    1503       /* MT: set ncq_max to 1 if NCQ is disabled for this port */
     1586    if (enable_ncq[ad_no(ai)][p]) {
     1587      ai->ports[p].devs[d].ncq_max = id_buf[ATA_ID_QUEUE_DEPTH] & 0x001fU;
     1588    }
     1589    if (ai->ports[p].devs[d].ncq_max < 1) {
     1590      /* NCQ not enabled for this device, or device doesn't support NCQ */
    15041591      ai->ports[p].devs[d].ncq_max = 1;
    1505       dprintf("NCQ off for a:%d p:%d\n", (int) ad_no(ai), p);
    1506     } else {
    1507       ai->ports[p].devs[d].ncq_max = max(id_buf[ATA_ID_QUEUE_DEPTH] & 0x001fU, 1);
    1508       dprintf("NCQ max=%d for a:%d p:%d\n", ai->ports[p].devs[d].ncq_max,
    1509                                             (int) ad_no(ai), p);
    1510     }
    1511 
     1592    }
    15121593    if (id_buf[ATA_ID_CFS_ENABLE_2] & 0x0400U) {
    15131594      ai->ports[p].devs[d].lba48   = 1;
     
    15151596  }
    15161597
    1517   dprintf("found device %d.%d.%d: removable = %d, dev_type = %d, atapi = %d\n",
    1518           ad_no(ai), p, d,
     1598  dprintf("found device %d.%d.%d: removable = %d, dev_type = %d, atapi = %d, "
     1599          "ncq_max = %d\n", ad_no(ai), p, d,
    15191600          ai->ports[p].devs[d].removable,
    15201601          ai->ports[p].devs[d].dev_type,
    1521           ai->ports[p].devs[d].atapi);
     1602          ai->ports[p].devs[d].atapi,
     1603          ai->ports[p].devs[d].ncq_max);
    15221604
    15231605  /* add device to resource manager; we don't really care about errors here */
  • trunk/src/os2ahci/ahci.h

    r44 r80  
    276276  u32   fis_rx_h;                          /* FIS receive bufffer high */
    277277  u32   irq_mask;                          /* IRQ mask */
     278  u32   port_cmd;                          /* port engine status */
    278279} AHCI_PORT_CFG;
    279280
  • trunk/src/os2ahci/ata.c

    r71 r80  
    501501    geometry->TotalCylinders  = ATA_CYLS(id_buf);
    502502
    503   }
    504  
    505   /* MT: if neither ATA nor BIOS supply valid data, or if their
    506    *     CHS values result in a sector count lower than determined,
    507    *     we use a typical [SCSI] BIOS algorithm
    508    */
    509   if ((u32) geometry->NumHeads * (u32) geometry->SectorsPerTrack *
    510           (u32) geometry->TotalCylinders < geometry->TotalSectors) {
     503  } else {
     504    /* use typical SCSI geometry */
    511505    geometry->NumHeads        = 255;
    512506    geometry->SectorsPerTrack = 63;
  • trunk/src/os2ahci/ctxhook.c

    r77 r80  
    3838/* port reset context hook and input data */
    3939ULONG           reset_ctxhook_h;
     40ULONG           th_reset_watchdog;
    4041volatile u32    ports_to_reset[MAX_AD];
    4142IORB_QUEUE      abort_queue;
     
    284285  spin_lock(drv_lock);
    285286
     287  if (th_reset_watchdog != 0) {
     288    /* watchdog timer still active -- just reset it */
     289    ADD_CancelTimer(th_reset_watchdog);
     290    th_reset_watchdog = 0;
     291  }
     292
    286293  /* add ports of active IORBs from the abort queue to ports_to_reset[] */
    287294  for (iorb = abort_queue.root; iorb != NULL; iorb = next) {
  • trunk/src/os2ahci/os2ahci.c

    r77 r80  
    101101/* apapter/port-specific options saved when parsing the command line */
    102102u8              emulate_scsi[MAX_AD][AHCI_MAX_PORTS];
    103 u8              disable_ncq[MAX_AD][AHCI_MAX_PORTS];
     103u8              enable_ncq[MAX_AD][AHCI_MAX_PORTS];
    104104u8              link_speed[MAX_AD][AHCI_MAX_PORTS];
    105105u8              link_power[MAX_AD][AHCI_MAX_PORTS];
     
    261261      case 'n':
    262262        /* disable NCQ */
    263         set_port_option(disable_ncq, !invert_option);
     263        set_port_option(enable_ncq, !invert_option);
    264264        break;
    265265
     
    789789 *        requests.
    790790 *
    791  *        In order to support applications that can't deal with ATAPI devies
     791 *        In order to support applications that can't deal with ATAPI devices
    792792 *        (i.e. need a SCSI adapter) os2ahci will optionally report ATAPI
    793793 *        dvices as SCSI devices. The corresponding SCSI adapter doesn't
    794  *        really  exist and is only reported here for the IOCM_GET_DEVICETABLE
     794 *        really exist and is only reported here for the IOCM_GET_DEVICETABLE
    795795 *        request. The units attached to this adapter will use the real HW
    796796 *        unit IDs, thus we'll never receive a command specific to the
     
    11641164
    11651165/******************************************************************************
    1166  * Complete an IORB. It should be called without the adapter-level spinlock
     1166 * Complete an IORB. This should be called without the adapter-level spinlock
    11671167 * to allow the IORB completion routine to perform whatever processing it
    11681168 * requires. This implies that the IORB should no longer be in any global
     
    12201220/******************************************************************************
    12211221 * Lock the adapter, waiting for availability if necessary. This is expected
    1222  * to be called without the driver-level spinlock aquired.
     1222 * to be called at task/request time without the driver-level spinlock
     1223 * aquired. Don't call at interrupt time.
    12231224 */
    12241225void lock_adapter(AD_INFO *ai)
     
    12821283   */
    12831284  DevHelp_ArmCtxHook(0, reset_ctxhook_h);
     1285
     1286  /* Set up a watchdog timer which calls the context hook manually in case
     1287   * some kernel thread is looping around the IORB_COMPLETE status bit
     1288   * without yielding the CPU (kernel threads don't preempt). This shouldn't
     1289   * happen per design because kernel threads are supposed to yield but it
     1290   * does in the early boot phase.
     1291   */
     1292  ADD_StartTimerMS(&th_reset_watchdog, 5000, (PFN) reset_watchdog, 0, 0);
     1293}
     1294
     1295/******************************************************************************
     1296 * Reset handler watchdog. If a timeout occurs, a context hook is armed which
     1297 * will execute as soon as a kernel thread yields the CPU. However, some
     1298 * kernel components won't yield the CPU during the early boot phase and the
     1299 * only way to kick some sense into those components is to run the context
     1300 * hook right inside this timer callback. Not exactly pretty, especially
     1301 * considering the fact that context hooks were implemented to prevent running
     1302 * lengthy operations like a port reset at task time, but without this
     1303 * watchdog mechanism we run the risk of getting completely stalled by device
     1304 * problems during the early boot phase.
     1305 */
     1306void _cdecl _far reset_watchdog(ULONG timer_handle, ULONG p1,
     1307                                ULONG p2)
     1308{
     1309  /* reset watchdog timer */
     1310  ADD_CancelTimer(timer_handle);
     1311  dprintf("reset watchdog invoked\n");
     1312
     1313  /* call context hook manually */
     1314  reset_ctxhook(0);
    12841315}
    12851316
  • trunk/src/os2ahci/os2ahci.def

    r79 r80  
    11library os2ahci
    2 Description '$@#thi.guten (www.thiguten.de):1.00.20110224#@OS/2 AHCI Adapter Device Driver'
     2Description '$@#thi.guten (www.thiguten.de):1.00.20110228#@OS/2 AHCI Adapter Device Driver'
    33protmode
    44
  • trunk/src/os2ahci/os2ahci.h

    r77 r80  
    383383extern void    unlock_adapter         (AD_INFO *ai);
    384384extern void _cdecl _far timeout_callback    (ULONG timer_handle, ULONG p1, ULONG p2);
     385extern void _cdecl _far reset_watchdog      (ULONG timer_handle, ULONG p1, ULONG p2);
    385386
    386387/* ahci.c */
     
    499500/* port reset context hook and input data */
    500501extern ULONG         reset_ctxhook_h;
     502extern ULONG         th_reset_watchdog;
    501503extern volatile u32  ports_to_reset[MAX_AD];
    502504extern IORB_QUEUE    abort_queue;
     
    507509/* apapter/port-specific options saved when parsing the command line */
    508510extern u8            emulate_scsi[MAX_AD][AHCI_MAX_PORTS];
    509 extern u8            disable_ncq[MAX_AD][AHCI_MAX_PORTS];
     511extern u8            enable_ncq[MAX_AD][AHCI_MAX_PORTS];
    510512extern u8            link_speed[MAX_AD][AHCI_MAX_PORTS];
    511513extern u8            link_power[MAX_AD][AHCI_MAX_PORTS];
  • trunk/src/os2ahci/pci.c

    r79 r80  
    183183 * other strings
    184184 */
    185 static char s_already_claimed[] = "Warning: device already claimed by other driver.\n";
     185static char s_already_claimed[] = "Warning: device already claimed by another driver.\n";
    186186
    187187
     
    684684   *       the MMIO base address register (BAR), read back the resulting value
    685685   *       and check the 0 bits from the right end. After doing this, we must
    686    *       restore the original value set up by the BIOS because we're not yet
    687    *       ready to take over.
     686   *       restore the original value set up by the BIOS.
    688687   *
    689688   * The least significant 4 bits are not relevant for the MMIO address, thus
     
    713712       mmio_size <<= 1);
    714713
    715   ddprintf("MMIO size            = %ld\n", mmio_size);
    716   ddprintf("MMIO address (BIOS)  = 0x%08lx\n", mmio_bios & 0xfffffff0UL);
     714  ddprintf("MMIO size    = %ld\n", mmio_size);
     715  ddprintf("MMIO address = 0x%08lx\n", mmio_bios & 0xfffffff0UL);
    717716
    718717  /* register BIOS MMIO address space with resource manager */
     
    724723
    725724  ret = RMAllocResource(rm_drvh, &ad_info->rm_mmio, &resource);
    726 
    727725  if (ret != RMRC_SUCCESS) {
    728726    if (ret == RMRC_RES_ALREADY_CLAIMED) {
    729       /* MT: according to my observations, this is the 2nd place
    730        * where we could fail due to the adapter having been already
    731        * claimed by another driver...
    732        */
    733727      cprintf(s_already_claimed);
    734       return;
     728    } else {
     729      cprintf("error: couldn't register MMIO region (rc = %d)\n", ret);
    735730    }
    736     /* didn't work; try to find another MMIO region */
    737     cprintf("warning: BIOS MMIO address not accepted by resource manager "
    738             "(code %d)\n", ret);
    739     memset(&resource, 0x00, sizeof(resource));
    740     resource.ResourceType         = RS_TYPE_MEM;
    741     resource.MEMResource.MemSize  = mmio_size;
    742     resource.MEMResource.MemFlags = RS_MEM_EXCLUSIVE | RS_SEARCH;
    743    
    744     ret = RMAllocResource(rm_drvh, &ad_info->rm_mmio, &resource);
    745    
    746     if (ret == RMRC_SUCCESS) {
    747       /* MT: got a new address from Resource Manager; now we
    748        * need to tell PCI about the new address.
    749        * Leave the last 4 bits of the original MMIO value alone.
    750        */
    751       mmio_bios = (mmio_bios & 0x0000000fUL) |
    752         (resource.MEMResource.MemBase & 0xfffffff0UL);
    753       ddprintf("address we got from RM: 0x%08lx\n",
    754                resource.MEMResource.MemBase);
    755       ddprintf("setting new MMIO addr to 0x%08lx\n", mmio_bios);
    756      
    757       if (pci_write_conf(bus, dev_func, AHCI_MMIO,
    758                          sizeof(u32), mmio_bios) != OH_SUCCESS) {
    759         /* failed to update MMIO address - bail out */
    760         cprintf("error: couldn't update MMIO address\n");
    761         ret = ~RMRC_SUCCESS;
    762         return;
    763       }
    764     }
    765   }
    766 
    767   if (ret != RMRC_SUCCESS) {
    768     cprintf("error: couldn't register MMIO region (rc = %d)\n", ret);
    769731    return;
    770732  }
    771733  rc_list->hResource[rc_list->NumResource++] = ad_info->rm_mmio;
    772   ddprintf("MMIO address (final) = 0x%08lx\n", resource.MEMResource.MemBase);
    773734
    774735  /****************************************************************************
  • trunk/src/os2ahci/version.h

    r79 r80  
    66
    77
    8 #define VERSION            105       /* driver version (2 implied decimals) */
     8#define VERSION            106       /* driver version (2 implied decimals) */
    99
    1010/* BLDLEVEL information (in C source modules added via macro
Note: See TracChangeset for help on using the changeset viewer.