cardbus_cis.c (140198) | cardbus_cis.c (141412) |
---|---|
1/*- 2 * Copyright (c) 2000,2001 Jonathan Chen. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2000,2001 Jonathan Chen. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/dev/cardbus/cardbus_cis.c 140198 2005-01-13 19:12:10Z imp $"); | 28__FBSDID("$FreeBSD: head/sys/dev/cardbus/cardbus_cis.c 141412 2005-02-06 21:03:13Z imp $"); |
29 30/* 31 * CIS Handling for the Cardbus Bus 32 */ 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> --- 74 unchanged lines hidden (view full) --- 111 int rid, struct resource *res); 112static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child, 113 uint32_t *start, int *rid); 114static int decode_tuple(device_t cbdev, device_t child, int tupleid, 115 int len, uint8_t *tupledata, uint32_t start, 116 uint32_t *off, struct tuple_callbacks *callbacks); 117static int cardbus_parse_cis(device_t cbdev, device_t child, 118 struct tuple_callbacks *callbacks); | 29 30/* 31 * CIS Handling for the Cardbus Bus 32 */ 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> --- 74 unchanged lines hidden (view full) --- 111 int rid, struct resource *res); 112static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child, 113 uint32_t *start, int *rid); 114static int decode_tuple(device_t cbdev, device_t child, int tupleid, 115 int len, uint8_t *tupledata, uint32_t start, 116 uint32_t *off, struct tuple_callbacks *callbacks); 117static int cardbus_parse_cis(device_t cbdev, device_t child, 118 struct tuple_callbacks *callbacks); |
119static int barsort(const void *a, const void *b); 120static int cardbus_alloc_resources(device_t cbdev, device_t child); 121static void cardbus_add_map(device_t cbdev, device_t child, int reg); 122static void cardbus_pickup_maps(device_t cbdev, device_t child); | |
123 | 119 |
124 | |
125#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC } 126 127static char *funcnames[] = { 128 "Multi-Functioned", 129 "Memory", 130 "Serial Port", 131 "Parallel Port", 132 "Fixed Disk", --- 142 unchanged lines hidden (view full) --- 275 for (i = 0; i < len; i++) 276 printf("%02x", tupledata[i]); 277 printf("\n"); 278 } 279 if (len < 2) /* too short */ 280 return (0); 281 type = tupledata[0]; /* XXX <32 always? */ 282 switch (dinfo->funcid) { | 120#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC } 121 122static char *funcnames[] = { 123 "Multi-Functioned", 124 "Memory", 125 "Serial Port", 126 "Parallel Port", 127 "Fixed Disk", --- 142 unchanged lines hidden (view full) --- 270 for (i = 0; i < len; i++) 271 printf("%02x", tupledata[i]); 272 printf("\n"); 273 } 274 if (len < 2) /* too short */ 275 return (0); 276 type = tupledata[0]; /* XXX <32 always? */ 277 switch (dinfo->funcid) { |
283 case TPL_FUNC_SERIAL: 284 if (type == TPL_FUNCE_SER_UART) { /* NB: len known > 1 */ 285 dinfo->funce.sio.type = tupledata[1] & 0x1f; 286 } 287 dinfo->fepresent |= 1<<type; 288 break; 289 case TPL_FUNC_LAN: | 278 case PCCARD_FUNCTION_NETWORK: |
290 switch (type) { | 279 switch (type) { |
291 case TPL_FUNCE_LAN_TECH: 292 dinfo->funce.lan.tech = tupledata[1]; /* XXX mask? */ 293 break; 294#if 0 295 case TPL_FUNCE_LAN_SPEED: 296 for (i = 0; i < 3; i++) { 297 if (dinfo->funce.lan.speed[i] == 0) { 298 if (len > 4) { 299 dinfo->funce.lan.speed[i] = 300 ...; 301 } 302 break; 303 } 304 } 305 break; 306#endif 307 case TPL_FUNCE_LAN_MEDIA: 308 for (i = 0; i < 4 && dinfo->funce.lan.media[i]; i++) { 309 if (dinfo->funce.lan.media[i] == 0) { 310 /* NB: len known > 1 */ 311 dinfo->funce.lan.media[i] = 312 tupledata[1]; /*XXX? mask */ 313 break; 314 } 315 } 316 break; 317 case TPL_FUNCE_LAN_NID: | 280 case PCCARD_TPLFE_TYPE_LAN_NID: |
318 if (tupledata[1] > sizeof(dinfo->funce.lan.nid)) { 319 /* ignore, warning? */ 320 return (0); 321 } 322 bcopy(tupledata + 2, dinfo->funce.lan.nid, 323 tupledata[1]); 324 break; | 281 if (tupledata[1] > sizeof(dinfo->funce.lan.nid)) { 282 /* ignore, warning? */ 283 return (0); 284 } 285 bcopy(tupledata + 2, dinfo->funce.lan.nid, 286 tupledata[1]); 287 break; |
325 case TPL_FUNCE_LAN_CONN: 326 dinfo->funce.lan.contype = tupledata[1];/*XXX mask? */ 327 break; | |
328 } 329 dinfo->fepresent |= 1<<type; 330 break; 331 } 332 return (0); 333} 334 335static int --- 390 unchanged lines hidden (view full) --- 726 cardbus_read_tuple_finish(cbdev, child, rid, res); 727 return (expect_linktarget); 728 } 729 } while (tupleid != CISTPL_END); 730 cardbus_read_tuple_finish(cbdev, child, rid, res); 731 return (0); 732} 733 | 288 } 289 dinfo->fepresent |= 1<<type; 290 break; 291 } 292 return (0); 293} 294 295static int --- 390 unchanged lines hidden (view full) --- 686 cardbus_read_tuple_finish(cbdev, child, rid, res); 687 return (expect_linktarget); 688 } 689 } while (tupleid != CISTPL_END); 690 cardbus_read_tuple_finish(cbdev, child, rid, res); 691 return (0); 692} 693 |
734static void 735cardbus_do_res(struct resource_list_entry *rle, device_t child, uint32_t start) 736{ 737 rle->start = start; 738 rle->end = start + rle->count - 1; 739 pci_write_config(child, rle->rid, rle->start, 4); 740} 741 742static int 743barsort(const void *a, const void *b) 744{ 745 return ((*(const struct resource_list_entry * const *)b)->count - 746 (*(const struct resource_list_entry * const *)a)->count); 747} 748 749static int 750cardbus_alloc_resources(device_t cbdev, device_t child) 751{ 752 struct cardbus_devinfo *dinfo = device_get_ivars(child); 753 int count; 754 struct resource_list_entry *rle; 755 struct resource_list_entry **barlist; 756 int tmp; 757 uint32_t mem_psize = 0, mem_nsize = 0, io_size = 0; 758 struct resource *res; 759 uint32_t start,end; 760 int rid, flags; 761 762 count = 0; 763 SLIST_FOREACH(rle, &dinfo->pci.resources, link) { 764 count++; 765 } 766 if (count == 0) 767 return (0); 768 barlist = malloc(sizeof(struct resource_list_entry*) * count, M_DEVBUF, 769 M_WAITOK); 770 count = 0; 771 SLIST_FOREACH(rle, &dinfo->pci.resources, link) { 772 barlist[count] = rle; 773 if (rle->type == SYS_RES_IOPORT) { 774 io_size += rle->count; 775 } else if (rle->type == SYS_RES_MEMORY) { 776 if (dinfo->mprefetchable & BARBIT(rle->rid)) 777 mem_psize += rle->count; 778 else 779 mem_nsize += rle->count; 780 } 781 count++; 782 } 783 784 /* 785 * We want to allocate the largest resource first, so that our 786 * allocated memory is packed. 787 */ 788 qsort(barlist, count, sizeof(struct resource_list_entry*), barsort); 789 790 /* Allocate prefetchable memory */ 791 flags = 0; 792 for (tmp = 0; tmp < count; tmp++) { 793 rle = barlist[tmp]; 794 if (rle->res == NULL && 795 rle->type == SYS_RES_MEMORY && 796 dinfo->mprefetchable & BARBIT(rle->rid)) { 797 flags = rman_make_alignment_flags(rle->count); 798 break; 799 } 800 } 801 if (flags > 0) { /* If any prefetchable memory is requested... */ 802 /* 803 * First we allocate one big space for all resources of this 804 * type. We do this because our parent, pccbb, needs to open 805 * a window to forward all addresses within the window, and 806 * it would be best if nobody else has resources allocated 807 * within the window. 808 * (XXX: Perhaps there might be a better way to do this?) 809 */ 810 rid = 0; 811 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, &rid, 0, 812 (dinfo->mprefetchable & dinfo->mbelow1mb)?0xFFFFF:~0UL, 813 mem_psize, flags); 814 if (res == NULL) { 815 device_printf(cbdev, 816 "Can't get memory for prefetch mem\n"); 817 free(barlist, M_DEVBUF); 818 return (EIO); 819 } 820 start = rman_get_start(res); 821 end = rman_get_end(res); 822 DEVPRINTF((cbdev, "Prefetchable memory at %x-%x\n", start, end)); 823 /* 824 * Now that we know the region is free, release it and hand it 825 * out piece by piece. 826 */ 827 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res); 828 for (tmp = 0; tmp < count; tmp++) { 829 rle = barlist[tmp]; 830 if (rle->type == SYS_RES_MEMORY && 831 dinfo->mprefetchable & BARBIT(rle->rid)) { 832 cardbus_do_res(rle, child, start); 833 start += rle->count; 834 } 835 } 836 } 837 838 /* Allocate non-prefetchable memory */ 839 flags = 0; 840 for (tmp = 0; tmp < count; tmp++) { 841 rle = barlist[tmp]; 842 if (rle->type == SYS_RES_MEMORY && 843 (dinfo->mprefetchable & BARBIT(rle->rid)) == 0) { 844 flags = rman_make_alignment_flags(rle->count); 845 break; 846 } 847 } 848 if (flags > 0) { /* If any non-prefetchable memory is requested... */ 849 /* 850 * First we allocate one big space for all resources of this 851 * type. We do this because our parent, pccbb, needs to open 852 * a window to forward all addresses within the window, and 853 * it would be best if nobody else has resources allocated 854 * within the window. 855 * (XXX: Perhaps there might be a better way to do this?) 856 */ 857 rid = 0; 858 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, &rid, 0, 859 ((~dinfo->mprefetchable) & dinfo->mbelow1mb)?0xFFFFF:~0UL, 860 mem_nsize, flags); 861 if (res == NULL) { 862 device_printf(cbdev, 863 "Can't get memory for non-prefetch mem\n"); 864 free(barlist, M_DEVBUF); 865 return (EIO); 866 } 867 start = rman_get_start(res); 868 end = rman_get_end(res); 869 DEVPRINTF((cbdev, "Non-prefetchable memory at %x-%x\n", 870 start, end)); 871 /* 872 * Now that we know the region is free, release it and hand it 873 * out piece by piece. 874 */ 875 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res); 876 for (tmp = 0; tmp < count; tmp++) { 877 rle = barlist[tmp]; 878 if (rle->type == SYS_RES_MEMORY && 879 (dinfo->mprefetchable & BARBIT(rle->rid)) == 0) { 880 cardbus_do_res(rle, child, start); 881 start += rle->count; 882 } 883 } 884 } 885 886 /* Allocate IO ports */ 887 flags = 0; 888 for (tmp = 0; tmp < count; tmp++) { 889 rle = barlist[tmp]; 890 if (rle->type == SYS_RES_IOPORT) { 891 flags = rman_make_alignment_flags(rle->count); 892 break; 893 } 894 } 895 if (flags > 0) { /* If any IO port is requested... */ 896 /* 897 * First we allocate one big space for all resources of this 898 * type. We do this because our parent, pccbb, needs to open 899 * a window to forward all addresses within the window, and 900 * it would be best if nobody else has resources allocated 901 * within the window. 902 * (XXX: Perhaps there might be a better way to do this?) 903 */ 904 rid = 0; 905 res = bus_alloc_resource(cbdev, SYS_RES_IOPORT, &rid, 0, 906 (dinfo->ibelow1mb)?0xFFFFF:~0UL, io_size, flags); 907 if (res == NULL) { 908 device_printf(cbdev, 909 "Can't get memory for IO ports\n"); 910 free(barlist, M_DEVBUF); 911 return (EIO); 912 } 913 start = rman_get_start(res); 914 end = rman_get_end(res); 915 DEVPRINTF((cbdev, "IO port at %x-%x\n", start, end)); 916 /* 917 * Now that we know the region is free, release it and hand it 918 * out piece by piece. 919 */ 920 bus_release_resource(cbdev, SYS_RES_IOPORT, rid, res); 921 for (tmp = 0; tmp < count; tmp++) { 922 rle = barlist[tmp]; 923 if (rle->type == SYS_RES_IOPORT) { 924 cardbus_do_res(rle, child, start); 925 start += rle->count; 926 } 927 } 928 } 929 930 /* Allocate IRQ */ 931 rid = 0; 932 res = bus_alloc_resource_any(cbdev, SYS_RES_IRQ, &rid, RF_SHAREABLE); 933 if (res == NULL) { 934 device_printf(cbdev, "Can't get memory for irq\n"); 935 free(barlist, M_DEVBUF); 936 return (EIO); 937 } 938 start = rman_get_start(res); 939 end = rman_get_end(res); 940 bus_release_resource(cbdev, SYS_RES_IRQ, rid, res); 941 resource_list_add(&dinfo->pci.resources, SYS_RES_IRQ, rid, start, end, 942 1); 943 dinfo->pci.cfg.intline = rman_get_start(res); 944 pci_write_config(child, PCIR_INTLINE, rman_get_start(res), 1); 945 946 free(barlist, M_DEVBUF); 947 return (0); 948} 949 950/* 951 * Adding a memory/io resource (sans CIS) 952 */ 953 954static void 955cardbus_add_map(device_t cbdev, device_t child, int reg) 956{ 957 struct cardbus_devinfo *dinfo = device_get_ivars(child); 958 struct resource_list_entry *rle; 959 uint32_t size; 960 uint32_t testval; 961 int type; 962 963 SLIST_FOREACH(rle, &dinfo->pci.resources, link) { 964 if (rle->rid == reg) 965 return; 966 } 967 968 if (reg == CARDBUS_ROM_REG) 969 testval = CARDBUS_ROM_ADDRMASK; 970 else 971 testval = ~0; 972 973 pci_write_config(child, reg, testval, 4); 974 testval = pci_read_config(child, reg, 4); 975 976 if (testval == ~0 || testval == 0) 977 return; 978 979 if ((testval & 1) == 0) 980 type = SYS_RES_MEMORY; 981 else 982 type = SYS_RES_IOPORT; 983 984 size = CARDBUS_MAPREG_MEM_SIZE(testval); 985 device_printf(cbdev, "Resource not specified in CIS: id=%x, size=%x\n", 986 reg, size); 987 resource_list_add(&dinfo->pci.resources, type, reg, 0UL, ~0UL, size); 988} 989 990static void 991cardbus_pickup_maps(device_t cbdev, device_t child) 992{ 993 struct cardbus_devinfo *dinfo = device_get_ivars(child); 994 int reg; 995 996 /* 997 * Try to pick up any resources that was not specified in CIS. 998 * Maybe this isn't any longer necessary now that we have fixed 999 * CIS parsing and we should filter things here? XXX 1000 */ 1001 for (reg = 0; reg < dinfo->pci.cfg.nummaps; reg++) 1002 cardbus_add_map(cbdev, child, PCIR_BAR(reg)); 1003} 1004 | |
1005int 1006cardbus_do_cis(device_t cbdev, device_t child) 1007{ 1008 int ret; 1009 struct tuple_callbacks init_callbacks[] = { 1010 MAKETUPLE(LONGLINK_CB, unhandled), 1011 MAKETUPLE(INDIRECT, unhandled), 1012 MAKETUPLE(LONGLINK_MFC, unhandled), --- 7 unchanged lines hidden (view full) --- 1020 MAKETUPLE(FUNCE, funce), 1021 MAKETUPLE(END, end), 1022 MAKETUPLE(GENERIC, generic), 1023 }; 1024 1025 ret = cardbus_parse_cis(cbdev, child, init_callbacks); 1026 if (ret < 0) 1027 return (ret); | 694int 695cardbus_do_cis(device_t cbdev, device_t child) 696{ 697 int ret; 698 struct tuple_callbacks init_callbacks[] = { 699 MAKETUPLE(LONGLINK_CB, unhandled), 700 MAKETUPLE(INDIRECT, unhandled), 701 MAKETUPLE(LONGLINK_MFC, unhandled), --- 7 unchanged lines hidden (view full) --- 709 MAKETUPLE(FUNCE, funce), 710 MAKETUPLE(END, end), 711 MAKETUPLE(GENERIC, generic), 712 }; 713 714 ret = cardbus_parse_cis(cbdev, child, init_callbacks); 715 if (ret < 0) 716 return (ret); |
1028 cardbus_pickup_maps(cbdev, child); 1029 return (cardbus_alloc_resources(cbdev, child)); | 717 return 0; |
1030} | 718} |