Changeset 81 for trunk


Ignore:
Timestamp:
Mar 1, 2011, 9:19:08 PM (14 years ago)
Author:
chris
Message:

Version 1.07
============

  • Changed resource allocation such that all PCI BARs will be registered, even the ones which are related to legacy interfaces, to prevent other drivers from accessing the adapter. This didn't work as well as anticipated because DANIS506.ADD currently doesn't skip an adapter just because resources could not be registered but this can be fixed, of course, and the end result would be that by simply changing the load order of DANIS506.ADD and OS2AHCI.ADD would be sufficient to determine which driver controls AHCI-capable SATA adapters.
Location:
trunk/src/os2ahci
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/os2ahci/os2ahci.def

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

    r80 r81  
    315315
    316316  HRESOURCE     rm_adh;                /* resource handle for adapter */
    317   HRESOURCE     rm_mmio;               /* resource handle for MMIO */
     317  HRESOURCE     rm_bars[6];            /* resource handle for MMIO and I/O BARs */
    318318  HRESOURCE     rm_irq;                /* resource handle for IRQ */
    319319
     
    323323
    324324  u32           mmio_phys;             /* physical address of MMIO region */
     325  u32           mmio_size;             /* size of MMIO region */
    325326  u8      _far *mmio;                  /* pointer to this adapter's MMIO region */
    326327
  • trunk/src/os2ahci/pci.c

    r80 r81  
    2626
    2727/* offset of PCI base address register (BAR) in the PCI config space */
    28 #define PCI_BAR(reg)   (0x10 + (reg) * sizeof(u32))
    29 
    30 /* offset of MMIO base address register (BAR) for AHCI adapters */
    31 #define AHCI_MMIO      PCI_BAR(AHCI_PCI_BAR)
     28#define PCI_BAR(reg)   (UCHAR) (0x10 + (reg) * sizeof(u32))
    3229
    3330/******************************************************************************
     
    152149static int   oemhlp_call      (UCHAR subfunction, OH_PARM _far *parm,
    153150                               OH_DATA _far *data);
     151static long  bar_resource     (UCHAR bus, UCHAR dev_func,
     152                               RESOURCESTRUCT _far *resource, int i);
     153static char *rmerr            (APIRET ret);
    154154
    155155/* ------------------------ global/static variables ------------------------ */
     
    533533static void add_pci_device(PCI_ID *pci_id, OH_DATA _far *data)
    534534{
    535   char rc_list_buf[sizeof(AHRESOURCE) + sizeof(HRESOURCE) * 4];
     535  char rc_list_buf[sizeof(AHRESOURCE) + sizeof(HRESOURCE) * 15];
    536536  AHRESOURCE _far *rc_list = (AHRESOURCE _far *) rc_list_buf;
    537537  RESOURCESTRUCT resource;
     
    548548  u16 vendor;
    549549  u32 class;
    550   u32 mmio_bios = 0;
    551   u32 mmio_size;
    552   u32 mmio_rqd;
    553550  int irq;
    554551  int pin;
     
    666663
    667664  ret = RMAllocResource(rm_drvh, &ad_info->rm_irq, &resource);
    668   switch (ret) {
    669     case RMRC_SUCCESS:
    670       break;
    671     case RMRC_DEV_ALREADY_CLAIMED:
    672     case RMRC_RES_ALREADY_CLAIMED:
    673       cprintf(s_already_claimed);
    674       return;
    675     default:
    676       cprintf("error: couldn't register IRQ %d (rc = %d)\n", irq, ret);
    677       return;
     665  if (ret != RMRC_SUCCESS) {
     666    cprintf("error: couldn't register IRQ %d (rc = %s)\n", irq, rmerr(ret));
     667    return;
    678668  }
    679669  rc_list->hResource[rc_list->NumResource++] = ad_info->rm_irq;
    680670
    681   /* Determine MMIO size for this device
    682    *
    683    * NOTE: In order to do this, we need to temporarily write 0xffffffff to
    684    *       the MMIO base address register (BAR), read back the resulting value
    685    *       and check the 0 bits from the right end. After doing this, we must
    686    *       restore the original value set up by the BIOS.
    687    *
    688    * The least significant 4 bits are not relevant for the MMIO address, thus
    689    * we'll start at 0x10:
    690    *
    691    *  31                                                        4 3 2 1 0
    692    *  -------------------------------------------------------------------
    693    *                        base address                          P T T I
    694    *  P = prefetchable
    695    *  T = type
    696    *  I = I/O (1) or memory (0)
     671  /* Allocate all I/O and MMIO addresses offered by this device. In theory,
     672   * we need only BAR #5, the AHCI MMIO BAR, but in order to prevent any
     673   * other driver from hijacking our device and accessing it via legacy
     674   * registers we'll reserve anything we can find.
    697675   */
    698   if (pci_read_conf (bus, dev_func, AHCI_MMIO, sizeof(u32), &mmio_bios) != OH_SUCCESS ||
    699       pci_write_conf(bus, dev_func, AHCI_MMIO, sizeof(u32), ~(0UL))     != OH_SUCCESS ||
    700       pci_read_conf (bus, dev_func, AHCI_MMIO, sizeof(u32), &mmio_rqd)  != OH_SUCCESS ||
    701       pci_write_conf(bus, dev_func, AHCI_MMIO, sizeof(u32), mmio_bios)  != OH_SUCCESS) {
    702 
    703     cprintf("error: couldn't determine MMIO size\n");
    704     if (mmio_bios != 0) {
    705       cprintf("restoring BIOS MMIO address\n");
    706       pci_write_conf(bus, dev_func, AHCI_MMIO, sizeof(u32), mmio_bios);
     676  for (i = 0; i < sizeof(ad_info->rm_bars) / sizeof(*ad_info->rm_bars); i++) {
     677    long len = bar_resource(bus, dev_func, &resource, i);
     678   
     679    if (len < 0) {
     680      /* something went wrong */
     681      goto add_pci_fail;
    707682    }
    708     return;
    709   }
    710   for (mmio_size = 0x00000010UL;
    711        mmio_size < 0x10000000UL && (mmio_rqd & mmio_size) == 0;
    712        mmio_size <<= 1);
    713 
    714   ddprintf("MMIO size    = %ld\n", mmio_size);
    715   ddprintf("MMIO address = 0x%08lx\n", mmio_bios & 0xfffffff0UL);
    716 
    717   /* register BIOS MMIO address space with resource manager */
    718   memset(&resource, 0x00, sizeof(resource));
    719   resource.ResourceType         = RS_TYPE_MEM;
    720   resource.MEMResource.MemBase  = mmio_bios & 0xfffffff0UL;
    721   resource.MEMResource.MemSize  = mmio_size;
    722   resource.MEMResource.MemFlags = RS_MEM_EXCLUSIVE;
    723 
    724   ret = RMAllocResource(rm_drvh, &ad_info->rm_mmio, &resource);
    725   if (ret != RMRC_SUCCESS) {
    726     if (ret == RMRC_RES_ALREADY_CLAIMED) {
    727       cprintf(s_already_claimed);
    728     } else {
    729       cprintf("error: couldn't register MMIO region (rc = %d)\n", ret);
     683    if (len == 0) {
     684      /* this BAR is unused */
     685      continue;
    730686    }
    731     return;
    732   }
    733   rc_list->hResource[rc_list->NumResource++] = ad_info->rm_mmio;
     687
     688    if (i == AHCI_PCI_BAR) {
     689      if (resource.ResourceType != RS_TYPE_MEM) {
     690        cprintf("error: BAR #5 must be an MMIO region\n");
     691        goto add_pci_fail;
     692      }
     693      /* save this BAR's address as MMIO address */
     694      ad_info->mmio_phys = resource.MEMResource.MemBase;
     695      ad_info->mmio_size = resource.MEMResource.MemSize;
     696    }
     697
     698    /* register [MM]IO region with resource manager */
     699    ret = RMAllocResource(rm_drvh, ad_info->rm_bars + i, &resource);
     700    if (ret != RMRC_SUCCESS) {
     701      cprintf("error: couldn't register [MM]IO region (rc = %s)\n", rmerr(ret));
     702      goto add_pci_fail;
     703    }
     704    rc_list->hResource[rc_list->NumResource++] = ad_info->rm_bars[i];
     705  }
     706
     707  if (ad_info->mmio_phys == 0) {
     708    cprintf("error: couldn't determine MMIO base address\n");
     709    goto add_pci_fail;
     710  }
    734711
    735712  /****************************************************************************
     
    742719  ad_info->dev_func = dev_func;
    743720  ad_info->irq      = irq;
    744   ad_info->mmio_phys = resource.MEMResource.MemBase;
    745721
    746722  /* allocate memory for port-specific DMA scratch buffers */
     
    760736
    761737  /* map MMIO address to first GDT selector */
    762   if (DevHelp_PhysToGDTSelector(ad_info->mmio_phys, (USHORT) mmio_size,
    763                                 gdt[0]) != 0) {
     738  if (DevHelp_PhysToGDTSelector(ad_info->mmio_phys,
     739                                (USHORT) ad_info->mmio_size, gdt[0]) != 0) {
    764740    cprintf("error: couldn't map MMIO address to GDT selector\n");
    765741    goto add_pci_fail;
     
    803779  ret = RMCreateAdapter(rm_drvh, &ad_info->rm_adh, &adapter, NULL, rc_list);
    804780  if (ret != RMRC_SUCCESS) {
    805     cprintf("error: couldn't register adapter (rc = %d)\n", ret);
     781    cprintf("error: couldn't register adapter (rc = %s)\n", rmerr(ret));
    806782    goto add_pci_fail;
    807783  }
     
    816792add_pci_fail:
    817793  /* something went wrong; try to clean up as far as possible */
    818   if (ad_info->rm_mmio != 0) {
    819     RMDeallocResource(rm_drvh, ad_info->rm_mmio);
     794  for (i = 0; i < sizeof(ad_info->rm_bars) / sizeof(*ad_info->rm_bars); i++) {
     795    if (ad_info->rm_bars[i] != 0) {
     796      RMDeallocResource(rm_drvh, ad_info->rm_bars[i]);
     797    }
    820798  }
    821799  if (ad_info->rm_irq != 0) {
    822800    RMDeallocResource(rm_drvh, ad_info->rm_irq);
    823   }
    824   if (&ad_info->dma_buf_phys != 0) {
    825     DevHelp_FreePhys(ad_info->dma_buf_phys);
    826801  }
    827802  for (i = 0; i < sizeof(gdt) / sizeof(*gdt); i++) {
     
    829804      DevHelp_FreeGDTSelector(gdt[i]);
    830805    }
     806  }
     807  if (ad_info->dma_buf_phys != 0) {
     808    DevHelp_FreePhys(ad_info->dma_buf_phys);
    831809  }
    832810}
     
    960938  }
    961939  return(data->bios_info.rc);
     940}
     941
     942/******************************************************************************
     943 * Prepare a resource structure for a PCI Base Address Register (BAR). This
     944 * basically means the type, address and range of the I/O address space. It
     945 * returns the length of the address range as a signed long to allow the caller
     946 * to differentiate between error conditions (< 0), unused BARs (0) or valid
     947 * bars (> 0).
     948 *
     949 * NOTE: In order to do this, we need to temporarily write 0xffffffff to
     950 *       the MMIO base address register (BAR), read back the resulting value
     951 *       and check the 0 bits from the right end, masking the lower 2 (I/O) or
     952 *       4 (MMIO) bits. After doing this, we must restore the original value
     953 *       set up by the BIOS.
     954 *
     955 *  31                                                        4 3 2 1 0
     956 *  -------------------------------------------------------------------
     957 *                        base address                          P T T I
     958 *  P = prefetchable
     959 *  T = type (0 = any 32 bit, 1 = <1M, 2 = 64 bit)
     960 *  I = I/O (1) or memory (0)
     961 */
     962static long bar_resource(UCHAR bus, UCHAR dev_func,
     963                         RESOURCESTRUCT _far *resource, int i)
     964{
     965  u32 bar_addr = 0;
     966  u32 bar_size = 0;
     967
     968  /* temporarily write 1s to this BAR to determine the address range */
     969  if (pci_read_conf (bus, dev_func, PCI_BAR(i), sizeof(u32), &bar_addr) != OH_SUCCESS ||
     970      pci_write_conf(bus, dev_func, PCI_BAR(i), sizeof(u32), ~(0UL))    != OH_SUCCESS ||
     971      pci_read_conf (bus, dev_func, PCI_BAR(i), sizeof(u32), &bar_size) != OH_SUCCESS ||
     972      pci_write_conf(bus, dev_func, PCI_BAR(i), sizeof(u32), bar_addr)  != OH_SUCCESS) {
     973
     974    cprintf("error: couldn't determine [MM]IO size\n");
     975    if (bar_addr != 0) {
     976      pci_write_conf(bus, dev_func, PCI_BAR(i), sizeof(u32), bar_addr);
     977    }
     978    return(-1);
     979  }
     980
     981  if (bar_size == 0 || bar_size == 0xffffffffUL) {
     982    /* bar not implemented or device not working properly */
     983    return(0);
     984  }
     985
     986  /* prepare resource allocation structure */
     987  memset(resource, 0x00, sizeof(*resource));
     988  if (bar_addr & 1) {
     989    bar_size = ~(bar_size & 0xfffffffcUL) + 1;
     990    bar_size &= 0xffffUL;  /* I/O address space is 16 bits on x86 */
     991    bar_addr &= 0xfffcUL;
     992
     993    resource->ResourceType              = RS_TYPE_IO;
     994    resource->IOResource.BaseIOPort     = bar_addr;
     995    resource->IOResource.NumIOPorts     = bar_size;
     996    resource->IOResource.IOFlags        = RS_IO_EXCLUSIVE;
     997    resource->IOResource.IOAddressLines = 16;
     998
     999  } else {
     1000    bar_size = ~(bar_size & 0xfffffff0UL) + 1;
     1001    bar_addr &= 0xfffffff0UL;
     1002
     1003    resource->ResourceType         = RS_TYPE_MEM;
     1004    resource->MEMResource.MemBase  = bar_addr;
     1005    resource->MEMResource.MemSize  = bar_size;
     1006    resource->MEMResource.MemFlags = RS_MEM_EXCLUSIVE;
     1007  }
     1008
     1009  ddprintf("BAR #%d: type = %s, addr = 0x%08lx, size = %ld\n", i,
     1010           (resource->ResourceType == RS_TYPE_IO) ? "I/O" : "MMIO",
     1011           bar_addr, bar_size);
     1012
     1013  return((long) bar_size);
    9621014}
    9631015
     
    10251077  return s_generic;
    10261078}
     1079
     1080/******************************************************************************
     1081 * Return textual version of a resource manager error
     1082 */
     1083static char *rmerr(APIRET ret)
     1084{
     1085  switch (ret) {
     1086  case RMRC_SUCCESS:
     1087    return("RMRC_SUCCESS");
     1088  case RMRC_NOTINITIALIZED:
     1089    return("RMRC_NOTINITIALIZED");
     1090  case RMRC_BAD_DRIVERHANDLE:
     1091    return("RMRC_BAD_DRIVERHANDLE");
     1092  case RMRC_BAD_ADAPTERHANDLE:
     1093    return("RMRC_BAD_ADAPTERHANDLE");
     1094  case RMRC_BAD_DEVICEHANDLE:
     1095    return("RMRC_BAD_DEVICEHANDLE");
     1096  case RMRC_BAD_RESOURCEHANDLE:
     1097    return("RMRC_BAD_RESOURCEHANDLE");
     1098  case RMRC_BAD_LDEVHANDLE:
     1099    return("RMRC_BAD_LDEVHANDLE");
     1100  case RMRC_BAD_SYSNAMEHANDLE:
     1101    return("RMRC_BAD_SYSNAMEHANDLE");
     1102  case RMRC_BAD_DEVHELP:
     1103    return("RMRC_BAD_DEVHELP");
     1104  case RMRC_NULL_POINTER:
     1105    return("RMRC_NULL_POINTER");
     1106  case RMRC_NULL_STRINGS:
     1107    return("RMRC_NULL_STRINGS");
     1108  case RMRC_BAD_VERSION:
     1109    return("RMRC_BAD_VERSION");
     1110  case RMRC_RES_ALREADY_CLAIMED:
     1111    return("RMRC_RES_ALREADY_CLAIMED");
     1112  case RMRC_DEV_ALREADY_CLAIMED:
     1113    return("RMRC_DEV_ALREADY_CLAIMED");
     1114  case RMRC_INVALID_PARM_VALUE:
     1115    return("RMRC_INVALID_PARM_VALUE");
     1116  case RMRC_OUT_OF_MEMORY:
     1117    return("RMRC_OUT_OF_MEMORY");
     1118  case RMRC_SEARCH_FAILED:
     1119    return("RMRC_SEARCH_FAILED");
     1120  case RMRC_BUFFER_TOO_SMALL:
     1121    return("RMRC_BUFFER_TOO_SMALL");
     1122  case RMRC_GENERAL_FAILURE:
     1123    return("RMRC_GENERAL_FAILURE");
     1124  case RMRC_IRQ_ENTRY_ILLEGAL:
     1125    return("RMRC_IRQ_ENTRY_ILLEGAL");
     1126  case RMRC_NOT_IMPLEMENTED:
     1127    return("RMRC_NOT_IMPLEMENTED");
     1128  case RMRC_NOT_INSTALLED:
     1129    return("RMRC_NOT_INSTALLED");
     1130  case RMRC_BAD_DETECTHANDLE:
     1131    return("RMRC_BAD_DETECTHANDLE");
     1132  case RMRC_BAD_RMHANDLE:
     1133    return("RMRC_BAD_RMHANDLE");
     1134  case RMRC_BAD_FLAGS:
     1135    return("RMRC_BAD_FLAGS");
     1136  case RMRC_NO_DETECTED_DATA:
     1137    return("RMRC_NO_DETECTED_DATA");
     1138  default:
     1139    return("RMRC_UNKOWN");
     1140  }
     1141}
  • trunk/src/os2ahci/version.h

    r80 r81  
    66
    77
    8 #define VERSION            106       /* driver version (2 implied decimals) */
     8#define VERSION            107       /* 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.