- Timestamp:
- Mar 1, 2011, 9:19:08 PM (14 years ago)
- Location:
- trunk/src/os2ahci
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/os2ahci/os2ahci.def
r80 r81 1 1 library os2ahci 2 Description '$@#thi.guten (www.thiguten.de):1.00.20110 228#@OS/2 AHCI Adapter Device Driver'2 Description '$@#thi.guten (www.thiguten.de):1.00.20110301#@OS/2 AHCI Adapter Device Driver' 3 3 protmode 4 4 -
trunk/src/os2ahci/os2ahci.h
r80 r81 315 315 316 316 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 */ 318 318 HRESOURCE rm_irq; /* resource handle for IRQ */ 319 319 … … 323 323 324 324 u32 mmio_phys; /* physical address of MMIO region */ 325 u32 mmio_size; /* size of MMIO region */ 325 326 u8 _far *mmio; /* pointer to this adapter's MMIO region */ 326 327 -
trunk/src/os2ahci/pci.c
r80 r81 26 26 27 27 /* 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)) 32 29 33 30 /****************************************************************************** … … 152 149 static int oemhlp_call (UCHAR subfunction, OH_PARM _far *parm, 153 150 OH_DATA _far *data); 151 static long bar_resource (UCHAR bus, UCHAR dev_func, 152 RESOURCESTRUCT _far *resource, int i); 153 static char *rmerr (APIRET ret); 154 154 155 155 /* ------------------------ global/static variables ------------------------ */ … … 533 533 static void add_pci_device(PCI_ID *pci_id, OH_DATA _far *data) 534 534 { 535 char rc_list_buf[sizeof(AHRESOURCE) + sizeof(HRESOURCE) * 4];535 char rc_list_buf[sizeof(AHRESOURCE) + sizeof(HRESOURCE) * 15]; 536 536 AHRESOURCE _far *rc_list = (AHRESOURCE _far *) rc_list_buf; 537 537 RESOURCESTRUCT resource; … … 548 548 u16 vendor; 549 549 u32 class; 550 u32 mmio_bios = 0;551 u32 mmio_size;552 u32 mmio_rqd;553 550 int irq; 554 551 int pin; … … 666 663 667 664 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; 678 668 } 679 669 rc_list->hResource[rc_list->NumResource++] = ad_info->rm_irq; 680 670 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. 697 675 */ 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; 707 682 } 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; 730 686 } 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 } 734 711 735 712 /**************************************************************************** … … 742 719 ad_info->dev_func = dev_func; 743 720 ad_info->irq = irq; 744 ad_info->mmio_phys = resource.MEMResource.MemBase;745 721 746 722 /* allocate memory for port-specific DMA scratch buffers */ … … 760 736 761 737 /* 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) { 764 740 cprintf("error: couldn't map MMIO address to GDT selector\n"); 765 741 goto add_pci_fail; … … 803 779 ret = RMCreateAdapter(rm_drvh, &ad_info->rm_adh, &adapter, NULL, rc_list); 804 780 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)); 806 782 goto add_pci_fail; 807 783 } … … 816 792 add_pci_fail: 817 793 /* 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 } 820 798 } 821 799 if (ad_info->rm_irq != 0) { 822 800 RMDeallocResource(rm_drvh, ad_info->rm_irq); 823 }824 if (&ad_info->dma_buf_phys != 0) {825 DevHelp_FreePhys(ad_info->dma_buf_phys);826 801 } 827 802 for (i = 0; i < sizeof(gdt) / sizeof(*gdt); i++) { … … 829 804 DevHelp_FreeGDTSelector(gdt[i]); 830 805 } 806 } 807 if (ad_info->dma_buf_phys != 0) { 808 DevHelp_FreePhys(ad_info->dma_buf_phys); 831 809 } 832 810 } … … 960 938 } 961 939 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 */ 962 static 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); 962 1014 } 963 1015 … … 1025 1077 return s_generic; 1026 1078 } 1079 1080 /****************************************************************************** 1081 * Return textual version of a resource manager error 1082 */ 1083 static 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 6 6 7 7 8 #define VERSION 10 6/* driver version (2 implied decimals) */8 #define VERSION 107 /* driver version (2 implied decimals) */ 9 9 10 10 /* BLDLEVEL information (in C source modules added via macro
Note:
See TracChangeset
for help on using the changeset viewer.