Deleted Added
full compact
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}