1/* $NetBSD: pcmcia.c,v 1.23 2000/07/28 19:17:02 drochner Exp $ */ 2 3/*- 4 * Copyright (c) 1997 Marc Horowitz. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 16 unchanged lines hidden (view full) --- 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> |
33__FBSDID("$FreeBSD: head/sys/dev/pccard/pccard.c 147963 2005-07-13 15:00:59Z imp $"); |
34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/malloc.h> 38#include <sys/module.h> 39#include <sys/kernel.h> 40#include <sys/queue.h> 41#include <sys/sysctl.h> --- 213 unchanged lines hidden (view full) --- 255 * are combination cards, but only one of these units 256 * can be on at a time. 257 */ 258 ivar = malloc(sizeof(struct pccard_ivar), M_DEVBUF, 259 M_WAITOK | M_ZERO); 260 resource_list_init(&ivar->resources); 261 child = device_add_child(dev, NULL, -1); 262 device_set_ivars(child, ivar); |
263 ivar->pf = pf; |
264 pf->dev = child; 265 /* |
266 * XXX We might want to move the next three lines into |
267 * XXX the pccard interface layer. For the moment, this 268 * XXX is OK, but some drivers want to pick the config 269 * XXX entry to use as well as some address tweaks (mostly 270 * XXX due to bugs in decode logic that makes some 271 * XXX addresses illegal or broken). 272 */ 273 pccard_function_init(pf); 274 if (sc->sc_enabled_count == 0) --- 598 unchanged lines hidden (view full) --- 873 pccard_print_resources(rl, "port", SYS_RES_IOPORT, 874 PCCARD_NPORT, "%#lx"); 875 pccard_print_resources(rl, "iomem", SYS_RES_MEMORY, 876 PCCARD_NMEM, "%#lx"); 877 pccard_print_resources(rl, "irq", SYS_RES_IRQ, PCCARD_NIRQ, 878 "%ld"); 879 pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ, 880 "%ld"); |
881 retval += printf(" function %d config %d", devi->pf->number, 882 devi->pf->cfe->number); |
883 } 884 885 retval += bus_print_child_footer(dev, child); 886 887 return (retval); 888} 889 890static int 891pccard_set_resource(device_t dev, device_t child, int type, int rid, |
892 u_long start, u_long count) |
893{ 894 struct pccard_ivar *devi = PCCARD_IVAR(child); 895 struct resource_list *rl = &devi->resources; 896 897 if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY 898 && type != SYS_RES_IRQ && type != SYS_RES_DRQ) 899 return (EINVAL); 900 if (rid < 0) --- 59 unchanged lines hidden (view full) --- 960 return (CARD_SET_MEMORY_OFFSET(device_get_parent(dev), child, rid, 961 offset, deltap)); 962} 963 964static void 965pccard_probe_nomatch(device_t bus, device_t child) 966{ 967 struct pccard_ivar *devi = PCCARD_IVAR(child); |
968 struct pccard_function *pf = devi->pf; |
969 struct pccard_softc *sc = PCCARD_SOFTC(bus); 970 971 device_printf(bus, "<unknown card>"); 972 printf(" (manufacturer=0x%04x, product=0x%04x) at function %d\n", |
973 sc->card.manufacturer, sc->card.product, pf->number); |
974 device_printf(bus, " CIS info: %s, %s, %s\n", sc->card.cis1_info[0], 975 sc->card.cis1_info[1], sc->card.cis1_info[2]); 976 return; 977} 978 979static int 980pccard_child_location_str(device_t bus, device_t child, char *buf, 981 size_t buflen) 982{ 983 struct pccard_ivar *devi = PCCARD_IVAR(child); |
984 struct pccard_function *pf = devi->pf; |
985 |
986 snprintf(buf, buflen, "function=%d", pf->number); |
987 return (0); 988} 989 |
990/* XXX Maybe this should be in subr_bus? */ 991static void 992pccard_safe_quote(char *dst, const char *src, size_t len) 993{ 994 char *walker = dst, *ep = dst + len - 1; 995 996 if (len == 0) 997 return; 998 while (walker < ep) 999 { 1000 if (*src == '"') { 1001 if (ep - walker < 2) 1002 break; 1003 *walker++ = '\\'; 1004 } 1005 *walker++ = *src++; 1006 } 1007 *walker = '\0'; 1008} 1009 |
1010static int 1011pccard_child_pnpinfo_str(device_t bus, device_t child, char *buf, 1012 size_t buflen) 1013{ 1014 struct pccard_ivar *devi = PCCARD_IVAR(child); |
1015 struct pccard_function *pf = devi->pf; |
1016 struct pccard_softc *sc = PCCARD_SOFTC(bus); |
1017 char cis0[128], cis1[128]; |
1018 |
1019 pccard_safe_quote(cis0, sc->card.cis1_info[0], sizeof(cis0)); 1020 pccard_safe_quote(cis1, sc->card.cis1_info[1], sizeof(cis1)); |
1021 snprintf(buf, buflen, "manufacturer=0x%04x product=0x%04x " 1022 "cisvendor=\"%s\" cisproduct=\"%s\" function_type=%d", |
1023 sc->card.manufacturer, sc->card.product, cis0, cis1, pf->function); |
1024 return (0); 1025} 1026 1027static int 1028pccard_read_ivar(device_t bus, device_t child, int which, u_char *result) 1029{ 1030 struct pccard_ivar *devi = PCCARD_IVAR(child); |
1031 struct pccard_function *pf = devi->pf; |
1032 struct pccard_softc *sc = PCCARD_SOFTC(bus); 1033 |
1034 if (!pf) 1035 panic("No pccard function pointer"); |
1036 switch (which) { 1037 default: |
1038 return (EINVAL); |
1039 case PCCARD_IVAR_ETHADDR: |
1040 bcopy(pf->pf_funce_lan_nid, result, ETHER_ADDR_LEN); |
1041 break; 1042 case PCCARD_IVAR_VENDOR: |
1043 *(uint32_t *)result = sc->card.manufacturer; |
1044 break; 1045 case PCCARD_IVAR_PRODUCT: |
1046 *(uint32_t *)result = sc->card.product; |
1047 break; 1048 case PCCARD_IVAR_PRODEXT: |
1049 *(uint16_t *)result = sc->card.prodext; |
1050 break; 1051 case PCCARD_IVAR_FUNCTION: |
1052 *(uint32_t *)result = pf->function; |
1053 break; 1054 case PCCARD_IVAR_FUNCTION_NUMBER: |
1055 *(uint32_t *)result = pf->number; |
1056 break; 1057 case PCCARD_IVAR_VENDOR_STR: |
1058 *(const char **)result = sc->card.cis1_info[0]; |
1059 break; 1060 case PCCARD_IVAR_PRODUCT_STR: |
1061 *(const char **)result = sc->card.cis1_info[1]; |
1062 break; 1063 case PCCARD_IVAR_CIS3_STR: |
1064 *(const char **)result = sc->card.cis1_info[2]; |
1065 break; 1066 case PCCARD_IVAR_CIS4_STR: |
1067 *(const char **)result = sc->card.cis1_info[3]; |
1068 break; 1069 } 1070 return (0); 1071} 1072 1073static void 1074pccard_driver_added(device_t dev, driver_t *driver) 1075{ --- 108 unchanged lines hidden (view full) --- 1184 rman_set_device(rle->res, dev); 1185 return (0); 1186} 1187 1188static void 1189pccard_child_detached(device_t parent, device_t dev) 1190{ 1191 struct pccard_ivar *ivar = PCCARD_IVAR(dev); |
1192 struct pccard_function *pf = ivar->pf; |
1193 1194 pccard_function_disable(pf); 1195} 1196 1197static void 1198pccard_intr(void *arg) 1199{ 1200 struct pccard_function *pf = (struct pccard_function*) arg; --- 29 unchanged lines hidden (view full) --- 1230} 1231 1232static int 1233pccard_setup_intr(device_t dev, device_t child, struct resource *irq, 1234 int flags, driver_intr_t *intr, void *arg, void **cookiep) 1235{ 1236 struct pccard_softc *sc = PCCARD_SOFTC(dev); 1237 struct pccard_ivar *ivar = PCCARD_IVAR(child); |
1238 struct pccard_function *pf = ivar->pf; |
1239 int err; 1240 |
1241 if (pf->intr_handler != NULL) |
1242 panic("Only one interrupt handler per function allowed"); 1243 err = bus_generic_setup_intr(dev, child, irq, flags, pccard_intr, |
1244 pf, cookiep); |
1245 if (err != 0) 1246 return (err); |
1247 pf->intr_handler = intr; 1248 pf->intr_handler_arg = arg; 1249 pf->intr_handler_cookie = *cookiep; |
1250 if (pccard_mfc(sc)) { |
1251 pccard_ccr_write(pf, PCCARD_CCR_OPTION, 1252 pccard_ccr_read(pf, PCCARD_CCR_OPTION) | |
1253 PCCARD_CCR_OPTION_IREQ_ENABLE); 1254 } 1255 return (0); 1256} 1257 1258static int 1259pccard_teardown_intr(device_t dev, device_t child, struct resource *r, 1260 void *cookie) 1261{ 1262 struct pccard_softc *sc = PCCARD_SOFTC(dev); 1263 struct pccard_ivar *ivar = PCCARD_IVAR(child); |
1264 struct pccard_function *pf = ivar->pf; |
1265 int ret; 1266 1267 if (pccard_mfc(sc)) { |
1268 pccard_ccr_write(pf, PCCARD_CCR_OPTION, 1269 pccard_ccr_read(pf, PCCARD_CCR_OPTION) & |
1270 ~PCCARD_CCR_OPTION_IREQ_ENABLE); 1271 } 1272 ret = bus_generic_teardown_intr(dev, child, r, cookie); 1273 if (ret == 0) { |
1274 pf->intr_handler = NULL; 1275 pf->intr_handler_arg = NULL; 1276 pf->intr_handler_cookie = NULL; |
1277 } 1278 1279 return (ret); 1280} 1281 1282static int 1283pccard_activate_resource(device_t brdev, device_t child, int type, int rid, 1284 struct resource *r) 1285{ 1286 struct pccard_ivar *ivar = PCCARD_IVAR(child); |
1287 struct pccard_function *pf = ivar->pf; |
1288 1289 switch(type) { 1290 case SYS_RES_IOPORT: 1291 /* 1292 * We need to adjust IOBASE[01] and IOSIZE if we're an MFC 1293 * card. 1294 */ 1295 if (pccard_mfc(pf->sc)) --- 69 unchanged lines hidden --- |