1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * PCMCIA NEXUS 30 * The PCMCIA module is a generalized interface for 31 * implementing PCMCIA nexus drivers. It preserves 32 * the logical socket name space while allowing multiple 33 * instances of the hardware to be properly represented 34 * in the device tree. 35 * 36 * The nexus also exports events to an event manager 37 * driver if it has registered. 38 */ 39 40 #include <sys/types.h> 41 #include <sys/systm.h> 42 #include <sys/user.h> 43 #include <sys/buf.h> 44 #include <sys/file.h> 45 #include <sys/uio.h> 46 #include <sys/conf.h> 47 #include <sys/stat.h> 48 #include <sys/autoconf.h> 49 #include <sys/vtoc.h> 50 #include <sys/dkio.h> 51 #include <sys/ddi.h> 52 #include <sys/debug.h> 53 #include <sys/sunddi.h> 54 #include <sys/sunndi.h> 55 #include <sys/cred.h> 56 #include <sys/kstat.h> 57 #include <sys/kmem.h> 58 #include <sys/modctl.h> 59 #include <sys/kobj.h> 60 #include <sys/callb.h> 61 #include <sys/param.h> 62 #include <sys/thread.h> 63 #include <sys/proc.h> 64 65 #include <sys/pctypes.h> 66 #include <sys/pcmcia.h> 67 #include <sys/sservice.h> 68 #include <pcmcia/sys/cs_types.h> 69 #include <pcmcia/sys/cis.h> 70 #include <pcmcia/sys/cis_handlers.h> 71 #include <pcmcia/sys/cs.h> 72 #include <pcmcia/sys/cs_priv.h> 73 74 #ifdef sparc 75 #include <sys/ddi_subrdefs.h> 76 77 #elif defined(__x86) || defined(__amd64) 78 #include <sys/mach_intr.h> 79 #endif 80 81 #undef SocketServices 82 83 /* some bus specific stuff */ 84 85 /* need PCI regspec size for worst case at present */ 86 #include <sys/pci.h> 87 88 typedef struct pcmcia_logical_socket { 89 int ls_socket; /* adapter's socket number */ 90 uint32_t ls_flags; 91 struct pcmcia_adapter *ls_adapter; 92 pcmcia_if_t *ls_if; 93 dev_info_t *ls_sockdrv; 94 dev_info_t *ls_dip[PCMCIA_MAX_FUNCTIONS]; 95 dev_info_t *ls_mfintr_dip; 96 int ls_functions; 97 uint32_t ls_cs_events; 98 uint32_t ls_intr_pri; 99 uint32_t ls_intr_vec; 100 int ls_intrrefs; 101 struct intrspec ls_intrspec; /* MFC intrspec */ 102 inthandler_t *ls_inthandlers; /* for multifunction cards */ 103 ddi_iblock_cookie_t ls_iblk; 104 ddi_idevice_cookie_t ls_idev; 105 kmutex_t ls_ilock; 106 int ls_error; /* error for CS return */ 107 } pcmcia_logical_socket_t; 108 109 /* 110 * entry points used by the true nexus 111 */ 112 int pcmcia_detach(dev_info_t *, ddi_detach_cmd_t); 113 int pcmcia_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, void *); 114 int pcmcia_prop_op(dev_t, dev_info_t *, dev_info_t *, ddi_prop_op_t, 115 int, char *, caddr_t, int *); 116 void pcmcia_set_assigned(dev_info_t *, int, ra_return_t *); 117 int pcmcia_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 118 ddi_intr_handle_impl_t *hdlp, void *result); 119 120 /* 121 * prototypes used internally by the nexus and sometimes Card Services 122 */ 123 int SocketServices(int function, ...); 124 125 126 void *CISParser(int function, ...); 127 extern void *(*cis_parser)(int, ...); 128 129 struct regspec *pcmcia_cons_regspec(dev_info_t *, int, uchar_t *, 130 ra_return_t *); 131 132 static int (*pcmcia_card_services)(int, ...) = NULL; 133 134 /* 135 * variables used in the logical/physical mappings 136 * that the nexus common code maintains. 137 */ 138 struct pcmcia_adapter *pcmcia_adapters[PCMCIA_MAX_ADAPTERS]; 139 int pcmcia_num_adapters; 140 pcmcia_logical_socket_t *pcmcia_sockets[PCMCIA_MAX_SOCKETS]; 141 int pcmcia_num_sockets; 142 pcmcia_logical_window_t *pcmcia_windows[PCMCIA_MAX_WINDOWS]; 143 int pcmcia_num_windows; 144 struct power_entry pcmcia_power_table[PCMCIA_MAX_POWER]; 145 int pcmcia_num_power; 146 147 struct pcmcia_mif *pcmcia_mif_handlers = NULL; 148 pcm_dev_node_t *pcmcia_devnodes = NULL; 149 150 kmutex_t pcmcia_global_lock; 151 kcondvar_t pcmcia_condvar; 152 kmutex_t pcmcia_enum_lock; 153 154 /* 155 * Mapping of the device "type" to names acceptable to 156 * the DDI 157 */ 158 static char *pcmcia_dev_type[] = { 159 "multifunction", 160 "byte", 161 "serial", 162 "parallel", 163 "block", 164 "display", 165 "network", 166 "block", 167 "byte" 168 }; 169 170 char *pcmcia_default_pm_mode = "parental-suspend-resume"; 171 172 /* 173 * generic names from the approved list: 174 * disk tape pci sbus scsi token-ring isa keyboard display mouse 175 * audio ethernet timer memory parallel serial rtc nvram scanner 176 * floppy(controller) fddi isdn atm ide pccard video-in video-out 177 * in some cases there will need to be device class dependent names. 178 * network -> ethernet, token-ring, etc. 179 * this list is a first guess and is used when all else fails. 180 */ 181 182 char *pcmcia_generic_names[] = { 183 "multifunction", 184 "memory", 185 "serial", 186 "parallel", 187 "disk", 188 "video", /* no spec for video-out yet */ 189 "network", 190 "aims", 191 "scsi", 192 "security" 193 }; 194 195 #define PCM_GENNAME_SIZE (sizeof (pcmcia_generic_names) / \ 196 sizeof (char *)) 197 #define PCMCIA_MAP_IO 0x0 198 #define PCMCIA_MAP_MEM 0x1 199 #define PPB_SUBTRACTIVE ((PCI_CLASS_BRIDGE << 16) | (PCI_BRIDGE_PCI << 8) | \ 200 (PCI_BRIDGE_PCI_IF_SUBDECODE)) 201 202 /* 203 * The following should be 2^^n - 1 204 */ 205 #define PCMCIA_SOCKET_BITS 0x7f 206 207 #ifdef PCMCIA_DEBUG 208 int pcmcia_debug = 0x0; 209 static void pcmcia_dump_minors(dev_info_t *); 210 #endif 211 212 static f_tt *pcmcia_cs_event = NULL; 213 int pcmcia_timer_id; 214 dev_info_t *pcmcia_dip; 215 /* 216 * XXX - See comments in cs.c 217 */ 218 static f_tt *pcmcia_cis_parser = NULL; 219 220 extern struct pc_socket_services pc_socket_services; 221 222 /* some function declarations */ 223 static int pcm_adapter_callback(dev_info_t *, int, int, int); 224 extern void pcmcia_init_adapter(anp_t *, dev_info_t *); 225 extern void pcmcia_find_cards(anp_t *); 226 extern void pcmcia_merge_power(struct power_entry *); 227 extern void pcmcia_do_resume(int, pcmcia_logical_socket_t *); 228 extern void pcmcia_resume(int, pcmcia_logical_socket_t *); 229 extern void pcmcia_do_suspend(int, pcmcia_logical_socket_t *); 230 extern void pcm_event_manager(int, int, void *); 231 static void pcmcia_create_dev_info(int); 232 static int pcmcia_create_device(ss_make_device_node_t *); 233 static void pcmcia_init_devinfo(dev_info_t *, struct pcm_device_info *); 234 void pcmcia_fix_string(char *str); 235 dev_info_t *pcmcia_number_socket(dev_info_t *, int); 236 static int pcmcia_merge_conf(dev_info_t *); 237 static uint32_t pcmcia_mfc_intr(caddr_t, caddr_t); 238 void pcmcia_free_resources(dev_info_t *); 239 static void pcmcia_ppd_free(struct pcmcia_parent_private *ppd); 240 int pcmcia_get_intr(dev_info_t *, int); 241 int pcmcia_return_intr(dev_info_t *, int); 242 int pcmcia_ra_alloc(dev_info_t *, ndi_ra_request_t *, ra_return_t *, char *, 243 dev_info_t **); 244 int pcmcia_ra_free(dev_info_t *, ra_return_t *, char *); 245 246 extern int cs_init(void); 247 extern int cs_deinit(void); 248 extern void cisp_init(void); 249 extern void cis_deinit(void); 250 251 /* 252 * non-DDI compliant functions are listed here 253 * some will be declared while others that have 254 * entries in .h files. All will be commented on. 255 * 256 * with declarations: 257 * ddi_add_child 258 * ddi_binding_name 259 * ddi_bus_prop_op 260 * ddi_ctlops 261 * ddi_find_devinfo 262 * ddi_get_name_addr 263 * ddi_get_parent_data 264 * ddi_hold_installed_driver 265 * ddi_name_to_major 266 * ddi_node_name 267 * ddi_pathname 268 * ddi_rele_driver 269 * ddi_set_name_addr 270 * ddi_set_parent_data 271 * ddi_unorphan_devs 272 * i_ddi_bind_node_to_driver 273 * i_ddi_bind_node_to_driver 274 * i_ddi_bus_map 275 * i_ddi_map_fault 276 * i_ddi_mem_alloc 277 * i_ddi_mem_alloc 278 * i_ddi_mem_free 279 * i_ddi_mem_free 280 * modload 281 * modunload 282 */ 283 284 extern void ddi_unorphan_devs(major_t); 285 286 /* Card&Socket Services entry points */ 287 static int GetCookiesAndDip(sservice_t *); 288 static int SSGetAdapter(get_adapter_t *); 289 static int SSGetPage(get_page_t *); 290 static int SSGetSocket(get_socket_t *); 291 static int SSGetStatus(get_ss_status_t *); 292 static int SSGetWindow(get_window_t *); 293 static int SSInquireAdapter(inquire_adapter_t *); 294 static int SSInquireSocket(inquire_socket_t *); 295 static int SSInquireWindow(inquire_window_t *); 296 static int SSResetSocket(int, int); 297 static int SSSetPage(set_page_t *); 298 static int SSSetSocket(set_socket_t *); 299 static int SSSetWindow(set_window_t *); 300 static int SSSetIRQHandler(set_irq_handler_t *); 301 static int SSClearIRQHandler(clear_irq_handler_t *); 302 303 static struct modldrv modlmisc = { 304 &mod_miscops, /* Type of module. This one is a driver */ 305 "PCMCIA Nexus Support %I%", /* Name of the module. */ 306 }; 307 308 static struct modlinkage modlinkage = { 309 MODREV_1, (void *)&modlmisc, NULL 310 }; 311 312 int 313 _init() 314 { 315 int ret; 316 317 cisp_init(); 318 319 if (cs_init() != CS_SUCCESS) { 320 if (cs_deinit() != CS_SUCCESS) 321 cmn_err(CE_CONT, "pcmcia: _init cs_deinit error\n"); 322 return (-1); 323 } 324 325 mutex_init(&pcmcia_global_lock, NULL, MUTEX_DEFAULT, NULL); 326 cv_init(&pcmcia_condvar, NULL, CV_DRIVER, NULL); 327 mutex_init(&pcmcia_enum_lock, NULL, MUTEX_DEFAULT, NULL); 328 329 if ((ret = mod_install(&modlinkage)) != 0) { 330 mutex_destroy(&pcmcia_global_lock); 331 cv_destroy(&pcmcia_condvar); 332 mutex_destroy(&pcmcia_enum_lock); 333 } 334 return (ret); 335 } 336 337 int 338 _fini() 339 { 340 int ret; 341 342 if ((ret = mod_remove(&modlinkage)) == 0) { 343 mutex_destroy(&pcmcia_global_lock); 344 cv_destroy(&pcmcia_condvar); 345 mutex_destroy(&pcmcia_enum_lock); 346 cis_deinit(); 347 if (cs_deinit() != CS_SUCCESS) { 348 cmn_err(CE_CONT, "pcmcia: _fini cs_deinit error\n"); 349 } 350 } 351 return (ret); 352 } 353 354 int 355 _info(struct modinfo *modinfop) 356 { 357 return (mod_info(&modlinkage, modinfop)); 358 } 359 360 extern pri_t minclsyspri; 361 362 /* 363 * pcmcia_attach() 364 * the attach routine must make sure that everything needed is present 365 * including real hardware. The sequence of events is: 366 * attempt to load all adapter drivers 367 * attempt to load Card Services (which _depends_on pcmcia) 368 * initialize logical sockets 369 * report the nexus exists 370 */ 371 372 int 373 pcmcia_attach(dev_info_t *dip, anp_t *adapter) 374 { 375 int count, done, i; 376 377 #if defined(PCMCIA_DEBUG) 378 if (pcmcia_debug) { 379 cmn_err(CE_CONT, "pcmcia_attach: dip=0x%p adapter=0x%p\n", 380 (void *)dip, (void *)adapter); 381 } 382 #endif 383 384 pcmcia_dip = dip; 385 386 mutex_enter(&pcmcia_enum_lock); 387 mutex_enter(&pcmcia_global_lock); 388 if (pcmcia_num_adapters == 0) { 389 pcmcia_cis_parser = (f_tt *)CISParser; 390 cis_parser = (void *(*)(int, ...)) CISParser; 391 pcmcia_cs_event = (f_tt *)cs_event; 392 cs_socket_services = SocketServices; 393 /* tell CS we are up with basic init level */ 394 (void) cs_event(PCE_SS_INIT_STATE, PCE_SS_STATE_INIT, 0); 395 } 396 397 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, 398 PCM_DEVICETYPE, "pccard"); 399 400 ddi_report_dev(dip); /* directory/device naming */ 401 402 /* 403 * now setup any power management stuff necessary. 404 * we do it here in order to ensure that all PC Card nexi 405 * implement it. 406 */ 407 408 if (pm_create_components(dip, 1) != DDI_SUCCESS) { 409 cmn_err(CE_WARN, "%s: not power managed\n", 410 ddi_get_name_addr(dip)); 411 } else { 412 pm_set_normal_power(dip, 0, 1); 413 } 414 415 /* 416 * setup the info necessary for Card Services/SocketServices 417 * and notify CS when ready. 418 */ 419 420 pcmcia_free_resources(dip); 421 pcmcia_init_adapter(adapter, dip); 422 /* exit mutex so CS can run for any cards found */ 423 mutex_exit(&pcmcia_global_lock); 424 425 /* 426 * make sure the devices are identified before 427 * returning. We do this by checking each socket to see if 428 * a card is present. If there is one, and there isn't a dip, 429 * we can't be done. We scan the list of sockets doing the 430 * check. if we aren't done, wait for a condition variable to 431 * wakeup. 432 * Because we can miss a wakeup and because things can 433 * take time, we do eventually give up and have a timeout. 434 */ 435 436 for (count = 0, done = 0; 437 done == 0 && count < max(pcmcia_num_sockets, 16); 438 count++) { 439 done = 1; 440 /* block CS while checking so we don't miss anything */ 441 mutex_enter(&pcmcia_global_lock); 442 for (i = 0; i < pcmcia_num_sockets; i++) { 443 get_ss_status_t status; 444 if (pcmcia_sockets[i] == NULL) 445 continue; 446 bzero(&status, sizeof (status)); 447 status.socket = i; 448 if (SSGetStatus(&status) == SUCCESS) { 449 if (status.CardState & SBM_CD && 450 pcmcia_sockets[i]->ls_dip[0] == NULL) { 451 done = 0; 452 } 453 } 454 } 455 /* only wait if we aren't done with this set */ 456 if (!done) { 457 mutex_exit(&pcmcia_global_lock); 458 delay(10); /* give up CPU for a time */ 459 mutex_enter(&pcmcia_global_lock); 460 } 461 mutex_exit(&pcmcia_global_lock); 462 } 463 464 mutex_exit(&pcmcia_enum_lock); 465 return (DDI_SUCCESS); 466 } 467 468 /* 469 * pcmcia_detach 470 * unload everything and then detach the nexus 471 */ 472 /* ARGSUSED */ 473 int 474 pcmcia_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 475 { 476 switch (cmd) { 477 case DDI_DETACH: 478 pm_destroy_components(dip); 479 return (DDI_SUCCESS); 480 481 /* 482 * resume from a checkpoint 483 * We don't do anything special here since the adapter 484 * driver will generate resume events that we intercept 485 * and convert to insert events. 486 */ 487 case DDI_SUSPEND: 488 case DDI_PM_SUSPEND: 489 return (DDI_SUCCESS); 490 491 default: 492 return (DDI_FAILURE); 493 } 494 } 495 496 /* 497 * card_services_error() 498 * used to make 2.4/2.5 drivers get an error when 499 * they try to initialize. 500 */ 501 static int 502 card_services_error() 503 { 504 return (CS_BAD_VERSION); 505 } 506 static int (*cs_error_ptr)() = card_services_error; 507 508 /* 509 * pcmcia_ctlops 510 * handle the nexus control operations for the cases where 511 * a PC Card driver gets called and we need to modify the 512 * devinfo structure or otherwise do bus specific operations 513 */ 514 int 515 pcmcia_ctlops(dev_info_t *dip, dev_info_t *rdip, 516 ddi_ctl_enum_t ctlop, void *arg, void *result) 517 { 518 int e; 519 char name[64]; 520 struct pcmcia_parent_private *ppd; 521 power_req_t *pm; 522 523 #if defined(PCMCIA_DEBUG) 524 if (pcmcia_debug) { 525 cmn_err(CE_CONT, "pcmcia_ctlops(%p, %p, %d, %p, %p)\n", 526 (void *)dip, (void *)rdip, ctlop, (void *)arg, 527 (void *)result); 528 if (rdip != NULL && ddi_get_name(rdip) != NULL) 529 cmn_err(CE_CONT, "\t[%s]\n", ddi_get_name(rdip)); 530 } 531 #endif 532 533 switch (ctlop) { 534 case DDI_CTLOPS_REPORTDEV: 535 if (rdip == (dev_info_t *)0) 536 return (DDI_FAILURE); 537 538 if (strcmp("pcs", ddi_node_name(rdip)) == 0) 539 cmn_err(CE_CONT, "?PCCard socket %d at %s@%s\n", 540 ddi_get_instance(rdip), 541 ddi_driver_name(dip), ddi_get_name_addr(dip)); 542 else 543 cmn_err(CE_CONT, "?%s%d at %s@%s in socket %d\n", 544 ddi_driver_name(rdip), 545 ddi_get_instance(rdip), 546 ddi_driver_name(dip), 547 ddi_get_name_addr(dip), 548 CS_GET_SOCKET_NUMBER( 549 ddi_getprop(DDI_DEV_T_NONE, rdip, 550 DDI_PROP_DONTPASS, 551 PCM_DEV_SOCKET, -1))); 552 553 return (DDI_SUCCESS); 554 555 case DDI_CTLOPS_INITCHILD: 556 /* 557 * we get control here before the child is called. 558 * we can change things if necessary. This is where 559 * the CardServices hook gets planted. 560 */ 561 #if defined(PCMCIA_DEBUG) 562 if (pcmcia_debug) { 563 cmn_err(CE_CONT, "pcmcia: init child: %s(%d) @%p\n", 564 ddi_node_name(arg), ddi_get_instance(arg), 565 (void *)arg); 566 if (DEVI(arg)->devi_binding_name != NULL) 567 cmn_err(CE_CONT, "\tbinding_name=%s\n", 568 DEVI(arg)->devi_binding_name); 569 if (DEVI(arg)->devi_node_name != NULL) 570 cmn_err(CE_CONT, "\tnode_name=%s\n", 571 DEVI(arg)->devi_node_name); 572 } 573 #endif 574 575 ppd = (struct pcmcia_parent_private *) 576 ddi_get_parent_data((dev_info_t *)arg); 577 if (ppd == NULL) 578 return (DDI_FAILURE); 579 580 if (strcmp("pcs", ddi_node_name((dev_info_t *)arg)) == 0) { 581 if (ppd == NULL) 582 return (DDI_FAILURE); 583 (void) sprintf(name, "%x", 584 (int)ppd->ppd_reg[0].phys_hi); 585 ddi_set_name_addr((dev_info_t *)arg, name); 586 return (DDI_SUCCESS); 587 } 588 589 /* 590 * We don't want driver.conf files that stay in 591 * pseudo device form. It is acceptable to have 592 * .conf files add properties only. 593 */ 594 if (ndi_dev_is_persistent_node((dev_info_t *)arg) == 0) { 595 (void) pcmcia_merge_conf((dev_info_t *)arg); 596 cmn_err(CE_WARN, "%s%d: %s.conf invalid", 597 ddi_get_name((dev_info_t *)arg), 598 ddi_get_instance((dev_info_t *)arg), 599 ddi_get_name((dev_info_t *)arg)); 600 return (DDI_FAILURE); 601 } 602 603 604 #if defined(PCMCIA_DEBUG) 605 if (pcmcia_debug && ppd != NULL) { 606 cmn_err(CE_CONT, "\tnreg=%x, intr=%x, socket=%x," 607 " function=%x, active=%x, flags=%x\n", 608 ppd->ppd_nreg, ppd->ppd_intr, 609 ppd->ppd_socket, ppd->ppd_function, 610 ppd->ppd_active, ppd->ppd_flags); 611 } 612 #endif 613 614 /* 615 * make sure names are relative to socket number 616 */ 617 if (ppd->ppd_function > 0) { 618 int sock; 619 int func; 620 sock = ppd->ppd_socket; 621 func = ppd->ppd_function; 622 (void) sprintf(name, "%x,%x", sock, func); 623 } else { 624 (void) sprintf(name, "%x", ppd->ppd_socket); 625 } 626 ddi_set_name_addr((dev_info_t *)arg, name); 627 628 #if defined(PCMCIA_DEBUG) 629 if (pcmcia_debug) 630 cmn_err(CE_CONT, "pcmcia: system init done for %s [%s] " 631 "nodeid: %x @%s\n", 632 ddi_get_name(arg), ddi_get_name_addr(arg), 633 DEVI(arg)->devi_nodeid, name); 634 if (pcmcia_debug > 1) 635 pcmcia_dump_minors((dev_info_t *)arg); 636 #endif 637 638 return (DDI_SUCCESS); 639 640 case DDI_CTLOPS_UNINITCHILD: 641 642 #if defined(PCMCIA_DEBUG) 643 if (pcmcia_debug) { 644 cmn_err(CE_CONT, "pcmcia: uninit child: %s(%d) @%p\n", 645 ddi_node_name(arg), ddi_get_instance(arg), 646 (void *)arg); 647 if (DEVI(arg)->devi_binding_name != NULL) 648 cmn_err(CE_CONT, "\tbinding_name=%s\n", 649 DEVI(arg)->devi_binding_name); 650 if (DEVI(arg)->devi_node_name != NULL) 651 cmn_err(CE_CONT, "\tnode_name=%s\n", 652 DEVI(arg)->devi_node_name); 653 } 654 #endif 655 656 ddi_set_name_addr((dev_info_t *)arg, NULL); 657 ddi_remove_minor_node((dev_info_t *)arg, NULL); 658 return (DDI_SUCCESS); 659 660 case DDI_CTLOPS_SLAVEONLY: 661 /* PCMCIA devices can't ever be busmaster until CardBus */ 662 ppd = (struct pcmcia_parent_private *) 663 ddi_get_parent_data(rdip); 664 if (ppd != NULL && ppd->ppd_flags & PPD_CB_BUSMASTER) 665 return (DDI_FAILURE); /* at most */ 666 return (DDI_SUCCESS); 667 668 case DDI_CTLOPS_SIDDEV: 669 /* in general this is true. */ 670 return (DDI_SUCCESS); 671 672 case DDI_CTLOPS_NREGS: 673 ppd = (struct pcmcia_parent_private *) 674 ddi_get_parent_data(rdip); 675 if (ppd != NULL) 676 *((uint32_t *)result) = (ppd->ppd_nreg); 677 else 678 *((uint32_t *)result) = 0; 679 return (DDI_SUCCESS); 680 681 case DDI_CTLOPS_REGSIZE: 682 ppd = (struct pcmcia_parent_private *) 683 ddi_get_parent_data(rdip); 684 if (ppd != NULL && ppd->ppd_nreg > 0) 685 *((off_t *)result) = sizeof (struct pcm_regs); 686 else 687 *((off_t *)result) = 0; 688 return (DDI_SUCCESS); 689 690 case DDI_CTLOPS_POWER: 691 ppd = (struct pcmcia_parent_private *) 692 ddi_get_parent_data(rdip); 693 694 if (ppd == NULL) 695 return (DDI_FAILURE); 696 /* 697 * if this is not present, don't bother (claim success) 698 * since it is already in the right state. Don't 699 * do any resume either since the card insertion will 700 * happen independently. 701 */ 702 if (!ppd->ppd_active) 703 return (DDI_SUCCESS); 704 for (e = 0; e < pcmcia_num_adapters; e++) 705 if (pcmcia_adapters[e] == 706 pcmcia_sockets[ppd->ppd_socket]->ls_adapter) 707 break; 708 if (e == pcmcia_num_adapters) 709 return (DDI_FAILURE); 710 pm = (power_req_t *)arg; 711 #if defined(PCMCIA_DEBUG) 712 if (pcmcia_debug) { 713 cmn_err(CE_WARN, "power: %d: %p, %d, %d [%s]\n", 714 pm->request_type, 715 (void *)pm->req.set_power_req.who, 716 pm->req.set_power_req.cmpt, 717 pm->req.set_power_req.level, 718 ddi_get_name_addr(rdip)); 719 } 720 #endif 721 e = ppd->ppd_socket; 722 switch (pm->request_type) { 723 case PMR_SUSPEND: 724 if (!(pcmcia_sockets[e]->ls_flags & 725 PCS_SUSPENDED)) { 726 pcmcia_do_suspend(ppd->ppd_socket, 727 pcmcia_sockets[e]); 728 } 729 ppd->ppd_flags |= PPD_SUSPENDED; 730 return (DDI_SUCCESS); 731 case PMR_RESUME: 732 /* for now, we just succeed since the rest is done */ 733 return (DDI_SUCCESS); 734 case PMR_SET_POWER: 735 /* 736 * not sure how to handle power control 737 * for now, we let the child handle it itself 738 */ 739 (void) pcmcia_power(pm->req.set_power_req.who, 740 pm->req.set_power_req.cmpt, 741 pm->req.set_power_req.level); 742 break; 743 default: 744 break; 745 } 746 return (DDI_FAILURE); 747 /* These CTLOPS will need to be implemented for new form */ 748 /* let CardServices know about this */ 749 750 default: 751 /* if we don't understand, pass up the tree */ 752 /* most things default to general ops */ 753 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 754 } 755 } 756 757 struct pcmcia_props { 758 char *name; 759 int len; 760 int prop; 761 } pcmcia_internal_props[] = { 762 { PCM_DEV_ACTIVE, 0, PCMCIA_PROP_ACTIVE }, 763 { PCM_DEV_R2TYPE, 0, PCMCIA_PROP_R2TYPE }, 764 { PCM_DEV_CARDBUS, 0, PCMCIA_PROP_CARDBUS }, 765 { CS_PROP, sizeof (void *), PCMCIA_PROP_OLDCS }, 766 { "reg", 0, PCMCIA_PROP_REG }, 767 { "interrupts", sizeof (int), PCMCIA_PROP_INTR }, 768 { "pm-hardware-state", 0, PCMCIA_PROP_DEFAULT_PM }, 769 }; 770 771 /* 772 * pcmcia_prop_decode(name) 773 * decode the name and determine if this is a property 774 * we construct on the fly, one we have on the prop list 775 * or one that requires calling the CIS code. 776 */ 777 static int 778 pcmcia_prop_decode(char *name) 779 { 780 int i; 781 if (strncmp(name, "cistpl_", 7) == 0) 782 return (PCMCIA_PROP_CIS); 783 784 for (i = 0; i < (sizeof (pcmcia_internal_props) / 785 sizeof (struct pcmcia_props)); i++) { 786 if (strcmp(name, pcmcia_internal_props[i].name) == 0) 787 return (i); 788 } 789 790 return (PCMCIA_PROP_UNKNOWN); 791 } 792 793 /* 794 * pcmcia_prop_op() 795 * we don't have properties in PROM per se so look for them 796 * only in the devinfo node. Future may allow us to find 797 * certain CIS tuples via this interface if a user asks for 798 * a property of the form "cistpl-<tuplename>" but not yet. 799 * 800 * The addition of 1275 properties adds to the necessity. 801 */ 802 int 803 pcmcia_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip, 804 ddi_prop_op_t prop_op, int mod_flags, 805 char *name, caddr_t valuep, int *lengthp) 806 { 807 int len, proplen, which, flags; 808 caddr_t buff, propptr; 809 struct pcmcia_parent_private *ppd; 810 811 len = *lengthp; 812 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(ch_dip); 813 814 switch (which = pcmcia_prop_decode(name)) { 815 default: 816 if (ppd == NULL) 817 return (DDI_PROP_NOT_FOUND); 818 819 /* note that proplen may get modified */ 820 proplen = pcmcia_internal_props[which].len; 821 switch (pcmcia_internal_props[which].prop) { 822 case PCMCIA_PROP_DEFAULT_PM: 823 propptr = pcmcia_default_pm_mode; 824 proplen = strlen(propptr) + 1; 825 break; 826 case PCMCIA_PROP_OLDCS: 827 propptr = (caddr_t)&cs_error_ptr; 828 break; 829 case PCMCIA_PROP_REG: 830 propptr = (caddr_t)ppd->ppd_reg; 831 proplen = ppd->ppd_nreg * sizeof (struct pcm_regs); 832 break; 833 case PCMCIA_PROP_INTR: 834 propptr = (caddr_t)&ppd->ppd_intr; 835 break; 836 837 /* the next set are boolean values */ 838 case PCMCIA_PROP_ACTIVE: 839 propptr = NULL; 840 if (!ppd->ppd_active) { 841 return (DDI_PROP_NOT_FOUND); 842 } 843 break; 844 case PCMCIA_PROP_R2TYPE: 845 propptr = NULL; 846 if (ppd->ppd_flags & PPD_CARD_CARDBUS) 847 return (DDI_PROP_NOT_FOUND); 848 break; 849 case PCMCIA_PROP_CARDBUS: 850 propptr = NULL; 851 if (!(ppd->ppd_flags * PPD_CARD_CARDBUS)) 852 return (DDI_PROP_NOT_FOUND); 853 break; 854 } 855 856 break; 857 858 case PCMCIA_PROP_CIS: 859 /* 860 * once we have the lookup code in place 861 * it is sufficient to break out of the switch 862 * once proplen and propptr are set. 863 * The common prop_op code deals with the rest. 864 */ 865 case PCMCIA_PROP_UNKNOWN: 866 return (ddi_bus_prop_op(dev, dip, ch_dip, prop_op, 867 mod_flags | DDI_PROP_NOTPROM, 868 name, valuep, lengthp)); 869 } 870 871 if (prop_op == PROP_LEN) { 872 /* just the length */ 873 *lengthp = proplen; 874 return (DDI_PROP_SUCCESS); 875 } 876 switch (prop_op) { 877 case PROP_LEN_AND_VAL_ALLOC: 878 if (mod_flags & DDI_PROP_CANSLEEP) 879 flags = KM_SLEEP; 880 else 881 flags = KM_NOSLEEP; 882 buff = kmem_alloc((size_t)proplen, flags); 883 if (buff == NULL) 884 return (DDI_PROP_NO_MEMORY); 885 *(caddr_t *)valuep = (caddr_t)buff; 886 break; 887 case PROP_LEN_AND_VAL_BUF: 888 buff = (caddr_t)valuep; 889 if (len < proplen) 890 return (DDI_PROP_BUF_TOO_SMALL); 891 break; 892 default: 893 break; 894 } 895 896 if (proplen > 0) 897 bcopy(propptr, buff, proplen); 898 *lengthp = proplen; 899 return (DDI_PROP_SUCCESS); 900 } 901 902 903 struct regspec * 904 pcmcia_rnum_to_regspec(dev_info_t *dip, int rnumber) 905 { 906 struct pcmcia_parent_private *ppd; 907 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip); 908 if (ppd->ppd_nreg < rnumber) 909 return (NULL); 910 return ((struct regspec *)&ppd->ppd_reg[rnumber]); 911 } 912 913 struct regspec * 914 pcmcia_rnum_to_mapped(dev_info_t *dip, int rnumber) 915 { 916 struct pcmcia_parent_private *ppd; 917 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip); 918 if (ppd->ppd_nreg < rnumber) 919 return (NULL); 920 if (ppd->ppd_assigned == NULL) 921 return (NULL); 922 if (ppd->ppd_assigned[rnumber].phys_len == 0) 923 return (NULL); 924 else 925 return ((struct regspec *)&ppd->ppd_assigned[rnumber]); 926 } 927 928 int 929 pcmcia_find_rnum(dev_info_t *dip, struct regspec *reg) 930 { 931 struct pcmcia_parent_private *ppd; 932 struct regspec *regp; 933 int i; 934 935 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip); 936 if (ppd == NULL) 937 return (-1); 938 for (regp = (struct regspec *)ppd->ppd_reg, i = 0; 939 i < ppd->ppd_nreg; i++, regp++) { 940 if (bcmp(reg, regp, sizeof (struct regspec)) == 0) 941 return (i); 942 } 943 for (regp = (struct regspec *)ppd->ppd_assigned, i = 0; 944 i < ppd->ppd_nreg; i++, regp++) { 945 if (bcmp(reg, regp, sizeof (struct regspec)) == 0) 946 return (i); 947 } 948 949 return (-1); 950 } 951 952 int 953 pcmcia_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 954 off_t offset, off_t len, caddr_t *vaddrp) 955 { 956 struct pcm_regs *regs, *mregs = NULL, tmp_reg; 957 ddi_map_req_t mr = *mp; 958 ra_return_t ret; 959 int check, rnum = -1; 960 uint32_t base; 961 uchar_t regbuf[sizeof (pci_regspec_t)]; 962 963 mp = &mr; /* a copy of original request */ 964 965 /* check for register number */ 966 switch (mp->map_type) { 967 case DDI_MT_REGSPEC: 968 regs = (struct pcm_regs *)mp->map_obj.rp; 969 mregs = (struct pcm_regs *)mp->map_obj.rp; 970 /* 971 * when using regspec, must not be relocatable 972 * and should be from assigned space. 973 */ 974 if (!PC_REG_RELOC(regs->phys_hi)) 975 return (DDI_FAILURE); 976 rnum = pcmcia_find_rnum(rdip, (struct regspec *)mregs); 977 break; 978 case DDI_MT_RNUMBER: 979 regs = (struct pcm_regs *) 980 pcmcia_rnum_to_regspec(rdip, mp->map_obj.rnumber); 981 mregs = (struct pcm_regs *) 982 pcmcia_rnum_to_mapped(rdip, mp->map_obj.rnumber); 983 rnum = mp->map_obj.rnumber; 984 if (regs == NULL) 985 return (DDI_FAILURE); 986 mp->map_type = DDI_MT_REGSPEC; 987 mp->map_obj.rp = (struct regspec *)mregs; 988 break; 989 default: 990 return (DDI_ME_INVAL); 991 } 992 993 /* basic sanity checks */ 994 switch (mp->map_op) { 995 default: 996 return (DDI_ME_UNIMPLEMENTED); 997 case DDI_MO_UNMAP: 998 if (mregs == NULL) 999 return (DDI_FAILURE); 1000 regs = mregs; 1001 break; 1002 case DDI_MO_MAP_LOCKED: 1003 case DDI_MO_MAP_HANDLE: 1004 panic("unsupported bus operation"); 1005 /*NOTREACHED*/ 1006 } 1007 1008 /* 1009 * we need a private copy for manipulation and 1010 * calculation of the correct ranges 1011 */ 1012 tmp_reg = *regs; 1013 mp->map_obj.rp = (struct regspec *)(regs = &tmp_reg); 1014 base = regs->phys_lo; 1015 if (base == 0 && offset != 0) { 1016 /* 1017 * for now this is an error. What does it really mean 1018 * to ask for an offset from an address that hasn't 1019 * been allocated yet. 1020 */ 1021 return (DDI_ME_INVAL); 1022 } 1023 regs->phys_lo += (uint32_t)offset; 1024 if (len != 0) { 1025 if (len > regs->phys_len) { 1026 return (DDI_ME_INVAL); 1027 } 1028 regs->phys_len = len; 1029 } 1030 1031 /* 1032 * basic sanity is checked so now make sure 1033 * we can actually allocate something for this 1034 * request and then convert to a "standard" 1035 * regspec for the next layer up (pci/isa/rootnex/etc.) 1036 */ 1037 1038 switch (PC_GET_REG_TYPE(regs->phys_hi)) { 1039 case PC_REG_SPACE_IO: 1040 check = PCA_RES_NEED_IO; 1041 break; 1042 case PC_REG_SPACE_MEMORY: 1043 check = PCA_RES_NEED_MEM; 1044 break; 1045 default: 1046 /* not a valid register type */ 1047 return (DDI_FAILURE); 1048 } 1049 1050 mr.map_type = DDI_MT_REGSPEC; 1051 ret.ra_addr_hi = 0; 1052 ret.ra_addr_lo = regs->phys_lo; 1053 ret.ra_len = regs->phys_len; 1054 mr.map_obj.rp = pcmcia_cons_regspec(dip, 1055 (check == PCA_RES_NEED_IO) ? 1056 PCMCIA_MAP_IO : PCMCIA_MAP_MEM, 1057 regbuf, &ret); 1058 switch (mp->map_op) { 1059 case DDI_MO_UNMAP: 1060 pcmcia_set_assigned(rdip, rnum, NULL); 1061 break; 1062 default: 1063 break; 1064 } 1065 return (ddi_map(dip, &mr, (off_t)0, (off_t)0, vaddrp)); 1066 } 1067 1068 /* 1069 * pcmcia_cons_regspec() 1070 * based on parent's bus type, construct a regspec that is usable 1071 * by that parent to map the resource into the system. 1072 */ 1073 #define PTYPE_PCI 1 1074 #define PTYPE_ISA 0 1075 struct regspec * 1076 pcmcia_cons_regspec(dev_info_t *dip, int type, uchar_t *buff, ra_return_t *ret) 1077 { 1078 int ptype = -1, len, bus; 1079 char device_type[MODMAXNAMELEN + 1]; 1080 dev_info_t *pdip; 1081 struct regspec *defreg; 1082 pci_regspec_t *pcireg; 1083 1084 pdip = ddi_get_parent(dip); 1085 if (pdip != ddi_root_node()) { 1086 /* we're not a child of root so find out what */ 1087 len = sizeof (device_type); 1088 if (ddi_prop_op(DDI_DEV_T_ANY, pdip, PROP_LEN_AND_VAL_BUF, 0, 1089 "device_type", (caddr_t)device_type, &len) == 1090 DDI_PROP_SUCCESS) { 1091 /* check things out */ 1092 if (strcmp(device_type, "pci") == 0) 1093 ptype = PTYPE_PCI; 1094 else if (strcmp(device_type, "isa") == 0) 1095 ptype = PTYPE_ISA; 1096 } 1097 } 1098 switch (ptype) { 1099 case PTYPE_PCI: 1100 /* XXX need to look at carefully */ 1101 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1102 "reg", (caddr_t)&pcireg, &len) == DDI_SUCCESS) { 1103 bus = PCI_REG_BUS_G(pcireg->pci_phys_hi); 1104 kmem_free(pcireg, len); 1105 } else { 1106 bus = 0; 1107 } 1108 pcireg = (pci_regspec_t *)buff; 1109 pcireg->pci_phys_hi = (type == PCMCIA_MAP_IO ? PCI_ADDR_IO : 1110 PCI_ADDR_MEM32) | PCI_RELOCAT_B | (bus << 16); 1111 pcireg->pci_phys_mid = ret->ra_addr_hi; 1112 pcireg->pci_phys_low = ret->ra_addr_lo; 1113 if (type == PCMCIA_MAP_IO) 1114 pcireg->pci_phys_low &= 0xFFFF; 1115 pcireg->pci_size_hi = 0; 1116 pcireg->pci_size_low = ret->ra_len; 1117 break; 1118 default: 1119 /* default case is to use struct regspec */ 1120 defreg = (struct regspec *)buff; 1121 defreg->regspec_bustype = type == PCMCIA_MAP_IO ? 1 : 0; 1122 defreg->regspec_addr = ret->ra_addr_lo; 1123 defreg->regspec_size = ret->ra_len; 1124 break; 1125 } 1126 return ((struct regspec *)buff); 1127 } 1128 1129 /* 1130 * pcmcia_init_adapter 1131 * Initialize the per-adapter structures and check to see if 1132 * there are possible other instances coming. 1133 */ 1134 void 1135 pcmcia_init_adapter(anp_t *adapter, dev_info_t *dip) 1136 { 1137 int i, n; 1138 pcmcia_if_t *ls_if; 1139 1140 i = pcmcia_num_adapters++; 1141 pcmcia_adapters[i] = kmem_zalloc(sizeof (struct pcmcia_adapter), 1142 KM_SLEEP); 1143 pcmcia_adapters[i]->pca_dip = dip; 1144 /* should this be pca_winshift??? */ 1145 pcmcia_adapters[i]->pca_module = ddi_name_to_major(ddi_get_name(dip)); 1146 pcmcia_adapters[i]->pca_unit = ddi_get_instance(dip); 1147 pcmcia_adapters[i]->pca_iblock = adapter->an_iblock; 1148 pcmcia_adapters[i]->pca_idev = adapter->an_idev; 1149 pcmcia_adapters[i]->pca_if = ls_if = adapter->an_if; 1150 pcmcia_adapters[i]->pca_number = i; 1151 (void) strcpy(pcmcia_adapters[i]->pca_name, ddi_get_name(dip)); 1152 pcmcia_adapters[i]-> 1153 pca_name[sizeof (pcmcia_adapters[i]->pca_name) - 1] = NULL; 1154 1155 if (ls_if != NULL) { 1156 inquire_adapter_t conf; 1157 int sock, win; 1158 1159 if (ls_if->pcif_inquire_adapter != NULL) 1160 GET_CONFIG(ls_if, dip, &conf); 1161 1162 /* resources - assume worst case and fix from there */ 1163 pcmcia_adapters[i]->pca_flags = PCA_RES_NEED_IRQ | 1164 PCA_RES_NEED_IO | PCA_RES_NEED_MEM; 1165 /* indicate first socket not initialized */ 1166 pcmcia_adapters[i]->pca_first_socket = -1; 1167 1168 if (conf.ResourceFlags & RES_OWN_IRQ) 1169 pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_IRQ; 1170 if (conf.ResourceFlags & RES_OWN_IO) 1171 pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_IO; 1172 if (conf.ResourceFlags & RES_OWN_MEM) 1173 pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_MEM; 1174 if (conf.ResourceFlags & RES_IRQ_SHAREABLE) 1175 pcmcia_adapters[i]->pca_flags |= PCA_IRQ_SHAREABLE; 1176 if (conf.ResourceFlags & RES_IRQ_NEXUS) 1177 pcmcia_adapters[i]->pca_flags |= PCA_IRQ_SMI_SHARE; 1178 1179 /* need to know interrupt limitations */ 1180 if (conf.ActiveLow) { 1181 pcmcia_adapters[i]->pca_avail_intr = conf.ActiveLow; 1182 pcmcia_adapters[i]->pca_flags |= PCA_IRQ_ISA; 1183 } else 1184 pcmcia_adapters[i]->pca_avail_intr = conf.ActiveHigh; 1185 1186 /* power entries for adapter */ 1187 pcmcia_adapters[i]->pca_power = 1188 conf.power_entry; 1189 pcmcia_adapters[i]->pca_numpower = 1190 conf.NumPower; 1191 1192 for (n = 0; n < conf.NumPower; n++) 1193 pcmcia_merge_power(&conf.power_entry[n]); 1194 1195 /* now setup the per socket info */ 1196 for (sock = 0; sock < conf.NumSockets; 1197 sock++) { 1198 dev_info_t *sockdrv = NULL; 1199 sockdrv = pcmcia_number_socket(dip, sock); 1200 if (sockdrv == NULL) 1201 n = sock + pcmcia_num_sockets; 1202 else { 1203 n = ddi_get_instance(sockdrv); 1204 } 1205 /* make sure we know first socket on adapter */ 1206 if (pcmcia_adapters[i]->pca_first_socket == -1) 1207 pcmcia_adapters[i]->pca_first_socket = n; 1208 1209 /* 1210 * the number of sockets is weird. 1211 * we might have only two sockets but 1212 * due to persistence of instances we 1213 * will need to call them something other 1214 * than 0 and 1. So, we use the largest 1215 * instance number as the number and 1216 * have some that just don't get used. 1217 */ 1218 if (n >= pcmcia_num_sockets) 1219 pcmcia_num_sockets = n + 1; 1220 #if defined(PCMCIA_DEBUG) 1221 if (pcmcia_debug) { 1222 cmn_err(CE_CONT, 1223 "pcmcia_init: new socket added %d " 1224 "(%d)\n", 1225 n, pcmcia_num_sockets); 1226 } 1227 #endif 1228 1229 pcmcia_sockets[n] = 1230 kmem_zalloc(sizeof (pcmcia_logical_socket_t), 1231 KM_SLEEP); 1232 pcmcia_sockets[n]->ls_socket = sock; 1233 pcmcia_sockets[n]->ls_if = ls_if; 1234 pcmcia_sockets[n]->ls_adapter = 1235 pcmcia_adapters[i]; 1236 pcmcia_sockets[n]->ls_cs_events = 0L; 1237 pcmcia_sockets[n]->ls_sockdrv = sockdrv; 1238 /* Prototype of intrspec */ 1239 pcmcia_sockets[n]->ls_intr_pri = 1240 adapter->an_ipl; 1241 #if defined(PCMCIA_DEBUG) 1242 if (pcmcia_debug) 1243 cmn_err(CE_CONT, 1244 "phys sock %d, log sock %d\n", 1245 sock, n); 1246 #endif 1247 mutex_init(&pcmcia_sockets[n]->ls_ilock, NULL, 1248 MUTEX_DRIVER, *adapter->an_iblock); 1249 } 1250 1251 pcmcia_adapters[i]->pca_numsockets = conf.NumSockets; 1252 /* now setup the per window information */ 1253 for (win = 0; win < conf.NumWindows; win++) { 1254 n = win + pcmcia_num_windows; 1255 pcmcia_windows[n] = 1256 kmem_zalloc(sizeof (pcmcia_logical_window_t), 1257 KM_SLEEP); 1258 pcmcia_windows[n]->lw_window = win; 1259 pcmcia_windows[n]->lw_if = ls_if; 1260 pcmcia_windows[n]->lw_adapter = 1261 pcmcia_adapters[i]; 1262 } 1263 pcmcia_num_windows += conf.NumWindows; 1264 SET_CALLBACK(ls_if, dip, 1265 pcm_adapter_callback, i); 1266 1267 /* now tell CS about each socket */ 1268 for (sock = 0; sock < pcmcia_num_sockets; sock++) { 1269 #if defined(PCMCIA_DEBUG) 1270 if (pcmcia_debug) { 1271 cmn_err(CE_CONT, 1272 "pcmcia_init: notify CS socket %d " 1273 "sockp=%p\n", 1274 sock, (void *)pcmcia_sockets[sock]); 1275 } 1276 #endif 1277 if (pcmcia_sockets[sock] == NULL || 1278 (pcmcia_sockets[sock]->ls_flags & 1279 PCS_SOCKET_ADDED)) { 1280 /* skip the ones that are done already */ 1281 continue; 1282 } 1283 pcmcia_sockets[sock]->ls_flags |= PCS_SOCKET_ADDED; 1284 if (cs_event(PCE_ADD_SOCKET, sock, 0) != 1285 CS_SUCCESS) { 1286 /* flag socket as broken */ 1287 pcmcia_sockets[sock]->ls_flags = 0; 1288 } else { 1289 pcm_event_manager(PCE_ADD_SOCKET, 1290 sock, NULL); 1291 } 1292 } 1293 1294 } 1295 #if defined(PCMCIA_DEBUG) 1296 if (pcmcia_debug) { 1297 cmn_err(CE_CONT, "logical sockets:\n"); 1298 for (i = 0; i < pcmcia_num_sockets; i++) { 1299 if (pcmcia_sockets[i] == NULL) 1300 continue; 1301 cmn_err(CE_CONT, 1302 "\t%d: phys sock=%d, if=%p, adapt=%p\n", 1303 i, pcmcia_sockets[i]->ls_socket, 1304 (void *)pcmcia_sockets[i]->ls_if, 1305 (void *)pcmcia_sockets[i]->ls_adapter); 1306 } 1307 cmn_err(CE_CONT, "logical windows:\n"); 1308 for (i = 0; i < pcmcia_num_windows; i++) { 1309 cmn_err(CE_CONT, 1310 "\t%d: phys_window=%d, if=%p, adapt=%p\n", 1311 i, pcmcia_windows[i]->lw_window, 1312 (void *)pcmcia_windows[i]->lw_if, 1313 (void *)pcmcia_windows[i]->lw_adapter); 1314 } 1315 cmn_err(CE_CONT, "\tpcmcia_num_power=%d\n", pcmcia_num_power); 1316 for (n = 0; n < pcmcia_num_power; n++) 1317 cmn_err(CE_CONT, 1318 "\t\tPowerLevel: %d\tValidSignals: %x\n", 1319 pcmcia_power_table[n].PowerLevel, 1320 pcmcia_power_table[n].ValidSignals); 1321 } 1322 #endif 1323 } 1324 1325 /* 1326 * pcmcia_find_cards() 1327 * check the adapter to see if there are cards present at 1328 * driver attach time. If there are, generate an artificial 1329 * card insertion event to get CS running and the PC Card ultimately 1330 * identified. 1331 */ 1332 void 1333 pcmcia_find_cards(anp_t *adapt) 1334 { 1335 int i; 1336 get_ss_status_t status; 1337 for (i = 0; i < pcmcia_num_sockets; i++) { 1338 if (pcmcia_sockets[i] && 1339 pcmcia_sockets[i]->ls_if == adapt->an_if) { 1340 /* check the status */ 1341 status.socket = i; 1342 if (SSGetStatus(&status) == SUCCESS && 1343 status.IFType != IF_CARDBUS && 1344 status.CardState & SBM_CD && 1345 pcmcia_sockets[i]->ls_dip[0] == NULL) { 1346 (void) cs_event(PCE_CARD_INSERT, i, 0); 1347 delay(1); 1348 } 1349 } 1350 } 1351 } 1352 1353 /* 1354 * pcmcia_number_socket(dip, adapt) 1355 * we determine socket number by creating a driver for each 1356 * socket on the adapter and then forcing it to attach. This 1357 * results in an instance being assigned which becomes the 1358 * logical socket number. If it fails, then we are the first 1359 * set of sockets and renumbering occurs later. We do this 1360 * one socket at a time and return the dev_info_t so the 1361 * instance number can be used. 1362 */ 1363 dev_info_t * 1364 pcmcia_number_socket(dev_info_t *dip, int localsocket) 1365 { 1366 dev_info_t *child = NULL; 1367 struct pcmcia_parent_private *ppd; 1368 1369 if (ndi_devi_alloc(dip, "pcs", (pnode_t)DEVI_SID_NODEID, 1370 &child) == NDI_SUCCESS) { 1371 ppd = kmem_zalloc(sizeof (struct pcmcia_parent_private), 1372 KM_SLEEP); 1373 ppd->ppd_reg = kmem_zalloc(sizeof (struct pcm_regs), KM_SLEEP); 1374 ppd->ppd_nreg = 1; 1375 ppd->ppd_reg[0].phys_hi = localsocket; 1376 ddi_set_parent_data(child, (caddr_t)ppd); 1377 if (ndi_devi_online(child, 0) != NDI_SUCCESS) { 1378 kmem_free(ppd->ppd_reg, sizeof (struct pcm_regs)); 1379 kmem_free(ppd, sizeof (struct pcmcia_parent_private)); 1380 (void) ndi_devi_free(child); 1381 child = NULL; 1382 } 1383 } 1384 return (child); 1385 } 1386 1387 /* 1388 * pcm_phys_to_log_socket() 1389 * from an adapter and socket number return the logical socket 1390 */ 1391 int 1392 pcm_phys_to_log_socket(struct pcmcia_adapter *adapt, int socket) 1393 { 1394 register pcmcia_logical_socket_t *sockp; 1395 int i; 1396 1397 for (i = 0, sockp = pcmcia_sockets[0]; 1398 i < pcmcia_num_sockets; i++, sockp = pcmcia_sockets[i]) { 1399 if (sockp == NULL) 1400 continue; 1401 if (sockp->ls_socket == socket && sockp->ls_adapter == adapt) 1402 break; 1403 } 1404 if (i >= pcmcia_num_sockets) { 1405 #if defined(PCMCIA_DEBUG) 1406 if (pcmcia_debug) 1407 cmn_err(CE_CONT, 1408 "\tbad socket/adapter: %x/%p != %x/%x\n", 1409 socket, (void *)adapt, pcmcia_num_sockets, 1410 pcmcia_num_adapters); 1411 #endif 1412 return (-1); 1413 } 1414 1415 return (i); /* want logical socket */ 1416 } 1417 1418 /* 1419 * pcm_adapter_callback() 1420 * this function is called back by the adapter driver at interrupt time. 1421 * It is here that events should get generated for the event manager if it 1422 * is present. It would also be the time where a device information 1423 * tree could be constructed for a card that was added in if we 1424 * choose to create them dynamically. 1425 */ 1426 1427 #if defined(PCMCIA_DEBUG) 1428 char *cblist[] = { 1429 "removal", 1430 "insert", 1431 "ready", 1432 "battery-warn", 1433 "battery-dead", 1434 "status-change", 1435 "write-protect", "reset", "unlock", "client-info", "eject-complete", 1436 "eject-request", "erase-complete", "exclusive-complete", 1437 "exclusive-request", "insert-complete", "insert-request", 1438 "reset-complete", "reset-request", "timer-expired", 1439 "resume", "suspend" 1440 }; 1441 #endif 1442 1443 /*ARGSUSED*/ 1444 static int 1445 pcm_adapter_callback(dev_info_t *dip, int adapter, int event, int socket) 1446 { 1447 pcmcia_logical_socket_t *sockp; 1448 1449 #if defined(PCMCIA_DEBUG) 1450 if (pcmcia_debug) { 1451 cmn_err(CE_CONT, "pcm_adapter_callback: %p %x %x %x: ", 1452 (void *)dip, adapter, event, socket); 1453 cmn_err(CE_CONT, "[%s]\n", cblist[event]); 1454 } 1455 #endif 1456 1457 if (adapter >= pcmcia_num_adapters || adapter < 0) { 1458 #if defined(PCMCIA_DEBUG) 1459 if (pcmcia_debug) 1460 cmn_err(CE_CONT, "\tbad adapter number: %d : %d\n", 1461 adapter, pcmcia_num_adapters); 1462 #endif 1463 return (1); 1464 } 1465 1466 /* get the logical socket since that is what CS knows */ 1467 socket = pcm_phys_to_log_socket(pcmcia_adapters[adapter], socket); 1468 if (socket == -1) { 1469 cmn_err(CE_WARN, "pcmcia callback - bad logical socket\n"); 1470 return (0); 1471 } 1472 sockp = pcmcia_sockets[socket]; 1473 switch (event) { 1474 case -1: /* special case of adapter going away */ 1475 case PCE_CARD_INSERT: 1476 sockp->ls_cs_events |= PCE_E2M(PCE_CARD_INSERT) | 1477 PCE_E2M(PCE_CARD_REMOVAL); 1478 break; 1479 case PCE_CARD_REMOVAL: 1480 /* disable interrupts at this point */ 1481 sockp->ls_cs_events |= PCE_E2M(PCE_CARD_INSERT) | 1482 PCE_E2M(PCE_CARD_REMOVAL); 1483 /* remove children that never attached */ 1484 1485 break; 1486 case PCE_PM_RESUME: 1487 pcmcia_do_resume(socket, sockp); 1488 /* event = PCE_CARD_INSERT; */ 1489 break; 1490 case PCE_PM_SUSPEND: 1491 pcmcia_do_suspend(socket, sockp); 1492 /* event = PCE_CARD_REMOVAL; */ 1493 break; 1494 default: 1495 /* nothing to do */ 1496 break; 1497 } 1498 1499 #if defined(PCMCIA_DEBUG) 1500 if (pcmcia_debug) { 1501 cmn_err(CE_CONT, 1502 "\tevent %d, event mask=%x, match=%x (log socket=%d)\n", 1503 event, 1504 (int)sockp->ls_cs_events, 1505 (int)(sockp->ls_cs_events & PCE_E2M(event)), socket); 1506 } 1507 #endif 1508 1509 if (pcmcia_cs_event && sockp->ls_cs_events & (1 << event)) { 1510 #if defined(PCMCIA_DEBUG) 1511 if (pcmcia_debug) 1512 cmn_err(CE_CONT, "\tcalling CS event handler (%p) " 1513 "with event=%d\n", 1514 (void *)pcmcia_cs_event, event); 1515 #endif 1516 CS_EVENT(event, socket, 0); 1517 } 1518 1519 /* let the event manager(s) know about the event */ 1520 pcm_event_manager(event, socket, NULL); 1521 1522 return (0); 1523 } 1524 1525 /* 1526 * pcm_event_manager() 1527 * checks for registered management driver callback handlers 1528 * if there are any, call them if the event warrants it 1529 */ 1530 void 1531 pcm_event_manager(int event, int socket, void *arg) 1532 { 1533 struct pcmcia_mif *mif; 1534 1535 for (mif = pcmcia_mif_handlers; mif != NULL; mif = mif->mif_next) { 1536 #if defined(PCMCIA_DEBUG) 1537 if (pcmcia_debug) 1538 cmn_err(CE_CONT, 1539 "pcm_event_manager: event=%d, mif_events=%x" 1540 " (tst:%d)\n", 1541 event, (int)*(uint32_t *)mif->mif_events, 1542 PR_GET(mif->mif_events, event)); 1543 #endif 1544 if (PR_GET(mif->mif_events, event)) { 1545 mif->mif_function(mif->mif_id, event, socket, arg); 1546 } 1547 } 1548 1549 } 1550 1551 /* 1552 * pcm_search_devinfo(dev_info_t *, pcm_device_info *, int) 1553 * search for an immediate child node to the nexus and not siblings of nexus 1554 * and not grandchildren. We follow the same sequence that name binding 1555 * follows so we match same class of device (modem == modem) and don't 1556 * have to depend on features that might not exist. 1557 */ 1558 dev_info_t * 1559 pcm_search_devinfo(dev_info_t *self, struct pcm_device_info *info, int socket) 1560 { 1561 char bf[256]; 1562 struct pcmcia_parent_private *ppd; 1563 dev_info_t *dip; 1564 int circular; 1565 1566 #if defined(PCMCIA_DEBUG) 1567 if (pcmcia_debug) 1568 cmn_err(CE_CONT, 1569 "pcm_search_devinfo: socket=%x [%s|%s|%s] pd_flags=%x\n", 1570 socket, info->pd_bind_name, info->pd_generic_name, 1571 info->pd_vers1_name, info->pd_flags); 1572 #endif 1573 1574 ndi_devi_enter(self, &circular); 1575 /* do searches in compatible property order */ 1576 for (dip = (dev_info_t *)DEVI(self)->devi_child; 1577 dip != NULL; 1578 dip = (dev_info_t *)DEVI(dip)->devi_sibling) { 1579 int ppd_socket; 1580 ppd = (struct pcmcia_parent_private *) 1581 ddi_get_parent_data(dip); 1582 if (ppd == NULL) { 1583 #if defined(PCMCIA_DEBUG) 1584 cmn_err(CE_WARN, "No parent private data\n"); 1585 #endif 1586 continue; 1587 } 1588 ppd_socket = CS_MAKE_SOCKET_NUMBER(ppd->ppd_socket, 1589 ppd->ppd_function); 1590 #if defined(PCMCIA_DEBUG) 1591 if (pcmcia_debug) { 1592 cmn_err(CE_CONT, "\tbind=[%s], node=[%s]\n", 1593 DEVI(dip)->devi_binding_name, 1594 DEVI(dip)->devi_node_name); 1595 } 1596 #endif 1597 if (info->pd_flags & PCM_NAME_VERS1) { 1598 (void) strcpy(bf, info->pd_vers1_name); 1599 pcmcia_fix_string(bf); 1600 if (DEVI(dip)->devi_binding_name && 1601 strcmp(DEVI(dip)->devi_binding_name, bf) == 0 && 1602 socket == ppd_socket) 1603 break; 1604 } 1605 if ((info->pd_flags & (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) == 1606 (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) { 1607 (void) sprintf(bf, "%s,%x", info->pd_bind_name, 1608 info->pd_function); 1609 if (strcmp(bf, DEVI(dip)->devi_binding_name) == 0 && 1610 socket == ppd->ppd_socket) 1611 break; 1612 } 1613 if (info->pd_flags & PCM_NAME_1275) { 1614 if (DEVI(dip)->devi_binding_name && 1615 strcmp(DEVI(dip)->devi_binding_name, 1616 info->pd_bind_name) == 0 && 1617 socket == ppd_socket) 1618 break; 1619 } 1620 if (info->pd_flags & PCM_NAME_GENERIC) { 1621 (void) sprintf(bf, "%s,%s", PCMDEV_NAMEPREF, 1622 info->pd_generic_name); 1623 if (DEVI(dip)->devi_binding_name && 1624 strcmp(DEVI(dip)->devi_binding_name, bf) == 0 && 1625 socket == ppd_socket) 1626 break; 1627 } 1628 if (info->pd_flags & PCM_NAME_GENERIC) { 1629 if (DEVI(dip)->devi_binding_name && 1630 strcmp(DEVI(dip)->devi_binding_name, 1631 info->pd_generic_name) == 0 && 1632 socket == ppd_socket) 1633 break; 1634 } 1635 if (info->pd_flags & PCM_NO_CONFIG) { 1636 if (DEVI(dip)->devi_binding_name && 1637 strcmp(DEVI(dip)->devi_binding_name, 1638 "pccard,memory") == 0 && 1639 socket == ppd_socket) 1640 break; 1641 } 1642 } 1643 ndi_devi_exit(self, circular); 1644 return (dip); 1645 } 1646 1647 /* 1648 * pcm_find_devinfo() 1649 * this is a wrapper around DDI calls to "find" any 1650 * devinfo node and then from there find the one associated 1651 * with the socket 1652 */ 1653 dev_info_t * 1654 pcm_find_devinfo(dev_info_t *pdip, struct pcm_device_info *info, int socket) 1655 { 1656 dev_info_t *dip; 1657 1658 dip = pcm_search_devinfo(pdip, info, socket); 1659 if (dip == NULL) 1660 return (NULL); 1661 /* 1662 * we have at least a base level dip 1663 * see if there is one (this or a sibling) 1664 * that has the correct socket number 1665 * if there is, return that one else 1666 * NULL so a new one is created 1667 */ 1668 #if defined(PCMCIA_DEBUG) 1669 if (pcmcia_debug) 1670 cmn_err(CE_CONT, "find: initial dip = %p, socket=%d, name=%s " 1671 "(instance=%d, socket=%d, name=%s)\n", 1672 (void *)dip, socket, info->pd_bind_name, 1673 ddi_get_instance(dip), 1674 ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1675 PCM_DEV_SOCKET, -1), 1676 ddi_get_name(dip)); 1677 #endif 1678 1679 #if defined(PCMCIA_DEBUG) 1680 if (pcmcia_debug && dip != NULL) 1681 cmn_err(CE_CONT, "\treturning non-NULL dip (%s)\n", 1682 ddi_get_name(dip)); 1683 #endif 1684 return (dip); 1685 } 1686 1687 /* 1688 * pcm_find_parent_dip(socket) 1689 * find the correct parent dip for this logical socket 1690 */ 1691 dev_info_t * 1692 pcm_find_parent_dip(int socket) 1693 { 1694 if ((socket < 0 || socket >= pcmcia_num_sockets) || 1695 pcmcia_sockets[socket] == NULL) 1696 return (NULL); 1697 return (pcmcia_sockets[socket]->ls_adapter->pca_dip); 1698 } 1699 1700 /* 1701 * pcmcia_set_em_handler() 1702 * This is called by the management and event driver to tell 1703 * the nexus what to call. Multiple drivers are allowed 1704 * but normally only one will exist. 1705 */ 1706 int 1707 pcmcia_set_em_handler(int (*handler)(), caddr_t events, int elen, 1708 uint32_t id, void **cs, void **ss) 1709 { 1710 struct pcmcia_mif *mif, *tmp; 1711 1712 if (handler == NULL) { 1713 /* NULL means remove the handler based on the ID */ 1714 if (pcmcia_mif_handlers == NULL) 1715 return (0); 1716 mutex_enter(&pcmcia_global_lock); 1717 if (pcmcia_mif_handlers->mif_id == id) { 1718 mif = pcmcia_mif_handlers; 1719 pcmcia_mif_handlers = mif->mif_next; 1720 kmem_free(mif, sizeof (struct pcmcia_mif)); 1721 } else { 1722 for (mif = pcmcia_mif_handlers; 1723 mif->mif_next != NULL && 1724 mif->mif_next->mif_id != id; 1725 mif = mif->mif_next) 1726 ; 1727 if (mif->mif_next != NULL && 1728 mif->mif_next->mif_id == id) { 1729 tmp = mif->mif_next; 1730 mif->mif_next = tmp->mif_next; 1731 kmem_free(tmp, sizeof (struct pcmcia_mif)); 1732 } 1733 } 1734 mutex_exit(&pcmcia_global_lock); 1735 } else { 1736 1737 if (pcmcia_num_adapters == 0) { 1738 return (ENXIO); 1739 } 1740 if (elen > EM_EVENTSIZE) 1741 return (EINVAL); 1742 1743 mif = (struct pcmcia_mif *) 1744 kmem_zalloc(sizeof (struct pcmcia_mif), 1745 KM_NOSLEEP); 1746 if (mif == NULL) 1747 return (ENOSPC); 1748 1749 mif->mif_function = (void (*)())handler; 1750 bcopy(events, mif->mif_events, elen); 1751 mif->mif_id = id; 1752 mutex_enter(&pcmcia_global_lock); 1753 mif->mif_next = pcmcia_mif_handlers; 1754 pcmcia_mif_handlers = mif; 1755 if (cs != NULL) 1756 *cs = (void *)pcmcia_card_services; 1757 if (ss != NULL) { 1758 *ss = (void *)SocketServices; 1759 } 1760 1761 mutex_exit(&pcmcia_global_lock); 1762 } 1763 return (0); 1764 } 1765 1766 /* 1767 * pcm_fix_bits(uchar_t *data, int num, int dir) 1768 * shift socket bits left(0) or right(0) 1769 * This is used when mapping logical and physical 1770 */ 1771 void 1772 pcm_fix_bits(socket_enum_t src, socket_enum_t dst, int num, int dir) 1773 { 1774 int i; 1775 1776 PR_ZERO(dst); 1777 1778 if (dir == 0) { 1779 /* LEFT */ 1780 for (i = 0; i <= (sizeof (dst) * PR_WORDSIZE) - num; i++) { 1781 if (PR_GET(src, i)) 1782 PR_SET(dst, i + num); 1783 } 1784 } else { 1785 /* RIGHT */ 1786 for (i = num; i < sizeof (dst) * PR_WORDSIZE; i++) { 1787 if (PR_GET(src, i)) 1788 PR_SET(dst, i - num); 1789 } 1790 } 1791 } 1792 1793 uint32_t 1794 genmask(int len) 1795 { 1796 uint32_t mask; 1797 for (mask = 0; len > 0; len--) { 1798 mask |= 1 << (len - 1); 1799 } 1800 return (mask); 1801 } 1802 1803 int 1804 genp2(int val) 1805 { 1806 int i; 1807 if (val == 0) 1808 return (0); 1809 for (i = 0; i < 32; i++) 1810 if (val > (1 << i)) 1811 return (i); 1812 return (0); 1813 } 1814 1815 #if defined(PCMCIA_DEBUG) 1816 char *ssfuncs[128] = { 1817 "GetAdapter", "GetPage", "GetSocket", "GetStatus", "GetWindow", 1818 "InquireAdapter", "InquireSocket", "InquireWindow", "ResetSocket", 1819 "SetPage", "SetAdapter", "SetSocket", "SetWindow", "SetIRQHandler", 1820 "ClearIRQHandler", 1821 /* 15 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1822 /* 25 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1823 /* 35 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1824 /* 45 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1825 /* 55 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1826 /* 65 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1827 /* 75 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1828 /* 85 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1829 /* 95 */ NULL, NULL, NULL, 1830 "CSIsActiveDip", 1831 "CSInitDev", "CSRegister", "CSCISInit", "CSUnregister", 1832 "CISGetAddress", "CISSetAddress", "CSCardRemoved", "CSGetCookiesAndDip" 1833 }; 1834 #endif 1835 1836 /* 1837 * SocketServices 1838 * general entrypoint for Card Services to find 1839 * Socket Services. Finding the entry requires 1840 * a _depends_on[] relationship. 1841 * 1842 * In some cases, the work is done locally but usually 1843 * the parameters are adjusted and the adapter driver 1844 * code asked to do the work. 1845 */ 1846 int 1847 SocketServices(int function, ...) 1848 { 1849 va_list arglist; 1850 uint32_t args[16]; 1851 csregister_t *reg; 1852 sservice_t *serv; 1853 dev_info_t *dip; 1854 int socket, func; 1855 int error = SUCCESS; 1856 pcmcia_logical_socket_t *sockp; 1857 1858 va_start(arglist, function); 1859 1860 #if defined(PCMCIA_DEBUG) 1861 if (pcmcia_debug > 1) 1862 cmn_err(CE_CONT, "SocketServices called for function %d [%s]\n", 1863 function, 1864 ((function < 128) && ssfuncs[function] != NULL) ? 1865 ssfuncs[function] : "UNKNOWN"); 1866 #endif 1867 switch (function) { 1868 case CSRegister: 1869 case CISGetAddress: 1870 case CISSetAddress: 1871 1872 reg = va_arg(arglist, csregister_t *); 1873 1874 if (reg->cs_magic != PCCS_MAGIC || 1875 reg->cs_version != PCCS_VERSION) { 1876 cmn_err(CE_WARN, 1877 "pcmcia: CSRegister (%x, %x, %p, %p) *ERROR*", 1878 reg->cs_magic, reg->cs_version, 1879 (void *)reg->cs_card_services, 1880 (void *)reg->cs_event); 1881 error = BAD_FUNCTION; 1882 break; 1883 } 1884 1885 switch (function) { 1886 case CISGetAddress: 1887 reg->cs_event = pcmcia_cis_parser; 1888 break; 1889 case CISSetAddress: 1890 pcmcia_cis_parser = reg->cs_event; 1891 break; 1892 case CSRegister: 1893 break; 1894 } 1895 break; 1896 1897 case CSUnregister: 1898 break; 1899 1900 case CSCISInit: 1901 args[0] = va_arg(arglist, int); 1902 #if defined(PCMCIA_DEBUG) 1903 if (pcmcia_debug) 1904 cmn_err(CE_CONT, 1905 "CSCISInit: CIS is initialized on socket %d\n", 1906 (int)args[0]); 1907 #endif 1908 /* 1909 * now that the CIS has been parsed (there may not 1910 * be one but the work is done) we can create the 1911 * device information structures. 1912 * 1913 * we serialize the node creation to avoid problems 1914 * with initial probe/attach of nexi. 1915 */ 1916 1917 mutex_enter(&pcmcia_global_lock); 1918 pcmcia_create_dev_info(args[0]); 1919 cv_broadcast(&pcmcia_condvar); /* wakeup the nexus attach */ 1920 mutex_exit(&pcmcia_global_lock); 1921 break; 1922 1923 case CSInitDev: 1924 #if defined(PCMCIA_DEBUG) 1925 if (pcmcia_debug) 1926 cmn_err(CE_CONT, "CSInitDev: initialize device\n"); 1927 #endif 1928 /* 1929 * this is where we create the /devices entries 1930 * that let us out into the world 1931 */ 1932 1933 (void) pcmcia_create_device(va_arg(arglist, 1934 ss_make_device_node_t *)); 1935 break; 1936 1937 case CSCardRemoved: 1938 args[0] = va_arg(arglist, uint32_t); 1939 socket = CS_GET_SOCKET_NUMBER(args[0]); 1940 func = CS_GET_FUNCTION_NUMBER(args[0]); 1941 #if defined(PCMCIA_DEBUG) 1942 if (pcmcia_debug) 1943 cmn_err(CE_CONT, 1944 "CSCardRemoved! (socket=%d)\n", (int)args[0]); 1945 #endif 1946 if (socket >= pcmcia_num_sockets) 1947 break; 1948 1949 sockp = pcmcia_sockets[socket]; 1950 if (sockp == NULL) { 1951 cmn_err(CE_WARN, 1952 "pcmcia: bad socket = %x", socket); 1953 break; 1954 } 1955 1956 for (func = 0; func < sockp->ls_functions; func++) { 1957 /* 1958 * break the association of dip and socket 1959 * for all functions on that socket 1960 */ 1961 dip = sockp->ls_dip[func]; 1962 sockp->ls_dip[func] = NULL; 1963 if (dip != NULL) { 1964 struct pcmcia_parent_private *ppd; 1965 ppd = (struct pcmcia_parent_private *) 1966 ddi_get_parent_data(dip); 1967 ppd->ppd_active = 0; 1968 (void) ndi_devi_offline(dip, 1969 NDI_DEVI_REMOVE); 1970 1971 pcmcia_ppd_free(ppd); 1972 } 1973 #if defined(PCMCIA_DEBUG) 1974 else { 1975 if (pcmcia_debug) 1976 cmn_err(CE_CONT, 1977 "CardRemoved: no " 1978 "dip present " 1979 "on socket %d!\n", 1980 (int)args[0]); 1981 } 1982 #endif 1983 } 1984 if (sockp->ls_flags & PCS_SUSPENDED) { 1985 mutex_enter(&pcmcia_global_lock); 1986 sockp->ls_flags &= ~PCS_SUSPENDED; 1987 cv_broadcast(&pcmcia_condvar); 1988 mutex_exit(&pcmcia_global_lock); 1989 } 1990 break; 1991 1992 case CSGetCookiesAndDip: 1993 serv = va_arg(arglist, sservice_t *); 1994 if (serv != NULL) 1995 error = GetCookiesAndDip(serv); 1996 else 1997 error = BAD_SOCKET; 1998 break; 1999 2000 case CSGetActiveDip: 2001 /* 2002 * get the dip associated with the card currently 2003 * in the specified socket 2004 */ 2005 args[0] = va_arg(arglist, uint32_t); 2006 socket = CS_GET_SOCKET_NUMBER(args[0]); 2007 func = CS_GET_FUNCTION_NUMBER(args[0]); 2008 error = (long)pcmcia_sockets[socket]->ls_dip[func]; 2009 break; 2010 2011 /* 2012 * the remaining entries are SocketServices calls 2013 */ 2014 case SS_GetAdapter: 2015 error = SSGetAdapter(va_arg(arglist, get_adapter_t *)); 2016 break; 2017 case SS_GetPage: 2018 error = SSGetPage(va_arg(arglist, get_page_t *)); 2019 break; 2020 case SS_GetSocket: 2021 error = SSGetSocket(va_arg(arglist, get_socket_t *)); 2022 break; 2023 case SS_GetStatus: 2024 error = SSGetStatus(va_arg(arglist, get_ss_status_t *)); 2025 break; 2026 case SS_GetWindow: 2027 error = SSGetWindow(va_arg(arglist, get_window_t *)); 2028 break; 2029 case SS_InquireAdapter: 2030 error = SSInquireAdapter(va_arg(arglist, inquire_adapter_t *)); 2031 break; 2032 case SS_InquireSocket: 2033 error = SSInquireSocket(va_arg(arglist, inquire_socket_t *)); 2034 break; 2035 case SS_InquireWindow: 2036 error = SSInquireWindow(va_arg(arglist, inquire_window_t *)); 2037 break; 2038 case SS_ResetSocket: 2039 args[0] = va_arg(arglist, uint32_t); 2040 args[1] = va_arg(arglist, int); 2041 error = SSResetSocket(args[0], args[1]); 2042 break; 2043 case SS_SetPage: 2044 error = SSSetPage(va_arg(arglist, set_page_t *)); 2045 break; 2046 case SS_SetSocket: 2047 error = SSSetSocket(va_arg(arglist, set_socket_t *)); 2048 break; 2049 case SS_SetWindow: 2050 error = SSSetWindow(va_arg(arglist, set_window_t *)); 2051 break; 2052 case SS_SetIRQHandler: 2053 error = SSSetIRQHandler(va_arg(arglist, set_irq_handler_t *)); 2054 break; 2055 case SS_ClearIRQHandler: 2056 error = SSClearIRQHandler(va_arg(arglist, 2057 clear_irq_handler_t *)); 2058 break; 2059 default: 2060 error = BAD_FUNCTION; 2061 break; 2062 } 2063 va_end(arglist); 2064 return (error); 2065 } 2066 2067 /* 2068 * pcmcia_merge_power() 2069 * The adapters may have different power tables so it 2070 * is necessary to construct a single power table that 2071 * can be used throughout the system. The result is 2072 * a merger of all capabilities. The nexus adds 2073 * power table entries one at a time. 2074 */ 2075 void 2076 pcmcia_merge_power(struct power_entry *power) 2077 { 2078 int i; 2079 struct power_entry pwr; 2080 2081 pwr = *power; 2082 2083 for (i = 0; i < pcmcia_num_power; i++) { 2084 if (pwr.PowerLevel == pcmcia_power_table[i].PowerLevel) { 2085 if (pwr.ValidSignals == 2086 pcmcia_power_table[i].ValidSignals) { 2087 return; 2088 } else { 2089 /* partial match */ 2090 pwr.ValidSignals &= 2091 ~pcmcia_power_table[i].ValidSignals; 2092 } 2093 } 2094 } 2095 /* what's left becomes a new entry */ 2096 if (pcmcia_num_power == PCMCIA_MAX_POWER) 2097 return; 2098 pcmcia_power_table[pcmcia_num_power++] = pwr; 2099 } 2100 2101 /* 2102 * pcmcia_do_suspend() 2103 * tell CS that a suspend has happened by passing a 2104 * card removal event. Then cleanup the socket state 2105 * to fake the cards being removed so resume works 2106 */ 2107 void 2108 pcmcia_do_suspend(int socket, pcmcia_logical_socket_t *sockp) 2109 { 2110 get_ss_status_t stat; 2111 struct pcmcia_adapter *adapt; 2112 pcmcia_if_t *ls_if; 2113 dev_info_t *dip; 2114 int i; 2115 2116 #ifdef XXX 2117 if (pcmcia_cs_event == NULL) { 2118 return; 2119 } 2120 #endif 2121 2122 ls_if = sockp->ls_if; 2123 adapt = sockp->ls_adapter; 2124 2125 if (ls_if == NULL || ls_if->pcif_get_status == NULL) { 2126 return; 2127 } 2128 2129 stat.socket = socket; 2130 #if defined(PCMCIA_DEBUG) 2131 if (pcmcia_debug) { 2132 cmn_err(CE_CONT, 2133 "pcmcia_do_suspend(%d, %p)\n", socket, (void *)sockp); 2134 } 2135 #endif 2136 2137 if (GET_STATUS(ls_if, adapt->pca_dip, &stat) != SUCCESS) 2138 return; 2139 2140 /* 2141 * If there is a card in the socket, then we need to send 2142 * everyone a PCE_CARD_REMOVAL event, and remove the 2143 * card active property. 2144 */ 2145 2146 for (i = 0; i < sockp->ls_functions; i++) { 2147 struct pcmcia_parent_private *ppd; 2148 dip = sockp->ls_dip[i]; 2149 if (dip != NULL) { 2150 ppd = (struct pcmcia_parent_private *) 2151 ddi_get_parent_data(dip); 2152 ppd->ppd_flags |= PPD_SUSPENDED; 2153 } 2154 #if 0 2155 sockp->ls_dip[i] = NULL; 2156 #endif 2157 } 2158 sockp->ls_flags |= PCS_SUSPENDED; 2159 2160 if (pcmcia_cs_event && 2161 (sockp->ls_cs_events & (1 << PCE_PM_SUSPEND))) { 2162 CS_EVENT(PCE_PM_SUSPEND, socket, 0); 2163 } 2164 pcm_event_manager(PCE_PM_SUSPEND, socket, NULL); 2165 } 2166 2167 /* 2168 * pcmcia_do_resume() 2169 * tell CS that a suspend has happened by passing a 2170 * card removal event. Then cleanup the socket state 2171 * to fake the cards being removed so resume works 2172 */ 2173 void 2174 pcmcia_do_resume(int socket, pcmcia_logical_socket_t *sockp) 2175 { 2176 get_ss_status_t stat; 2177 struct pcmcia_adapter *adapt; 2178 pcmcia_if_t *ls_if; 2179 2180 #ifdef XXX 2181 if (pcmcia_cs_event == NULL) { 2182 return; 2183 } 2184 #endif 2185 2186 ls_if = sockp->ls_if; 2187 adapt = sockp->ls_adapter; 2188 2189 if (ls_if == NULL || ls_if->pcif_get_status == NULL) { 2190 return; 2191 } 2192 2193 stat.socket = socket; 2194 #if defined(PCMCIA_DEBUG) 2195 if (pcmcia_debug) { 2196 cmn_err(CE_CONT, 2197 "pcmcia_do_resume(%d, %p)\n", socket, (void *)sockp); 2198 } 2199 #endif 2200 if (GET_STATUS(ls_if, adapt->pca_dip, &stat) == 2201 SUCCESS) { 2202 2203 #if defined(PCMCIA_DEBUG) 2204 if (pcmcia_debug) 2205 cmn_err(CE_CONT, "\tsocket=%x, CardState=%x\n", 2206 socket, stat.CardState); 2207 #endif 2208 #if 0 2209 /* now have socket info -- do we have events? */ 2210 if ((stat.CardState & SBM_CD) == SBM_CD) { 2211 if (pcmcia_cs_event && 2212 (sockp->ls_cs_events & (1 << PCE_CARD_INSERT))) { 2213 CS_EVENT(PCE_CARD_INSERT, socket, 0); 2214 } 2215 2216 /* we should have card removed from CS soon */ 2217 pcm_event_manager(PCE_CARD_INSERT, socket, NULL); 2218 } 2219 #else 2220 if (pcmcia_cs_event && 2221 (sockp->ls_cs_events & (1 << PCE_PM_SUSPEND))) { 2222 CS_EVENT(PCE_PM_RESUME, socket, 0); 2223 CS_EVENT(PCE_CARD_REMOVAL, socket, 0); 2224 if ((stat.CardState & SBM_CD) == SBM_CD) 2225 CS_EVENT(PCE_CARD_INSERT, socket, 0); 2226 } 2227 #endif 2228 } 2229 } 2230 2231 /* 2232 * pcmcia_map_power_set() 2233 * Given a power table entry and level, find it in the 2234 * master table and return the index in the adapter table. 2235 */ 2236 static int 2237 pcmcia_map_power_set(struct pcmcia_adapter *adapt, int level, int which) 2238 { 2239 int plevel, i; 2240 struct power_entry *pwr = (struct power_entry *)adapt->pca_power; 2241 plevel = pcmcia_power_table[level].PowerLevel; 2242 /* mask = pcmcia_power_table[level].ValidSignals; */ 2243 for (i = 0; i < adapt->pca_numpower; i++) 2244 if (plevel == pwr[i].PowerLevel && 2245 pwr[i].ValidSignals & which) 2246 return (i); 2247 return (0); 2248 } 2249 2250 /* 2251 * pcmcia_map_power_get() 2252 * Given an adapter power entry, find the appropriate index 2253 * in the master table. 2254 */ 2255 static int 2256 pcmcia_map_power_get(struct pcmcia_adapter *adapt, int level, int which) 2257 { 2258 int plevel, i; 2259 struct power_entry *pwr = (struct power_entry *)adapt->pca_power; 2260 plevel = pwr[level].PowerLevel; 2261 /* mask = pwr[level].ValidSignals; */ 2262 for (i = 0; i < pcmcia_num_power; i++) 2263 if (plevel == pcmcia_power_table[i].PowerLevel && 2264 pcmcia_power_table[i].ValidSignals & which) 2265 return (i); 2266 return (0); 2267 } 2268 2269 /* 2270 * XXX - SS really needs a way to allow the caller to express 2271 * interest in PCE_CARD_STATUS_CHANGE events. 2272 */ 2273 static uint32_t 2274 pcm_event_map[32] = { 2275 PCE_E2M(PCE_CARD_WRITE_PROTECT)|PCE_E2M(PCE_CARD_STATUS_CHANGE), 2276 PCE_E2M(PCE_CARD_UNLOCK)|PCE_E2M(PCE_CARD_STATUS_CHANGE), 2277 PCE_E2M(PCE_EJECTION_REQUEST)|PCE_E2M(PCE_CARD_STATUS_CHANGE), 2278 PCE_E2M(PCE_INSERTION_REQUEST)|PCE_E2M(PCE_CARD_STATUS_CHANGE), 2279 PCE_E2M(PCE_CARD_BATTERY_WARN)|PCE_E2M(PCE_CARD_STATUS_CHANGE), 2280 PCE_E2M(PCE_CARD_BATTERY_DEAD)|PCE_E2M(PCE_CARD_STATUS_CHANGE), 2281 PCE_E2M(PCE_CARD_READY)|PCE_E2M(PCE_CARD_STATUS_CHANGE), 2282 PCE_E2M(PCE_CARD_REMOVAL)|PCE_E2M(PCE_CARD_INSERT)| 2283 PCE_E2M(PCE_CARD_STATUS_CHANGE), 2284 PCE_E2M(PCE_PM_SUSPEND)|PCE_E2M(PCE_PM_RESUME), 2285 }; 2286 2287 static int 2288 pcm_mapevents(uint32_t eventmask) 2289 { 2290 uint32_t mask; 2291 int i; 2292 2293 for (i = 0, mask = 0; eventmask && i < 32; i++) { 2294 if (eventmask & (1 << i)) { 2295 mask |= pcm_event_map[i]; 2296 eventmask &= ~(1 << i); 2297 } 2298 } 2299 return (mask); 2300 } 2301 2302 2303 /* 2304 * PCMCIA Generic Naming Support 2305 * 2306 * With 2.6, PCMCIA naming moves to the 1275 and generic naming model. 2307 * Consequently, the whole naming mechanism is to be changed. This is 2308 * not backward compatible with the current names but that isn't a problem 2309 * due to so few drivers existing. 2310 * 2311 * For cards with a device_id tuple, a generic name will be used. 2312 * if there is no device_id, then the 1275 name will be used if possible. 2313 * The 1275 name is of the form pccardNNNN,MMMM from the manfid tuple. 2314 * if there is not manfid tuple, an attempt will be made to bind the 2315 * node to the version_1 strings. 2316 * 2317 * In all cases, a "compatible" property is created with a number 2318 * of names. The most generic name will be last in the list. 2319 */ 2320 2321 /* 2322 * pcmcia_fix_string() 2323 * want to avoid special characters in alias strings so convert 2324 * to something innocuous 2325 */ 2326 2327 void 2328 pcmcia_fix_string(char *str) 2329 { 2330 for (; str && *str; str++) { 2331 switch (*str) { 2332 case ' ': 2333 case '\t': 2334 *str = '_'; 2335 break; 2336 } 2337 } 2338 } 2339 2340 void 2341 pcmcia_1275_name(int socket, struct pcm_device_info *info, 2342 client_handle_t handle) 2343 { 2344 cistpl_manfid_t manfid; 2345 cistpl_jedec_t jedec; 2346 tuple_t tuple; 2347 int i; 2348 2349 tuple.Socket = socket; 2350 2351 /* get MANFID if it exists -- this is most important form */ 2352 tuple.DesiredTuple = CISTPL_MANFID; 2353 tuple.Attributes = 0; 2354 if ((i = csx_GetFirstTuple(handle, &tuple)) == 2355 SUCCESS) { 2356 i = csx_Parse_CISTPL_MANFID(handle, &tuple, 2357 &manfid); 2358 if (i == SUCCESS) { 2359 (void) sprintf(info->pd_bind_name, "%s%x,%x", 2360 PCMDEV_NAMEPREF, 2361 manfid.manf, manfid.card); 2362 info->pd_flags |= PCM_NAME_1275; 2363 } 2364 } else { 2365 tuple.Attributes = 0; 2366 tuple.DesiredTuple = CISTPL_JEDEC_A; 2367 if ((i = csx_GetFirstTuple(handle, &tuple)) == 2368 SUCCESS) { 2369 i = csx_Parse_CISTPL_JEDEC_A(handle, &tuple, 2370 &jedec); 2371 if (i == SUCCESS) { 2372 (void) sprintf(info->pd_bind_name, "%s%x,%x", 2373 PCMDEV_NAMEPREF, 2374 jedec.jid[0].id, jedec.jid[0].info); 2375 info->pd_flags |= PCM_NAME_1275; 2376 } 2377 } 2378 } 2379 } 2380 2381 void 2382 pcmcia_vers1_name(int socket, struct pcm_device_info *info, 2383 client_handle_t handle) 2384 { 2385 cistpl_vers_1_t vers1; 2386 tuple_t tuple; 2387 int which = 0; 2388 int i, len, space; 2389 2390 tuple.Socket = socket; 2391 info->pd_vers1_name[0] = '\0'; 2392 2393 /* Version 1 strings */ 2394 tuple.DesiredTuple = CISTPL_VERS_1; 2395 tuple.Attributes = 0; 2396 if (!which && 2397 (i = csx_GetFirstTuple(handle, &tuple)) == 2398 SUCCESS) { 2399 i = csx_Parse_CISTPL_VERS_1(handle, &tuple, &vers1); 2400 if (i == SUCCESS) { 2401 for (i = 0, len = 0, space = 0; i < vers1.ns; i++) { 2402 if ((space + len + strlen(info->pd_vers1_name)) >= 2403 sizeof (info->pd_vers1_name)) 2404 break; 2405 if (space) { 2406 info->pd_vers1_name[len++] = ','; 2407 } 2408 (void) strcpy(info->pd_vers1_name + len, 2409 (char *)vers1.pi[i]); 2410 len += strlen((char *)vers1.pi[i]); 2411 /* strip trailing spaces off of string */ 2412 while (info->pd_vers1_name[len - 1] == ' ' && 2413 len > 0) 2414 len--; 2415 space = 1; 2416 } 2417 info->pd_vers1_name[len] = '\0'; 2418 info->pd_flags |= PCM_NAME_VERS1; 2419 } 2420 } 2421 } 2422 2423 2424 int 2425 pcmcia_get_funce(client_handle_t handle, tuple_t *tuple) 2426 { 2427 int ret = 0; 2428 2429 tuple->Attributes = 0; 2430 while (csx_GetNextTuple(handle, tuple) == SUCCESS) { 2431 if (tuple->TupleCode == CISTPL_FUNCID) { 2432 break; 2433 } 2434 if (tuple->TupleCode == CISTPL_FUNCE) { 2435 ret = 1; 2436 break; 2437 } 2438 tuple->Attributes = 0; 2439 } 2440 return (ret); 2441 } 2442 2443 char *pcmcia_lan_types[] = { 2444 "arcnet", 2445 "ethernet", 2446 "token-ring", 2447 "localtalk", 2448 "fddi", 2449 "atm", 2450 "wireless", 2451 "reserved" 2452 }; 2453 2454 void 2455 pcmcia_generic_name(int socket, struct pcm_device_info *info, 2456 client_handle_t handle) 2457 { 2458 cistpl_funcid_t funcid; 2459 cistpl_funce_t funce; 2460 tuple_t tuple; 2461 int which = 0; 2462 int i; 2463 2464 tuple.Socket = socket; 2465 2466 tuple.DesiredTuple = CISTPL_FUNCID; 2467 tuple.Attributes = 0; 2468 if ((i = csx_GetFirstTuple(handle, &tuple)) == 2469 SUCCESS) { 2470 /* 2471 * need to make sure that CISTPL_FUNCID is not 2472 * present in both a global and local CIS for MF 2473 * cards. 3COM seems to do this erroneously 2474 */ 2475 2476 if (info->pd_flags & PCM_MULTI_FUNCTION && 2477 tuple.Flags & CISTPLF_GLOBAL_CIS) { 2478 tuple_t ltuple; 2479 ltuple = tuple; 2480 ltuple.DesiredTuple = CISTPL_FUNCID; 2481 ltuple.Attributes = 0; 2482 if ((i = csx_GetNextTuple(handle, <uple)) == 2483 SUCCESS) { 2484 /* this is the per-function funcid */ 2485 tuple = ltuple; 2486 } 2487 } 2488 2489 i = csx_Parse_CISTPL_FUNCID(handle, &tuple, &funcid); 2490 if (i == SUCCESS) { 2491 /* in case no function extension */ 2492 if (funcid.function < PCM_GENNAME_SIZE) 2493 (void) strcpy(info->pd_generic_name, 2494 pcmcia_generic_names[funcid.function]); 2495 else 2496 (void) sprintf(info->pd_generic_name, 2497 "class,%x", 2498 funcid.function); 2499 } 2500 info->pd_type = funcid.function; 2501 switch (funcid.function) { 2502 case TPLFUNC_LAN: 2503 which = pcmcia_get_funce(handle, &tuple); 2504 if (which) { 2505 i = csx_Parse_CISTPL_FUNCE(handle, 2506 &tuple, 2507 &funce, TPLFUNC_LAN); 2508 if (i == SUCCESS) { 2509 i = funce.data.lan.tech; 2510 if (i > sizeof (pcmcia_lan_types) / 2511 sizeof (char *)) { 2512 break; 2513 } 2514 (void) strcpy(info->pd_generic_name, 2515 pcmcia_lan_types[i]); 2516 } 2517 } 2518 break; 2519 case TPLFUNC_VIDEO: 2520 #ifdef future_pcmcia_spec 2521 which = pcmcia_get_funce(handle, &tuple); 2522 if (which) { 2523 i = csx_Parse_CISTPL_FUNCE(handle, 2524 &tuple, 2525 &funce, TPLFUNC_VIDEO); 2526 if (i == SUCCESS) { 2527 i = funce.video.tech; 2528 if (i > sizeof (pcmcia_lan_types) / 2529 sizeof (char *)) { 2530 break; 2531 } 2532 (void) strcpy(info->pd_generic_names, 2533 pcmcia_lan_types[i]); 2534 } 2535 } 2536 #endif 2537 break; 2538 } 2539 info->pd_flags |= PCM_NAME_GENERIC; 2540 } else { 2541 /* if no FUNCID, do we have CONFIG */ 2542 tuple.DesiredTuple = CISTPL_CONFIG; 2543 tuple.Attributes = 0; 2544 if (csx_GetFirstTuple(handle, &tuple) != SUCCESS) { 2545 info->pd_flags |= PCM_NO_CONFIG | PCM_NAME_GENERIC; 2546 (void) strcpy(info->pd_generic_name, 2547 pcmcia_generic_names[PCM_TYPE_MEMORY]); 2548 info->pd_type = PCM_TYPE_MEMORY; 2549 } 2550 } 2551 } 2552 2553 2554 /* 2555 * pcmcia_add_compatible() 2556 * add the cached compatible property list. 2557 */ 2558 void 2559 pcmcia_add_compatible(dev_info_t *dip, struct pcm_device_info *info) 2560 { 2561 int length = 0, i; 2562 char buff[MAXNAMELEN]; 2563 char *compat_name[8]; 2564 int ci = 0; 2565 2566 bzero(compat_name, sizeof (compat_name)); 2567 2568 if (info->pd_flags & PCM_NAME_VERS1) { 2569 (void) sprintf(buff, "%s,%s", PCMDEV_NAMEPREF, 2570 info->pd_vers1_name); 2571 pcmcia_fix_string(buff); /* don't want spaces */ 2572 length = strlen(buff) + 1; 2573 compat_name[ci] = kmem_alloc(length, KM_SLEEP); 2574 (void) strcpy(compat_name[ci++], buff); 2575 } 2576 2577 if ((info->pd_flags & (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) == 2578 (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) { 2579 (void) sprintf(buff, "%s,%x", info->pd_bind_name, 2580 info->pd_function); 2581 length = strlen(buff) + 1; 2582 compat_name[ci] = kmem_alloc(length, KM_SLEEP); 2583 (void) strcpy(compat_name[ci++], buff); 2584 } 2585 2586 if (info->pd_flags & PCM_NAME_1275) { 2587 length = strlen(info->pd_bind_name) + 1; 2588 compat_name[ci] = kmem_alloc(length, KM_SLEEP); 2589 (void) strcpy(compat_name[ci++], info->pd_bind_name); 2590 } 2591 2592 if (info->pd_flags & PCM_NAME_GENERIC) { 2593 if (strncmp(info->pd_generic_name, "class,", 6) == 0) { 2594 /* no generic without "pccard" */ 2595 (void) sprintf(buff, "%s%s", PCMDEV_NAMEPREF, 2596 info->pd_generic_name); 2597 } else { 2598 /* first pccard,generic-name */ 2599 (void) sprintf(buff, "%s,%s", PCMDEV_NAMEPREF, 2600 info->pd_generic_name); 2601 } 2602 length = strlen(buff) + 1; 2603 compat_name[ci] = kmem_alloc(length, KM_SLEEP); 2604 (void) strcpy(compat_name[ci++], buff); 2605 2606 /* now the simple generic name */ 2607 length = strlen(info->pd_generic_name) + 1; 2608 compat_name[ci] = kmem_alloc(length, KM_SLEEP); 2609 (void) strcpy(compat_name[ci++], info->pd_generic_name); 2610 } 2611 2612 if (info->pd_flags & PCM_NO_CONFIG) { 2613 char *mem = "pccard,memory"; 2614 /* 2615 * I/O cards are required to have a config tuple. 2616 * there are some that violate the spec and don't 2617 * but it is most likely that this is a memory card 2618 * so tag it as such. "memory" is more general 2619 * than other things so needs to come last. 2620 */ 2621 length = strlen(mem) + 1; 2622 compat_name[ci] = kmem_alloc(length, KM_SLEEP); 2623 (void) strcpy(compat_name[ci++], mem); 2624 } 2625 2626 if (ci == 0) 2627 return; 2628 2629 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, 2630 "compatible", (char **)compat_name, ci) != DDI_PROP_SUCCESS) 2631 cmn_err(CE_WARN, "pcmcia: unable to create compatible prop"); 2632 2633 for (i = 0; i < ci; i++) 2634 kmem_free(compat_name[i], strlen(compat_name[i]) + 1); 2635 } 2636 /* 2637 * CIS parsing and other PC Card specific code 2638 */ 2639 2640 /* 2641 * pcmcia_get_mem_regs() 2642 */ 2643 static int 2644 pcmcia_get_mem_regs(struct pcm_regs *regs, struct pcm_device_info *info, 2645 int type, int pctype) 2646 { 2647 int num_regs = 0; 2648 tuple_t tuple; 2649 cistpl_device_t device; 2650 uint32_t curr_base; 2651 int ret, len; 2652 int space; 2653 2654 /* 2655 * current plan for reg spec: 2656 * device_a will be accumulated to determine max size of 2657 * attribute memory. device for common. Then config 2658 * tuples to get a worst case I/O size. 2659 */ 2660 bzero(&tuple, sizeof (tuple)); 2661 tuple.Socket = info->pd_socket; 2662 2663 tuple.DesiredTuple = (cisdata_t)type; 2664 2665 space = (type == CISTPL_DEVICE_A) ? PC_REG_SPACE_ATTRIBUTE : 2666 PC_REG_SPACE_MEMORY; 2667 if ((ret = csx_GetFirstTuple(info->pd_handle, &tuple)) == CS_SUCCESS) { 2668 bzero(&device, sizeof (device)); 2669 2670 if (type == CISTPL_DEVICE) 2671 ret = csx_Parse_CISTPL_DEVICE(info->pd_handle, &tuple, 2672 &device); 2673 else 2674 ret = csx_Parse_CISTPL_DEVICE_A(info->pd_handle, &tuple, 2675 &device); 2676 2677 if (ret == CS_SUCCESS) { 2678 curr_base = 0; 2679 for (ret = 0; ret < device.num_devices; 2680 ret++) { 2681 /* need to order these for real mem first */ 2682 if (device.devnode[ret].type != 2683 CISTPL_DEVICE_DTYPE_NULL) { 2684 /* how to represent types??? */ 2685 regs[num_regs].phys_hi = 2686 PC_REG_PHYS_HI(0, 0, 2687 pctype, 2688 space, 2689 info->pd_socket, 2690 info->pd_function, 2691 0); 2692 regs[num_regs].phys_lo = curr_base; 2693 len = device.devnode[ret].size_in_bytes; 2694 curr_base += len; 2695 regs[num_regs].phys_len = len; 2696 num_regs++; 2697 } else { 2698 /* 2699 * NULL device is a "hole" 2700 */ 2701 curr_base += 2702 device.devnode[ret].size_in_bytes; 2703 } 2704 } 2705 } 2706 } 2707 return (num_regs); 2708 } 2709 2710 /* 2711 * 2712 */ 2713 static int 2714 pcmcia_get_io_regs(struct pcm_regs *regs, struct pcm_device_info *info, 2715 int pctype) 2716 { 2717 int num_regs = 0; 2718 tuple_t tuple; 2719 uint32_t curr_base; 2720 int len, curr, i, curr_len; 2721 cistpl_config_t config; 2722 cistpl_cftable_entry_t cftable; 2723 struct pcm_regs tmp[16]; 2724 int found = 0; 2725 2726 bzero(&tuple, sizeof (tuple)); 2727 tuple.DesiredTuple = CISTPL_CONFIG; 2728 tuple.Socket = info->pd_socket; 2729 tuple.Attributes = 0; 2730 curr_base = 0; 2731 len = 0; 2732 2733 if (csx_GetFirstTuple(info->pd_handle, &tuple) == CS_SUCCESS) { 2734 if (csx_Parse_CISTPL_CONFIG(info->pd_handle, 2735 &tuple, &config) != CS_SUCCESS) { 2736 info->pd_flags |= PCM_NO_CONFIG; /* must be memory */ 2737 return (0); 2738 } 2739 curr = 0; 2740 2741 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 2742 tuple.Socket = info->pd_socket; 2743 tuple.Attributes = 0; 2744 bzero(tmp, sizeof (tmp)); 2745 while (csx_GetNextTuple(info->pd_handle, 2746 &tuple) == CS_SUCCESS) { 2747 bzero(&cftable, sizeof (cftable)); 2748 if (csx_Parse_CISTPL_CFTABLE_ENTRY(info->pd_handle, 2749 &tuple, &cftable) == 2750 CS_SUCCESS) { 2751 if (cftable.flags & CISTPL_CFTABLE_TPCE_FS_IO) { 2752 /* we have an I/O entry */ 2753 if (cftable.io.flags & 2754 CISTPL_CFTABLE_TPCE_FS_IO_RANGE) { 2755 len = cftable.io.addr_lines; 2756 if (len != 0) 2757 len = 1 << len; 2758 for (i = 0; i < cftable.io.ranges && curr < 16; i++) { 2759 curr_base = cftable.io.range[i].addr; 2760 curr_len = cftable.io.range[i].length; 2761 if (curr_len == 0) 2762 curr_len = len; 2763 if (len != 0 || cftable.io.addr_lines == 0) { 2764 /* we have potential relocation */ 2765 int mask; 2766 mask = cftable.io.addr_lines ? 2767 cftable.io.addr_lines : 2768 genp2(len); 2769 mask = genmask(mask); 2770 if ((mask & curr_base) == 0) { 2771 /* more accurate length */ 2772 regs->phys_len = curr_len; 2773 regs->phys_lo = 0; 2774 regs->phys_hi = 2775 PC_REG_PHYS_HI(0, 2776 0, 2777 pctype, 2778 PC_REG_SPACE_IO, 2779 info->pd_socket, 2780 info->pd_function, 2781 0); 2782 num_regs++; 2783 found = 2; 2784 break; 2785 } 2786 } 2787 tmp[curr].phys_len = curr_len; 2788 tmp[curr].phys_lo = curr_base; 2789 curr++; 2790 found = 1; 2791 } 2792 if (found == 2) 2793 break; 2794 } else { 2795 /* no I/O range so just a mask */ 2796 regs->phys_len = 1 << cftable.io.addr_lines; 2797 regs->phys_hi = 2798 PC_REG_PHYS_HI(0, 2799 0, 2800 pctype, 2801 PC_REG_SPACE_IO, 2802 info->pd_socket, 2803 info->pd_function, 2804 0); 2805 regs->phys_lo = 0; 2806 num_regs++; 2807 regs++; 2808 /* quit on "good" entry */ 2809 break; 2810 } 2811 /* was this the last CFTABLE Entry? */ 2812 if (config.last == cftable.index) 2813 break; 2814 } 2815 } 2816 } 2817 if (found == 1) { 2818 /* 2819 * have some non-relocatable values 2820 * so we include them all for now 2821 */ 2822 for (i = 0; i < curr && num_regs < 8; i++) { 2823 regs->phys_len = tmp[i].phys_len; 2824 regs->phys_lo = tmp[i].phys_lo; 2825 regs->phys_hi = PC_REG_PHYS_HI(1, 0, pctype, 2826 PC_REG_SPACE_IO, info->pd_socket, 2827 info->pd_function, 0); 2828 regs++; 2829 num_regs++; 2830 } 2831 } 2832 } 2833 return (num_regs); 2834 } 2835 2836 /* 2837 * pcmcia_create_regs() 2838 * create a valid set of regspecs for the card 2839 * The first one is always for CIS access and naming 2840 */ 2841 /*ARGSUSED*/ 2842 static void 2843 pcmcia_find_regs(dev_info_t *dip, struct pcm_device_info *info, 2844 struct pcmcia_parent_private *ppd) 2845 { 2846 struct pcm_regs regs[32]; /* assume worst case */ 2847 int num_regs = 0; 2848 int len; 2849 int bustype; 2850 2851 if (ppd->ppd_flags & PPD_CARD_CARDBUS) { 2852 /* always have a CIS map */ 2853 regs[0].phys_hi = PC_REG_PHYS_HI(0, 0, PC_REG_TYPE_CARDBUS, 2854 PC_REG_SPACE_CONFIG, 2855 info->pd_socket, 2856 info->pd_function, 0); 2857 bustype = PC_REG_TYPE_CARDBUS; 2858 } else { 2859 /* always have a CIS map */ 2860 regs[0].phys_hi = PC_REG_PHYS_HI(0, 0, PC_REG_TYPE_16BIT, 2861 PC_REG_SPACE_ATTRIBUTE, 2862 info->pd_socket, 2863 info->pd_function, 0); 2864 bustype = PC_REG_TYPE_16BIT; 2865 } 2866 regs[0].phys_lo = 0; /* always starts at zero */ 2867 regs[0].phys_len = 0; 2868 num_regs++; 2869 /* 2870 * need to search CIS for other memory instances 2871 */ 2872 2873 if (info->pd_flags & PCM_OTHER_NOCIS) { 2874 /* special case of memory only card without CIS */ 2875 regs[1].phys_hi = PC_REG_PHYS_HI(0, 0, PC_REG_TYPE_16BIT, 2876 PC_REG_SPACE_MEMORY, 2877 info->pd_socket, 2878 info->pd_function, 0); 2879 regs[1].phys_lo = 0; 2880 regs[1].phys_len = PCM_MAX_R2_MEM; 2881 num_regs++; 2882 } else { 2883 /* 2884 * want to get any other memory and/or I/O regions 2885 * on the card and represent them here. 2886 */ 2887 num_regs += pcmcia_get_mem_regs(®s[num_regs], info, 2888 CISTPL_DEVICE_A, bustype); 2889 num_regs += pcmcia_get_mem_regs(®s[num_regs], info, 2890 CISTPL_DEVICE, bustype); 2891 2892 /* now look for an I/O space to configure */ 2893 num_regs += pcmcia_get_io_regs(®s[num_regs], info, 2894 bustype); 2895 2896 } 2897 2898 len = num_regs * sizeof (uint32_t) * 3; 2899 ppd->ppd_nreg = num_regs; 2900 ppd->ppd_reg = kmem_alloc(len, KM_SLEEP); 2901 bcopy(regs, ppd->ppd_reg, len); 2902 len = sizeof (struct pcm_regs) * ppd->ppd_nreg; 2903 ppd->ppd_assigned = kmem_zalloc(len, KM_SLEEP); 2904 } 2905 2906 2907 /* 2908 * pcmcia_need_intr() 2909 * check to see if an interrupt tuple exists. 2910 * existence means we need one in the intrspec. 2911 */ 2912 static int 2913 pcmcia_need_intr(int socket, struct pcm_device_info *info) 2914 { 2915 cistpl_config_t config; 2916 cistpl_cftable_entry_t cftable; 2917 tuple_t tuple; 2918 int i; 2919 2920 bzero(&tuple, sizeof (tuple)); 2921 tuple.DesiredTuple = CISTPL_CONFIG; 2922 tuple.Socket = socket; 2923 tuple.Attributes = 0; 2924 if (csx_GetFirstTuple(info->pd_handle, &tuple) != CS_SUCCESS) { 2925 return (0); 2926 } 2927 #if defined(PCMCIA_DEBUG) 2928 if (pcmcia_debug) { 2929 cmn_err(CE_CONT, "pcmcia_need_intr: have config tuple\n"); 2930 } 2931 #endif 2932 bzero(&config, sizeof (config)); 2933 if (csx_Parse_CISTPL_CONFIG(info->pd_handle, 2934 &tuple, &config) != CS_SUCCESS) { 2935 cmn_err(CE_WARN, "pcmcia: config failed to parse\n"); 2936 return (0); 2937 } 2938 2939 for (cftable.index = (int)-1, i = -1; 2940 i != config.last; i = cftable.index) { 2941 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 2942 tuple.Attributes = 0; 2943 if (csx_GetNextTuple(info->pd_handle, 2944 &tuple) != CS_SUCCESS) { 2945 cmn_err(CE_WARN, "pcmcia: get cftable failed\n"); 2946 break; 2947 } 2948 bzero(&cftable, sizeof (cftable)); 2949 if (csx_Parse_CISTPL_CFTABLE_ENTRY(info->pd_handle, 2950 &tuple, &cftable) != 2951 CS_SUCCESS) { 2952 cmn_err(CE_WARN, "pcmcia: parse cftable failed\n"); 2953 break; 2954 } 2955 #if defined(PCMCIA_DEBUG) 2956 if (pcmcia_debug) 2957 cmn_err(CE_CONT, "\t%x: flags=%x (%x)\n", 2958 i, cftable.flags, 2959 cftable.flags & CISTPL_CFTABLE_TPCE_FS_IRQ); 2960 #endif 2961 if (cftable.flags & CISTPL_CFTABLE_TPCE_FS_IRQ) 2962 return (1); 2963 } 2964 return (0); 2965 2966 } 2967 2968 /* 2969 * pcmcia_num_funcs() 2970 * look for a CISTPL_LONGLINK_MFC 2971 * if there is one, return the number of functions 2972 * if there isn't one, then there is one function 2973 */ 2974 static int 2975 pcmcia_num_funcs(int socket, client_handle_t handle) 2976 { 2977 int count = 1; 2978 cistpl_longlink_mfc_t mfc; 2979 tuple_t tuple; 2980 2981 bzero(&tuple, sizeof (tuple_t)); 2982 tuple.DesiredTuple = CISTPL_LONGLINK_MFC; 2983 tuple.Socket = socket; 2984 tuple.Attributes = 0; 2985 if (csx_GetFirstTuple(handle, &tuple) == CS_SUCCESS) { 2986 /* this is a multifunction card */ 2987 if (csx_ParseTuple(handle, &tuple, (cisparse_t *)&mfc, 2988 CISTPL_LONGLINK_MFC) == CS_SUCCESS) { 2989 count = mfc.nfuncs; 2990 } 2991 } 2992 return (count); 2993 } 2994 2995 client_handle_t pcmcia_cs_handle; 2996 2997 /* 2998 * pcmcia_create_dev_info(socket) 2999 * either find or create the device information structure 3000 * for the card(s) just inserted. We don't care about removal yet. 3001 * In any case, we will only do this at CS request 3002 */ 3003 static void 3004 pcmcia_create_dev_info(int socket) 3005 { 3006 struct pcm_device_info card_info; 3007 client_reg_t reg; 3008 cisinfo_t cisinfo; 3009 int i; 3010 dev_info_t *pdip; 3011 static int handle_def = 0; 3012 3013 #if defined(PCMCIA_DEBUG) 3014 if (pcmcia_debug) 3015 cmn_err(CE_CONT, "create dev_info_t for device in socket %d\n", 3016 socket); 3017 #endif 3018 3019 /* 3020 * before we can do anything else, we need the parent 3021 * devinfo of the socket. This gets things in the right 3022 * place in the device tree. 3023 */ 3024 3025 pdip = pcm_find_parent_dip(socket); 3026 if (pdip == NULL) 3027 return; 3028 3029 /* Card Services calls needed to get CIS info */ 3030 reg.dip = NULL; 3031 reg.Attributes = INFO_SOCKET_SERVICES; 3032 reg.EventMask = 0; 3033 reg.event_handler = NULL; 3034 reg.Version = CS_VERSION; 3035 3036 bzero(&card_info, sizeof (card_info)); 3037 3038 if (handle_def == 0) { 3039 if (csx_RegisterClient(&pcmcia_cs_handle, 3040 ®) != CS_SUCCESS) { 3041 #if defined(PCMCIA_DEBUG) 3042 if (pcmcia_debug) 3043 cmn_err(CE_CONT, 3044 "pcmcia: RegisterClient failed\n"); 3045 #endif 3046 return; 3047 } 3048 handle_def++; 3049 } 3050 card_info.pd_handle = pcmcia_cs_handle; 3051 3052 #if defined(PCMCIA_DEBUG) 3053 if (pcmcia_debug) 3054 cmn_err(CE_CONT, 3055 "pcmcia_create_dev_info: handle = %x\n", 3056 (int)card_info.pd_handle); 3057 #endif 3058 card_info.pd_type = -1; /* no type to start */ 3059 card_info.pd_socket = socket; 3060 card_info.pd_function = 0; 3061 pcmcia_sockets[socket]->ls_functions = 1; /* default */ 3062 3063 cisinfo.Socket = socket; 3064 3065 if ((i = csx_ValidateCIS(card_info.pd_handle, 3066 &cisinfo)) != SUCCESS || 3067 cisinfo.Tuples == 0) { 3068 /* no CIS means memory */ 3069 (void) strcpy(card_info.pd_generic_name, "memory"); 3070 card_info.pd_flags |= PCM_NAME_GENERIC | 3071 PCM_OTHER_NOCIS | PCM_NAME_1275; 3072 (void) strcpy(card_info.pd_bind_name, "pccard,memory"); 3073 (void) strcpy(card_info.pd_generic_name, "memory"); 3074 card_info.pd_type = PCM_TYPE_MEMORY; 3075 } else { 3076 int functions, lsocket; 3077 card_info.pd_tuples = cisinfo.Tuples; 3078 3079 /* 3080 * how many functions on the card? 3081 * we need to know and then we do one 3082 * child node for each function using 3083 * the function specific tuples. 3084 */ 3085 lsocket = CS_MAKE_SOCKET_NUMBER(socket, CS_GLOBAL_CIS); 3086 functions = pcmcia_num_funcs(lsocket, 3087 card_info.pd_handle); 3088 pcmcia_sockets[socket]->ls_functions = functions; 3089 if (functions > 1) { 3090 card_info.pd_flags |= PCM_MULTI_FUNCTION; 3091 } 3092 for (i = 0; i < functions; i++) { 3093 register int flags; 3094 lsocket = CS_MAKE_SOCKET_NUMBER(socket, i); 3095 card_info.pd_socket = socket; 3096 card_info.pd_function = i; 3097 /* 3098 * new name construction 3099 */ 3100 if (functions != 1) { 3101 /* need per function handle */ 3102 card_info.pd_function = i; 3103 /* get new handle */ 3104 } 3105 pcmcia_1275_name(lsocket, &card_info, 3106 card_info.pd_handle); 3107 pcmcia_vers1_name(lsocket, &card_info, 3108 card_info.pd_handle); 3109 pcmcia_generic_name(lsocket, &card_info, 3110 card_info.pd_handle); 3111 flags = card_info.pd_flags; 3112 if (!(flags & PCM_NAME_1275)) { 3113 if (flags & PCM_NAME_VERS1) { 3114 (void) strcpy(card_info.pd_bind_name, 3115 PCMDEV_NAMEPREF); 3116 card_info.pd_bind_name[sizeof (PCMDEV_NAMEPREF)] = 3117 ','; 3118 (void) strncpy(card_info.pd_bind_name + 3119 sizeof (PCMDEV_NAMEPREF), 3120 card_info.pd_vers1_name, 3121 MODMAXNAMELEN - 3122 sizeof (PCMDEV_NAMEPREF)); 3123 pcmcia_fix_string(card_info.pd_bind_name); 3124 } else { 3125 /* 3126 * have a CIS but not the right info 3127 * so treat as generic "pccard" 3128 */ 3129 (void) strcpy(card_info.pd_generic_name, 3130 "pccard,memory"); 3131 card_info.pd_flags |= PCM_NAME_GENERIC; 3132 (void) strcpy(card_info.pd_bind_name, 3133 "pccard,memory"); 3134 } 3135 } 3136 pcmcia_init_devinfo(pdip, &card_info); 3137 } 3138 return; 3139 } 3140 3141 pcmcia_init_devinfo(pdip, &card_info); 3142 } 3143 3144 /* 3145 * pcmcia_init_devinfo() 3146 * if there isn't a device info structure, create one 3147 * if there is, we don't do much. 3148 * 3149 * Note: this will need updating as 1275 finalizes their spec. 3150 */ 3151 static void 3152 pcmcia_init_devinfo(dev_info_t *pdip, struct pcm_device_info *info) 3153 { 3154 int unit; 3155 dev_info_t *dip; 3156 char *name; 3157 struct pcmcia_parent_private *ppd; 3158 3159 #if defined(PCMCIA_DEBUG) 3160 if (pcmcia_debug) 3161 cmn_err(CE_CONT, "init_devinfo(%s, %d)\n", info->pd_bind_name, 3162 info->pd_socket); 3163 #endif 3164 3165 /* 3166 * find out if there is already an instance of this 3167 * device. We don't want to create a new one unnecessarily 3168 */ 3169 unit = CS_MAKE_SOCKET_NUMBER(info->pd_socket, info->pd_function); 3170 3171 dip = pcm_find_devinfo(pdip, info, unit); 3172 if ((dip != NULL) && (ddi_getprop(DDI_DEV_T_NONE, dip, 3173 DDI_PROP_DONTPASS, PCM_DEV_SOCKET, -1) != -1)) { 3174 /* it already exist but isn't a .conf file */ 3175 3176 #if defined(PCMCIA_DEBUG) 3177 if (pcmcia_debug) 3178 cmn_err(CE_CONT, "\tfound existing device node (%s)\n", 3179 ddi_get_name(dip)); 3180 #endif 3181 if (strlen(info->pd_vers1_name) > 0) 3182 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 3183 dip, PCM_DEV_MODEL, info->pd_vers1_name); 3184 3185 ppd = (struct pcmcia_parent_private *) 3186 ddi_get_parent_data(dip); 3187 3188 pcmcia_sockets[info->pd_socket]->ls_dip[info->pd_function] = 3189 dip; 3190 3191 ppd->ppd_active = 1; 3192 3193 if (ndi_devi_online(dip, 0) == NDI_FAILURE) { 3194 pcmcia_sockets[info->pd_socket]-> \ 3195 ls_dip[info->pd_function] = NULL; 3196 ppd->ppd_active = 0; 3197 } 3198 } else { 3199 3200 char *dtype; 3201 3202 #if defined(PCMCIA_DEBUG) 3203 if (pcmcia_debug) 3204 cmn_err(CE_CONT, "pcmcia: create child [%s](%d): %s\n", 3205 info->pd_bind_name, info->pd_socket, 3206 info->pd_generic_name); 3207 #endif 3208 3209 if (info->pd_flags & PCM_NAME_GENERIC) 3210 name = info->pd_generic_name; 3211 else 3212 name = info->pd_bind_name; 3213 3214 if (ndi_devi_alloc(pdip, name, (pnode_t)DEVI_SID_NODEID, 3215 &dip) != 3216 NDI_SUCCESS) { 3217 cmn_err(CE_WARN, 3218 "pcmcia: unable to create device [%s](%d)\n", 3219 name, info->pd_socket); 3220 return; 3221 } 3222 /* 3223 * construct the "compatible" property if the device 3224 * has a generic name 3225 */ 3226 pcmcia_add_compatible(dip, info); 3227 3228 ppd = kmem_zalloc(sizeof (struct pcmcia_parent_private), 3229 KM_SLEEP); 3230 3231 ppd->ppd_socket = info->pd_socket; 3232 ppd->ppd_function = info->pd_function; 3233 3234 /* 3235 * add the "socket" property 3236 * the value of this property contains the logical PCMCIA 3237 * socket number the device has been inserted in, along 3238 * with the function # if the device is part of a 3239 * multi-function device. 3240 */ 3241 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 3242 PCM_DEV_SOCKET, unit); 3243 3244 if (info->pd_flags & PCM_MULTI_FUNCTION) 3245 ppd->ppd_flags |= PPD_CARD_MULTI; 3246 3247 /* 3248 * determine all the properties we need for PPD 3249 * then create the properties 3250 */ 3251 /* socket is unique */ 3252 pcmcia_find_regs(dip, info, ppd); 3253 3254 ppd->ppd_intr = pcmcia_need_intr(unit, info); 3255 3256 if (ppd->ppd_nreg > 0) 3257 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, 3258 "reg", (int *)ppd->ppd_reg, ppd->ppd_nreg * 3259 sizeof (struct pcm_regs) / sizeof (int)); 3260 if (ppd->ppd_intr) { 3261 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, 3262 "interrupts", ppd->ppd_intr); 3263 ppd->ppd_intrspec = 3264 kmem_zalloc(sizeof (struct intrspec), KM_SLEEP); 3265 } 3266 3267 /* set parent private - our own format */ 3268 ddi_set_parent_data(dip, (caddr_t)ppd); 3269 3270 /* init the device type */ 3271 if (info->pd_type >= 0 && 3272 info->pd_type < (sizeof (pcmcia_dev_type) / 3273 (sizeof (char *)))) 3274 dtype = pcmcia_dev_type[info->pd_type]; 3275 else 3276 dtype = "unknown"; 3277 3278 if (strlen(info->pd_vers1_name) > 0) 3279 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 3280 dip, PCM_DEV_MODEL, info->pd_vers1_name); 3281 3282 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 3283 PCM_DEVICETYPE, dtype); 3284 3285 /* set PC Card as active and present in socket */ 3286 pcmcia_sockets[info->pd_socket]->ls_dip[info->pd_function] = 3287 dip; 3288 3289 ppd->ppd_active = 1; 3290 3291 /* 3292 * We should not call ndi_devi_online here if 3293 * pcmcia attach is in progress. This causes a deadlock. 3294 */ 3295 if (pcmcia_dip != dip) { 3296 if (ndi_devi_online_async(dip, 0) 3297 != NDI_SUCCESS) { 3298 pcmcia_sockets[info->pd_socket]->\ 3299 ls_dip[info->pd_function] = NULL; 3300 pcmcia_ppd_free(ppd); 3301 (void) ndi_devi_free(dip); 3302 return; 3303 } 3304 } 3305 3306 #if defined(PCMCIA_DEBUG) 3307 if (pcmcia_debug) 3308 cmn_err(CE_CONT, "\tjust added \"active\" to %s in %d\n", 3309 ddi_get_name(dip), info->pd_socket); 3310 #endif 3311 } 3312 3313 /* 3314 * inform the event manager that a child was added 3315 * to the device tree. 3316 */ 3317 pcm_event_manager(PCE_DEV_IDENT, unit, ddi_get_name(dip)); 3318 3319 #if defined(PCMCIA_DEBUG) 3320 if (pcmcia_debug > 1) { 3321 pcmcia_dump_minors(dip); 3322 } 3323 #endif 3324 } 3325 3326 /* 3327 * free any allocated parent-private data 3328 */ 3329 static void 3330 pcmcia_ppd_free(struct pcmcia_parent_private *ppd) 3331 { 3332 size_t len; 3333 3334 if (ppd->ppd_nreg != 0) { 3335 len = ppd->ppd_nreg * sizeof (uint32_t) * 3; 3336 kmem_free(ppd->ppd_reg, len); 3337 len = sizeof (struct pcm_regs) * ppd->ppd_nreg; 3338 kmem_free(ppd->ppd_assigned, len); 3339 } 3340 3341 /* 3342 * pcmcia only allocates 1 intrspec today 3343 */ 3344 if (ppd->ppd_intr != 0) { 3345 len = sizeof (struct intrspec) * ppd->ppd_intr; 3346 kmem_free(ppd->ppd_intrspec, len); 3347 } 3348 3349 kmem_free(ppd, sizeof (*ppd)); 3350 } 3351 3352 3353 /* 3354 * pcmcia_get_devinfo(socket) 3355 * entry point to allow finding the device info structure 3356 * for a given logical socket. Used by event manager 3357 */ 3358 dev_info_t * 3359 pcmcia_get_devinfo(int socket) 3360 { 3361 int func = CS_GET_FUNCTION_NUMBER(socket); 3362 socket = CS_GET_SOCKET_NUMBER(socket); 3363 if (pcmcia_sockets[socket]) 3364 return (pcmcia_sockets[socket]->ls_dip[func]); 3365 return ((dev_info_t *)NULL); 3366 } 3367 3368 /* 3369 * CSGetCookiesAndDip() 3370 * get info needed by CS to setup soft interrupt handler and provide 3371 * socket-specific adapter information 3372 */ 3373 static int 3374 GetCookiesAndDip(sservice_t *serv) 3375 { 3376 pcmcia_logical_socket_t *socket; 3377 csss_adapter_info_t *ai; 3378 int sock; 3379 3380 sock = CS_GET_SOCKET_NUMBER(serv->get_cookies.socket); 3381 3382 if (sock >= pcmcia_num_sockets || 3383 (int)serv->get_cookies.socket < 0) 3384 return (BAD_SOCKET); 3385 3386 socket = pcmcia_sockets[sock]; 3387 ai = &serv->get_cookies.adapter_info; 3388 serv->get_cookies.dip = socket->ls_adapter->pca_dip; 3389 serv->get_cookies.iblock = socket->ls_adapter->pca_iblock; 3390 serv->get_cookies.idevice = socket->ls_adapter->pca_idev; 3391 3392 /* 3393 * Setup the adapter info for Card Services 3394 */ 3395 (void) strcpy(ai->name, socket->ls_adapter->pca_name); 3396 ai->major = socket->ls_adapter->pca_module; 3397 ai->minor = socket->ls_adapter->pca_unit; 3398 ai->number = socket->ls_adapter->pca_number; 3399 ai->num_sockets = socket->ls_adapter->pca_numsockets; 3400 ai->first_socket = socket->ls_adapter->pca_first_socket; 3401 3402 return (SUCCESS); 3403 } 3404 3405 /* 3406 * Note: 3407 * The following functions that start with 'SS' 3408 * implement SocketServices interfaces. They 3409 * simply map the socket and/or window number to 3410 * the adapter specific number based on the general 3411 * value that CardServices uses. 3412 * 3413 * See the descriptions in SocketServices for 3414 * details. Also refer to specific adapter drivers 3415 * for implementation reference. 3416 */ 3417 3418 static int 3419 SSGetAdapter(get_adapter_t *adapter) 3420 { 3421 int n; 3422 get_adapter_t info; 3423 3424 adapter->state = (unsigned)0xFFFFFFFF; 3425 adapter->SCRouting = 0xFFFFFFFF; 3426 3427 for (n = 0; n < pcmcia_num_adapters; n++) { 3428 GET_ADAPTER(pcmcia_adapters[n]->pca_if, 3429 pcmcia_adapters[n]->pca_dip, &info); 3430 adapter->state &= info.state; 3431 adapter->SCRouting &= info.SCRouting; 3432 } 3433 3434 return (SUCCESS); 3435 } 3436 3437 static int 3438 SSGetPage(get_page_t *page) 3439 { 3440 pcmcia_logical_window_t *window; 3441 get_page_t newpage; 3442 int retval, win; 3443 3444 if (page->window > pcmcia_num_windows) { 3445 return (BAD_WINDOW); 3446 } 3447 3448 window = pcmcia_windows[page->window]; 3449 newpage = *page; 3450 win = newpage.window = window->lw_window; /* real window */ 3451 3452 retval = GET_PAGE(window->lw_if, window->lw_adapter->pca_dip, 3453 &newpage); 3454 if (retval == SUCCESS) { 3455 *page = newpage; 3456 page->window = win; 3457 } 3458 return (retval); 3459 } 3460 3461 static int 3462 SSGetSocket(get_socket_t *socket) 3463 { 3464 int retval, sock; 3465 get_socket_t newsocket; 3466 pcmcia_logical_socket_t *sockp; 3467 3468 sock = socket->socket; 3469 if (sock > pcmcia_num_sockets || 3470 (sockp = pcmcia_sockets[sock]) == NULL) { 3471 return (BAD_SOCKET); 3472 } 3473 3474 newsocket = *socket; 3475 newsocket.socket = sockp->ls_socket; 3476 retval = GET_SOCKET(sockp->ls_if, sockp->ls_adapter->pca_dip, 3477 &newsocket); 3478 if (retval == SUCCESS) { 3479 newsocket.VccLevel = pcmcia_map_power_get(sockp->ls_adapter, 3480 newsocket.VccLevel, 3481 VCC); 3482 newsocket.Vpp1Level = pcmcia_map_power_get(sockp->ls_adapter, 3483 newsocket.Vpp1Level, 3484 VPP1); 3485 newsocket.Vpp2Level = pcmcia_map_power_get(sockp->ls_adapter, 3486 newsocket.Vpp2Level, 3487 VPP2); 3488 *socket = newsocket; 3489 socket->socket = sock; 3490 } 3491 3492 return (retval); 3493 } 3494 3495 static int 3496 SSGetStatus(get_ss_status_t *status) 3497 { 3498 get_ss_status_t newstat; 3499 int sock, retval; 3500 pcmcia_logical_socket_t *sockp; 3501 3502 sock = status->socket; 3503 if (sock > pcmcia_num_sockets || 3504 (sockp = pcmcia_sockets[sock]) == NULL) { 3505 return (BAD_SOCKET); 3506 } 3507 3508 newstat = *status; 3509 newstat.socket = sockp->ls_socket; 3510 retval = GET_STATUS(sockp->ls_if, sockp->ls_adapter->pca_dip, 3511 &newstat); 3512 if (retval == SUCCESS) { 3513 *status = newstat; 3514 status->socket = sock; 3515 } 3516 3517 return (retval); 3518 } 3519 3520 static int 3521 SSGetWindow(get_window_t *window) 3522 { 3523 int win, retval; 3524 get_window_t newwin; 3525 pcmcia_logical_window_t *winp; 3526 3527 win = window->window; 3528 winp = pcmcia_windows[win]; 3529 newwin = *window; 3530 newwin.window = winp->lw_window; 3531 3532 retval = GET_WINDOW(winp->lw_if, winp->lw_adapter->pca_dip, 3533 &newwin); 3534 if (retval == SUCCESS) { 3535 newwin.socket = winp->lw_socket; 3536 newwin.window = win; 3537 *window = newwin; 3538 } 3539 return (retval); 3540 } 3541 3542 /* 3543 * SSInquireAdapter() 3544 * Get the capabilities of the "generic" adapter 3545 * we are exporting to CS. 3546 */ 3547 static int 3548 SSInquireAdapter(inquire_adapter_t *adapter) 3549 { 3550 adapter->NumSockets = pcmcia_num_sockets; 3551 adapter->NumWindows = pcmcia_num_windows; 3552 adapter->NumEDCs = 0; 3553 /* 3554 * notes: Adapter Capabilities are going to be difficult to 3555 * determine with reliability. Fortunately, most of them 3556 * don't matter under Solaris or can be handled transparently 3557 */ 3558 adapter->AdpCaps = 0; /* need to fix these */ 3559 /* 3560 * interrupts need a little work. For x86, the valid IRQs will 3561 * be restricted to those that the system has exported to the nexus. 3562 * for SPARC, it will be the DoRight values. 3563 */ 3564 adapter->ActiveHigh = 0; 3565 adapter->ActiveLow = 0; 3566 adapter->power_entry = pcmcia_power_table; /* until we resolve this */ 3567 adapter->NumPower = pcmcia_num_power; 3568 return (SUCCESS); 3569 } 3570 3571 static int 3572 SSInquireSocket(inquire_socket_t *socket) 3573 { 3574 int retval, sock; 3575 inquire_socket_t newsocket; 3576 pcmcia_logical_socket_t *sockp; 3577 3578 sock = socket->socket; 3579 if (sock > pcmcia_num_sockets || 3580 (sockp = pcmcia_sockets[sock]) == NULL) 3581 return (BAD_SOCKET); 3582 newsocket = *socket; 3583 newsocket.socket = sockp->ls_socket; 3584 retval = INQUIRE_SOCKET(sockp->ls_if, sockp->ls_adapter->pca_dip, 3585 &newsocket); 3586 if (retval == SUCCESS) { 3587 *socket = newsocket; 3588 socket->socket = sock; 3589 } 3590 return (retval); 3591 } 3592 3593 static int 3594 SSInquireWindow(inquire_window_t *window) 3595 { 3596 int retval, win; 3597 pcmcia_logical_window_t *winp; 3598 inquire_window_t newwin; 3599 int slide; 3600 3601 win = window->window; 3602 if (win > pcmcia_num_windows) 3603 return (BAD_WINDOW); 3604 3605 winp = pcmcia_windows[win]; 3606 newwin = *window; 3607 newwin.window = winp->lw_window; 3608 retval = INQUIRE_WINDOW(winp->lw_if, winp->lw_adapter->pca_dip, 3609 &newwin); 3610 #if defined(PCMCIA_DEBUG) 3611 if (pcmcia_debug > 1) 3612 cmn_err(CE_CONT, "SSInquireWindow: win=%d, pwin=%d\n", 3613 win, newwin.window); 3614 #endif 3615 if (retval == SUCCESS) { 3616 *window = newwin; 3617 /* just in case */ 3618 window->iowin_char.IOWndCaps &= ~WC_BASE; 3619 slide = winp->lw_adapter->pca_first_socket; 3620 /* 3621 * note that sockets are relative to the adapter. 3622 * we have to adjust the bits to show a logical 3623 * version. 3624 */ 3625 3626 pcm_fix_bits(newwin.Sockets, window->Sockets, slide, 0); 3627 3628 #if defined(PCMCIA_DEBUG) 3629 if (pcmcia_debug > 1) { 3630 cmn_err(CE_CONT, "iw: orig bits=%x, new bits=%x\n", 3631 (int)*(uint32_t *)newwin.Sockets, 3632 (int)*(uint32_t *)window->Sockets); 3633 cmn_err(CE_CONT, "\t%x.%x.%x\n", window->WndCaps, 3634 window->mem_win_char.MemWndCaps, 3635 window->mem_win_char.MinSize); 3636 } 3637 #endif 3638 window->window = win; 3639 } 3640 return (retval); 3641 } 3642 3643 static int 3644 SSResetSocket(int socket, int mode) 3645 { 3646 pcmcia_logical_socket_t *sockp; 3647 3648 if (socket >= pcmcia_num_sockets || 3649 (sockp = pcmcia_sockets[socket]) == NULL) 3650 return (BAD_SOCKET); 3651 3652 return (RESET_SOCKET(sockp->ls_if, sockp->ls_adapter->pca_dip, 3653 sockp->ls_socket, mode)); 3654 } 3655 3656 static int 3657 SSSetPage(set_page_t *page) 3658 { 3659 int window, retval; 3660 set_page_t newpage; 3661 pcmcia_logical_window_t *winp; 3662 3663 window = page->window; 3664 if (window > pcmcia_num_windows) { 3665 #if defined(PCMCIA_DEBUG) 3666 if (pcmcia_debug > 1) 3667 cmn_err(CE_CONT, "SSSetPage: window=%d (of %d)\n", 3668 window, pcmcia_num_windows); 3669 #endif 3670 return (BAD_WINDOW); 3671 } 3672 3673 winp = pcmcia_windows[window]; 3674 newpage = *page; 3675 newpage.window = winp->lw_window; 3676 retval = SET_PAGE(winp->lw_if, winp->lw_adapter->pca_dip, &newpage); 3677 if (retval == SUCCESS) { 3678 newpage.window = window; 3679 *page = newpage; 3680 } 3681 #if defined(PCMCIA_DEBUG) 3682 if ((pcmcia_debug > 1) && retval != SUCCESS) 3683 cmn_err(CE_CONT, "\tSetPage: returning error %x\n", retval); 3684 #endif 3685 return (retval); 3686 } 3687 3688 static int 3689 SSSetWindow(set_window_t *win) 3690 { 3691 int socket, window, retval, func; 3692 set_window_t newwin; 3693 pcmcia_logical_window_t *winp; 3694 pcmcia_logical_socket_t *sockp; 3695 3696 window = win->window; 3697 if (window > pcmcia_num_windows) 3698 return (BAD_WINDOW); 3699 3700 socket = CS_GET_SOCKET_NUMBER(win->socket); 3701 func = CS_GET_FUNCTION_NUMBER(win->socket); 3702 3703 if (socket > pcmcia_num_sockets || 3704 (sockp = pcmcia_sockets[socket]) == NULL) { 3705 return (BAD_SOCKET); 3706 } 3707 3708 winp = pcmcia_windows[window]; 3709 winp->lw_socket = win->socket; /* reverse map */ 3710 newwin = *win; 3711 newwin.window = winp->lw_window; 3712 newwin.socket = sockp->ls_socket; 3713 newwin.child = sockp->ls_dip[func]; /* so we carry the dip around */ 3714 3715 retval = SET_WINDOW(winp->lw_if, winp->lw_adapter->pca_dip, &newwin); 3716 if (retval == SUCCESS) { 3717 newwin.window = window; 3718 newwin.socket = winp->lw_socket; 3719 *win = newwin; 3720 } 3721 return (retval); 3722 } 3723 3724 static int 3725 SSSetSocket(set_socket_t *socket) 3726 { 3727 int sock, retval; 3728 pcmcia_logical_socket_t *sockp; 3729 set_socket_t newsock; 3730 3731 sock = socket->socket; 3732 if (sock > pcmcia_num_sockets || 3733 (sockp = pcmcia_sockets[sock]) == NULL) { 3734 return (BAD_SOCKET); 3735 } 3736 3737 newsock = *socket; 3738 /* note: we force CS to always get insert/removal events */ 3739 sockp->ls_cs_events = pcm_mapevents(newsock.SCIntMask) | 3740 PCE_E2M(PCE_CARD_INSERT) | PCE_E2M(PCE_CARD_REMOVAL); 3741 #if defined(PCMCIA_DEBUG) 3742 if (pcmcia_debug > 1) 3743 cmn_err(CE_CONT, 3744 "SetSocket: SCIntMask = %x\n", newsock.SCIntMask); 3745 #endif 3746 newsock.socket = sockp->ls_socket; 3747 newsock.VccLevel = pcmcia_map_power_set(sockp->ls_adapter, 3748 newsock.VccLevel, VCC); 3749 newsock.Vpp1Level = pcmcia_map_power_set(sockp->ls_adapter, 3750 newsock.Vpp1Level, VPP1); 3751 newsock.Vpp2Level = pcmcia_map_power_set(sockp->ls_adapter, 3752 newsock.Vpp2Level, VPP2); 3753 retval = SET_SOCKET(sockp->ls_if, sockp->ls_adapter->pca_dip, 3754 &newsock); 3755 if (retval == SUCCESS) { 3756 newsock.socket = sock; 3757 newsock.VccLevel = pcmcia_map_power_get(sockp->ls_adapter, 3758 newsock.VccLevel, 3759 VCC); 3760 newsock.Vpp1Level = pcmcia_map_power_get(sockp->ls_adapter, 3761 newsock.Vpp1Level, 3762 VPP1); 3763 newsock.Vpp2Level = pcmcia_map_power_get(sockp->ls_adapter, 3764 newsock.Vpp2Level, 3765 VPP2); 3766 *socket = newsock; 3767 if (socket->IREQRouting & IRQ_ENABLE) { 3768 sockp->ls_flags |= PCS_IRQ_ENABLED; 3769 } else { 3770 sockp->ls_flags &= ~PCS_IRQ_ENABLED; 3771 } 3772 } 3773 return (retval); 3774 } 3775 3776 /* 3777 * SSSetIRQHandler() 3778 * arrange for IRQ to be allocated if appropriate and always 3779 * arrange that PC Card interrupt handlers get called. 3780 */ 3781 static int 3782 SSSetIRQHandler(set_irq_handler_t *handler) 3783 { 3784 int sock, retval, func; 3785 pcmcia_logical_socket_t *sockp; 3786 struct pcmcia_parent_private *ppd; 3787 dev_info_t *dip; 3788 ddi_iblock_cookie_t iblk; 3789 ddi_idevice_cookie_t idev; 3790 3791 sock = CS_GET_SOCKET_NUMBER(handler->socket); 3792 func = CS_GET_FUNCTION_NUMBER(handler->socket); 3793 if (sock > pcmcia_num_sockets || 3794 (sockp = pcmcia_sockets[sock]) == NULL) { 3795 return (BAD_SOCKET); 3796 } 3797 #if defined(PCMCIA_DEBUG) 3798 if (pcmcia_debug) { 3799 3800 cmn_err(CE_CONT, "SSSetIRQHandler: socket=%x, function=%x\n", 3801 sock, func); 3802 cmn_err(CE_CONT, "\thandler(%p): socket=%x, irq=%x, id=%x\n", 3803 (void *)handler->handler, handler->socket, handler->irq, 3804 handler->handler_id); 3805 } 3806 #endif 3807 dip = sockp->ls_dip[func]; 3808 3809 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip); 3810 3811 handler->iblk_cookie = &iblk; 3812 handler->idev_cookie = &idev; 3813 3814 retval = ddi_add_intr(dip, 0, handler->iblk_cookie, 3815 handler->idev_cookie, 3816 (uint32_t(*)(caddr_t)) handler->handler, 3817 handler->arg1); 3818 3819 if (retval == DDI_SUCCESS) { 3820 handler->iblk_cookie = &sockp->ls_iblk; 3821 handler->idev_cookie = &sockp->ls_idev; 3822 handler->irq = ppd->ppd_intrspec->intrspec_vec; 3823 retval = SUCCESS; 3824 } else { 3825 retval = sockp->ls_error; 3826 } 3827 return (retval); 3828 } 3829 3830 /* 3831 * SSClearIRQHandler() 3832 * Arrange to have the interrupt handler specified removed 3833 * from the interrupt list. 3834 */ 3835 static int 3836 SSClearIRQHandler(clear_irq_handler_t *handler) 3837 { 3838 int sock, func; 3839 pcmcia_logical_socket_t *sockp; 3840 dev_info_t *dip; 3841 3842 sock = CS_GET_SOCKET_NUMBER(handler->socket); 3843 func = CS_GET_FUNCTION_NUMBER(handler->socket); 3844 3845 #if defined(PCMCIA_DEBUG) 3846 if (pcmcia_debug) { 3847 3848 cmn_err(CE_CONT, 3849 "SSClearIRQHandler: socket=%x, function=%x\n", 3850 sock, func); 3851 cmn_err(CE_CONT, 3852 "\thandler(%p): socket=%x, id=%x\n", 3853 (void *)handler, handler->socket, 3854 handler->handler_id); 3855 } 3856 #endif 3857 3858 if (sock > pcmcia_num_sockets || 3859 (sockp = pcmcia_sockets[sock]) == NULL) { 3860 return (BAD_SOCKET); 3861 } 3862 dip = sockp->ls_dip[func]; 3863 if (dip) { 3864 ddi_remove_intr(dip, 0, NULL); 3865 return (SUCCESS); 3866 } 3867 return (BAD_SOCKET); 3868 } 3869 3870 3871 /* 3872 * pcm_pathname() 3873 * make a partial path from dip. 3874 * used to mknods relative to /devices/pcmcia/ 3875 * 3876 * XXX - we now use ddi_get_name_addr to get the "address" portion 3877 * of the name; that way, we only have to modify the name creation 3878 * algorithm in one place 3879 */ 3880 static void 3881 pcm_pathname(dev_info_t *dip, char *name, char *path) 3882 { 3883 (void) sprintf(path, "%s@%s:%s", ddi_node_name(dip), 3884 ddi_get_name_addr(dip), name); 3885 } 3886 3887 /* 3888 * pcmcia_create_device() 3889 * create the /devices entries for the driver 3890 * it is assumed that the PC Card driver will do a 3891 * RegisterClient for each subdevice. 3892 * The device type string is encoded here to match 3893 * the standardized names when possible. 3894 * XXX - note that we may need to provide a way for the 3895 * caller to specify the complete name string that 3896 * we pass to ddi_set_name_addr 3897 */ 3898 static int 3899 pcmcia_create_device(ss_make_device_node_t *init) 3900 { 3901 int err = SUCCESS; 3902 struct pcm_make_dev device; 3903 struct dev_ops *ops; 3904 major_t major; 3905 3906 /* 3907 * Now that we have the name, create it. 3908 */ 3909 3910 bzero(&device, sizeof (device)); 3911 if (init->flags & SS_CSINITDEV_CREATE_DEVICE) { 3912 if ((err = ddi_create_minor_node(init->dip, 3913 init->name, 3914 init->spec_type, 3915 init->minor_num, 3916 init->node_type, 3917 0)) != DDI_SUCCESS) { 3918 #if defined(PCMCIA_DEBUG) 3919 if (pcmcia_debug) 3920 cmn_err(CE_CONT, 3921 "pcmcia_create_device: failed " 3922 "create\n"); 3923 #endif 3924 return (BAD_ATTRIBUTE); 3925 } 3926 3927 major = ddi_name_to_major(ddi_binding_name(init->dip)); 3928 ops = ddi_get_driver(init->dip); 3929 LOCK_DEV_OPS(&devnamesp[major].dn_lock); 3930 INCR_DEV_OPS_REF(ops); 3931 (void) ddi_pathname(init->dip, device.path); 3932 DECR_DEV_OPS_REF(ops); 3933 UNLOCK_DEV_OPS(&devnamesp[major].dn_lock); 3934 (void) sprintf(device.path + strlen(device.path), ":%s", 3935 init->name); 3936 3937 (void) strcpy(device.driver, ddi_binding_name(init->dip)); 3938 #if defined(PCMCIA_DEBUG) 3939 if (pcmcia_debug) 3940 cmn_err(CE_CONT, 3941 "pcmcia_create_device: created %s " 3942 "from %s [%s]\n", 3943 device.path, init->name, device.driver); 3944 #endif 3945 device.dev = 3946 makedevice(ddi_name_to_major(ddi_get_name(init->dip)), 3947 init->minor_num); 3948 device.flags |= (init->flags & SS_CSINITDEV_MORE_DEVICES) ? 3949 PCM_EVENT_MORE : 0; 3950 device.type = init->spec_type; 3951 device.op = SS_CSINITDEV_CREATE_DEVICE; 3952 device.socket = ddi_getprop(DDI_DEV_T_ANY, init->dip, 3953 DDI_PROP_CANSLEEP, PCM_DEV_SOCKET, 3954 -1); 3955 } else if (init->flags & SS_CSINITDEV_REMOVE_DEVICE) { 3956 device.op = SS_CSINITDEV_REMOVE_DEVICE; 3957 device.socket = ddi_getprop(DDI_DEV_T_ANY, init->dip, 3958 DDI_PROP_CANSLEEP, PCM_DEV_SOCKET, 3959 -1); 3960 if (init->name != NULL) 3961 (void) strcpy(device.path, init->name); 3962 device.dev = 3963 makedevice(ddi_name_to_major(ddi_get_name(init->dip)), 3964 0); 3965 ddi_remove_minor_node(init->dip, init->name); 3966 } 3967 3968 /* 3969 * we send an event for ALL devices created. 3970 * To do otherwise ties us to using drvconfig 3971 * forever. There are relatively few devices 3972 * ever created so no need to do otherwise. 3973 * The existence of the event manager must never 3974 * be visible to a PCMCIA device driver. 3975 */ 3976 pcm_event_manager(PCE_INIT_DEV, device.socket, &device); 3977 3978 return (err); 3979 } 3980 3981 /* 3982 * pcmcia_get_minors() 3983 * We need to traverse the minor node list of the 3984 * dip if there are any. This takes two passes; 3985 * one to get the count and buffer size and the 3986 * other to actually copy the data into the buffer. 3987 * The framework requires that the dip be locked 3988 * during this time to avoid breakage as well as the 3989 * driver being locked. 3990 */ 3991 int 3992 pcmcia_get_minors(dev_info_t *dip, struct pcm_make_dev **minors) 3993 { 3994 int count = 0; 3995 struct ddi_minor_data *dp; 3996 struct pcm_make_dev *md; 3997 int socket; 3998 major_t major; 3999 struct dev_ops *ops; 4000 4001 socket = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 4002 PCM_DEV_SOCKET, -1); 4003 mutex_enter(&(DEVI(dip)->devi_lock)); 4004 if (DEVI(dip)->devi_minor != (struct ddi_minor_data *)NULL) { 4005 for (dp = DEVI(dip)->devi_minor; 4006 dp != (struct ddi_minor_data *)NULL; 4007 dp = dp->next) { 4008 count++; /* have one more */ 4009 } 4010 /* we now know how many nodes to allocate */ 4011 md = kmem_zalloc(count * sizeof (struct pcm_make_dev), 4012 KM_NOSLEEP); 4013 if (md != NULL) { 4014 *minors = md; 4015 for (dp = DEVI(dip)->devi_minor; 4016 dp != (struct ddi_minor_data *)NULL; 4017 dp = dp->next, md++) { 4018 #if defined(PCMCIA_DEBUG) 4019 if (pcmcia_debug > 1) { 4020 cmn_err(CE_CONT, 4021 "pcmcia_get_minors: name=%s," 4022 "socket=%d, stype=%x, " 4023 "ntype=%s, dev_t=%x", 4024 dp->ddm_name, 4025 socket, 4026 dp->ddm_spec_type, 4027 dp->ddm_node_type, 4028 (int)dp->ddm_dev); 4029 cmn_err(CE_CONT, 4030 "\tbind name = %s\n", 4031 ddi_binding_name(dip)); 4032 } 4033 #endif 4034 md->socket = socket; 4035 md->op = SS_CSINITDEV_CREATE_DEVICE; 4036 md->dev = dp->ddm_dev; 4037 md->type = dp->ddm_spec_type; 4038 (void) strcpy(md->driver, 4039 ddi_binding_name(dip)); 4040 major = ddi_name_to_major(md->driver); 4041 ops = ddi_get_driver(dip); 4042 LOCK_DEV_OPS(&devnamesp[major].dn_lock); 4043 pcm_pathname(dip, dp->ddm_name, md->path); 4044 INCR_DEV_OPS_REF(ops); 4045 (void) ddi_pathname(dip, md->path); 4046 DECR_DEV_OPS_REF(ops); 4047 UNLOCK_DEV_OPS(&devnamesp[major].dn_lock); 4048 (void) sprintf(md->path + strlen(md->path), 4049 ":%s", dp->ddm_name); 4050 if (dp->next == NULL) 4051 /* no more */ 4052 md->flags |= PCM_EVENT_MORE; 4053 } 4054 } else { 4055 count = 0; 4056 } 4057 } 4058 mutex_exit(&(DEVI(dip)->devi_lock)); 4059 return (count); 4060 } 4061 4062 #if defined(PCMCIA_DEBUG) 4063 static char *ddmtypes[] = { "minor", "alias", "default", "internal" }; 4064 4065 static void 4066 pcmcia_dump_minors(dev_info_t *dip) 4067 { 4068 int count = 0; 4069 struct ddi_minor_data *dp; 4070 int unit, major; 4071 dev_info_t *np; 4072 4073 unit = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 4074 PCM_DEV_SOCKET, -1); 4075 cmn_err(CE_CONT, 4076 "pcmcia_dump_minors: dip=%p, socket=%d\n", (void *)dip, unit); 4077 4078 major = ddi_driver_major(dip); 4079 if (major != -1) { 4080 for (np = devnamesp[major].dn_head; np != NULL; 4081 np = (dev_info_t *)DEVI(np)->devi_next) { 4082 char *cf2 = ""; 4083 char *cur = ""; 4084 if (i_ddi_node_state(np) == DS_READY) 4085 cf2 = "DS_READY"; 4086 if (np == dip) 4087 cur = "CUR"; 4088 cmn_err(CE_CONT, "\tsibs: %s %s %s\n", 4089 ddi_binding_name(np), cf2, cur); 4090 4091 mutex_enter(&(DEVI(np)->devi_lock)); 4092 if (DEVI(np)->devi_minor != 4093 (struct ddi_minor_data *)NULL) { 4094 for (dp = DEVI(np)->devi_minor; 4095 dp != (struct ddi_minor_data *)NULL; 4096 dp = dp->next) { 4097 count++; /* have one more */ 4098 } 4099 for (dp = DEVI(dip)->devi_minor; 4100 dp != (struct ddi_minor_data *)NULL; 4101 dp = dp->next) { 4102 cmn_err(CE_CONT, "\ttype=%s, name=%s," 4103 "socket=%d, stype=%x, " 4104 "ntype=%s, dev_t=%x", 4105 ddmtypes[dp->type], 4106 dp->ddm_name, 4107 unit, 4108 dp->ddm_spec_type, 4109 dp->ddm_node_type, 4110 (int)dp->ddm_dev); 4111 cmn_err(CE_CONT, "\tbind name = %s\n", 4112 ddi_binding_name(np)); 4113 } 4114 } 4115 mutex_exit(&(DEVI(np)->devi_lock)); 4116 } 4117 } 4118 } 4119 #endif 4120 4121 /* 4122 * experimental merging code 4123 * what are the things that we should merge on? 4124 * match something by name in the "compatible" property 4125 * restrict to a specific "socket" 4126 * restrict to a specific "instance" 4127 */ 4128 /*ARGSUSED*/ 4129 static int 4130 pcmcia_merge_conf(dev_info_t *dip) 4131 { 4132 return (0); /* merge failed */ 4133 } 4134 4135 /* 4136 * pcmcia_mfc_intr() 4137 * Multifunction Card interrupt handler 4138 * While some adapters share interrupts at the lowest 4139 * level, some can't. In order to be consistent, we 4140 * split multifunction cards out with this intercept and 4141 * allow the low level to do what is best for it. 4142 * the arg is a pcmcia_socket structure and all interrupts 4143 * are per-socket in this case. We also have the option 4144 * to optimize if the cards support it. It also means 4145 * that we can use the INTRACK mode if it proves desirable 4146 */ 4147 /*ARGSUSED*/ 4148 static uint32_t 4149 pcmcia_mfc_intr(caddr_t arg1, caddr_t arg2) 4150 { 4151 pcmcia_logical_socket_t *sockp; 4152 inthandler_t *intr, *first; 4153 int done, result; 4154 4155 sockp = (pcmcia_logical_socket_t *)arg1; 4156 4157 #if defined(PCMCIA_DEBUG) 4158 if (pcmcia_debug > 1) { 4159 cmn_err(CE_CONT, "pcmcia_mfc_intr sockp=%p" 4160 " ls_inthandlers=%p\n" 4161 "\t ls_flags=0x%x PCS_IRQ_ENABLED=0x%x \n", 4162 (void *) sockp, (void *) sockp->ls_inthandlers, 4163 sockp->ls_flags, PCS_IRQ_ENABLED); 4164 } 4165 #endif 4166 4167 if (sockp == NULL || sockp->ls_inthandlers == NULL || 4168 !(sockp->ls_flags & PCS_IRQ_ENABLED)) 4169 return (DDI_INTR_UNCLAIMED); 4170 4171 mutex_enter(&sockp->ls_ilock); 4172 for (done = 0, result = 0, first = intr = sockp->ls_inthandlers; 4173 intr != NULL && !done; intr = intr->next) { 4174 result |= intr->intr(intr->arg1, intr->arg2); 4175 if (intr->next == first) 4176 done++; 4177 } 4178 if (intr == NULL) { 4179 cmn_err(CE_WARN, "pcmcia_mfc_intr: bad MFC handler list"); 4180 } 4181 if (sockp->ls_inthandlers) 4182 sockp->ls_inthandlers = sockp->ls_inthandlers->next; 4183 4184 mutex_exit(&sockp->ls_ilock); 4185 return (result ? DDI_INTR_CLAIMED : DDI_INTR_UNCLAIMED); 4186 } 4187 4188 /* 4189 * pcmcia_power(dip) 4190 * control power for nexus and children 4191 */ 4192 int 4193 pcmcia_power(dev_info_t *dip, int component, int level) 4194 { 4195 #if 0 4196 anp_t *anp = (anp_t *)ddi_get_driver_private(dip); 4197 int i; 4198 /* 4199 * for now, we only have one component. Should there be one per-socket? 4200 * the level is only one (power on or off) 4201 */ 4202 if (component != 0 || level > 1) 4203 return (DDI_FAILURE); 4204 4205 for (i = 0; i < pcic->pc_numsockets; i++) { 4206 if (pcic->pc_callback) 4207 PC_CALLBACK(dip, pcic->pc_cb_arg, 4208 (level == 0) ? PCE_PM_SUSPEND : 4209 PCE_PM_RESUME, 4210 i); 4211 } 4212 #else 4213 cmn_err(CE_WARN, "pcmcia_power: component=%d, level=%d for %s", 4214 component, level, ddi_get_name_addr(dip)); 4215 return (DDI_FAILURE); 4216 #endif 4217 } 4218 4219 void 4220 pcmcia_begin_resume(dev_info_t *dip) 4221 { 4222 int i; 4223 struct pcmcia_adapter *adapt = NULL; 4224 for (i = 0; i < pcmcia_num_adapters; i++) { 4225 if (pcmcia_adapters[i]->pca_dip == dip) { 4226 adapt = pcmcia_adapters[i]; 4227 break; 4228 } 4229 } 4230 if (adapt == NULL) 4231 return; 4232 4233 for (i = 0; i < adapt->pca_numsockets; i++) { 4234 int s; 4235 s = adapt->pca_first_socket + i; 4236 if (pcmcia_sockets[s]->ls_flags & PCS_SUSPENDED) { 4237 if (pcmcia_sockets[s]->ls_flags & 4238 (1 << PCE_PM_RESUME)) { 4239 (void) cs_event(PCE_PM_RESUME, s, 0); 4240 pcm_event_manager(PCE_PM_RESUME, s, NULL); 4241 } 4242 (void) cs_event(PCE_CARD_REMOVAL, s, 0); 4243 pcm_event_manager(PCE_CARD_REMOVAL, s, NULL); 4244 } 4245 } 4246 } 4247 4248 void 4249 pcmcia_wait_insert(dev_info_t *dip) 4250 { 4251 int i, f, tries, done; 4252 clock_t tm; 4253 struct pcmcia_adapter *adapt = NULL; 4254 anp_t *nexus; 4255 4256 for (i = 0; i < pcmcia_num_adapters; i++) { 4257 if (pcmcia_adapters[i]->pca_dip == dip) { 4258 adapt = pcmcia_adapters[i]; 4259 break; 4260 } 4261 } 4262 if (adapt == NULL) 4263 return; 4264 4265 for (tries = adapt->pca_numsockets * 10; tries > 0; tries--) { 4266 done = 1; 4267 mutex_enter(&pcmcia_global_lock); 4268 for (i = 0; i < adapt->pca_numsockets; i++) { 4269 int s; 4270 s = adapt->pca_first_socket + i; 4271 for (f = 0; f < PCMCIA_MAX_FUNCTIONS; f++) 4272 if (pcmcia_sockets[s] && 4273 pcmcia_sockets[s]->ls_flags & 4274 PCS_SUSPENDED) { 4275 done = 0; 4276 break; 4277 } 4278 } 4279 if (!done) { 4280 tm = ddi_get_lbolt(); 4281 (void) cv_timedwait(&pcmcia_condvar, 4282 &pcmcia_global_lock, 4283 tm + drv_usectohz(100000)); 4284 } else { 4285 tries = 0; 4286 } 4287 mutex_exit(&pcmcia_global_lock); 4288 } 4289 4290 nexus = (anp_t *)ddi_get_driver_private(dip); 4291 pcmcia_find_cards(nexus); 4292 } 4293 4294 int 4295 pcmcia_map_reg(dev_info_t *pdip, dev_info_t *dip, ra_return_t *ra, 4296 uint32_t state, caddr_t *base, 4297 ddi_acc_handle_t *handle, ddi_device_acc_attr_t *attrib, 4298 uint32_t req_base) 4299 { 4300 struct pcmcia_parent_private *ppd; 4301 int rnum = 0, type = PCMCIA_MAP_MEM; 4302 ddi_map_req_t mr; 4303 ddi_acc_hdl_t *hp; 4304 int result; 4305 struct regspec *reg; 4306 ddi_device_acc_attr_t attr; 4307 4308 if (dip != NULL) { 4309 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip); 4310 if (ppd == NULL) 4311 return (DDI_FAILURE); 4312 for (rnum = 1; rnum < ppd->ppd_nreg; rnum++) { 4313 struct pcm_regs *p; 4314 p = &ppd->ppd_reg[rnum]; 4315 if (state & WS_IO) { 4316 /* need I/O */ 4317 type = PCMCIA_MAP_IO; 4318 /* 4319 * We want to find an IO regspec. When we 4320 * find one, it either has to match 4321 * the caller's requested base address 4322 * or it has to be relocatable. 4323 * We match on the requested base address 4324 * rather than the allocated base 4325 * address so that we handle the case 4326 * of adapters that have IO window base 4327 * relocation registers. 4328 */ 4329 if ((p->phys_hi & 4330 PC_REG_SPACE(PC_REG_SPACE_IO)) && 4331 ((req_base == p->phys_lo) || 4332 !(p->phys_hi & PC_REG_RELOC(1)))) 4333 break; 4334 } else { 4335 /* need memory */ 4336 type = PCMCIA_MAP_MEM; 4337 if (p->phys_hi & 4338 PC_REG_SPACE(PC_REG_SPACE_MEMORY| 4339 PC_REG_SPACE_ATTRIBUTE)) 4340 break; 4341 } 4342 } 4343 if (rnum >= ppd->ppd_nreg) 4344 return (DDI_FAILURE); 4345 } else if (state & WS_IO) { 4346 return (DDI_FAILURE); 4347 } 4348 4349 reg = kmem_zalloc(sizeof (pci_regspec_t), KM_SLEEP); 4350 reg = pcmcia_cons_regspec(pdip, type, (uchar_t *)reg, ra); 4351 4352 if (attrib == NULL || 4353 attrib->devacc_attr_version != DDI_DEVICE_ATTR_V0) { 4354 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 4355 attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 4356 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 4357 } else { 4358 attr = *attrib; 4359 } 4360 /* 4361 * Allocate and initialize the common elements of data access handle. 4362 */ 4363 *handle = impl_acc_hdl_alloc(KM_SLEEP, NULL); 4364 hp = impl_acc_hdl_get(*handle); 4365 hp->ah_vers = VERS_ACCHDL; 4366 hp->ah_dip = dip != NULL ? dip : pdip; 4367 hp->ah_rnumber = rnum; 4368 hp->ah_offset = 0; 4369 hp->ah_len = ra->ra_len; 4370 hp->ah_acc = attr; 4371 4372 /* 4373 * Set up the mapping request and call to parent. 4374 */ 4375 mr.map_op = DDI_MO_MAP_LOCKED; 4376 mr.map_type = DDI_MT_REGSPEC; 4377 mr.map_obj.rp = reg; 4378 mr.map_prot = PROT_READ | PROT_WRITE; 4379 mr.map_flags = DDI_MF_KERNEL_MAPPING; 4380 mr.map_handlep = hp; 4381 mr.map_vers = DDI_MAP_VERSION; 4382 4383 result = ddi_map(pdip, &mr, 0, ra->ra_len, base); 4384 if (result != DDI_SUCCESS) { 4385 impl_acc_hdl_free(*handle); 4386 *handle = (ddi_acc_handle_t)NULL; 4387 } else { 4388 hp->ah_addr = *base; 4389 if (mr.map_op == DDI_MO_UNMAP) 4390 ra = NULL; 4391 if (dip != NULL) 4392 pcmcia_set_assigned(dip, rnum, ra); 4393 } 4394 4395 kmem_free(reg, sizeof (pci_regspec_t)); 4396 4397 return (result); 4398 } 4399 4400 struct pcmcia_adapter * 4401 pcmcia_get_adapter(dev_info_t *dip) 4402 { 4403 int i; 4404 4405 for (i = 0; i < pcmcia_num_adapters; i++) { 4406 if (pcmcia_adapters[i] && 4407 pcmcia_adapters[i]->pca_dip == dip) { 4408 return (pcmcia_adapters[i]); 4409 } 4410 } 4411 return (NULL); 4412 } 4413 4414 4415 void 4416 pcmcia_set_assigned(dev_info_t *dip, int rnum, ra_return_t *ret) 4417 { 4418 struct pcmcia_parent_private *ppd; 4419 struct pcm_regs *reg, *assign; 4420 4421 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip); 4422 if (ppd) { 4423 reg = &ppd->ppd_reg[rnum]; 4424 assign = &ppd->ppd_assigned[rnum]; 4425 if (ret) { 4426 if (assign->phys_hi == 0) { 4427 assign->phys_hi = reg->phys_hi; 4428 assign->phys_lo = ret->ra_addr_lo; 4429 assign->phys_len = ret->ra_len; 4430 } else if (assign->phys_lo != ret->ra_addr_lo) { 4431 #ifdef PCMCIA_DEBUG 4432 cmn_err(CE_WARN, "pcmcia: bad address:" 4433 "%s=<%x,%x>", 4434 ddi_get_name_addr(dip), 4435 ret->ra_addr_lo, assign->phys_lo); 4436 #else 4437 cmn_err(CE_WARN, "!pcmcia: bad address:" 4438 "%s=<%x,%x>", 4439 ddi_get_name_addr(dip), 4440 ret->ra_addr_lo, (int)assign->phys_lo); 4441 #endif 4442 } 4443 assign->phys_hi = PC_INCR_REFCNT(assign->phys_hi); 4444 } else { 4445 int i; 4446 assign->phys_hi = PC_DECR_REFCNT(assign->phys_hi); 4447 i = PC_GET_REG_REFCNT(assign->phys_hi); 4448 if (i == 0) { 4449 assign->phys_hi = 0; 4450 assign->phys_lo = 0; 4451 assign->phys_len = 0; 4452 } 4453 } 4454 } 4455 } 4456 4457 int 4458 pcmcia_alloc_mem(dev_info_t *dip, ndi_ra_request_t *req, ra_return_t *ret, 4459 dev_info_t **res_dip) 4460 { 4461 return (pcmcia_ra_alloc(dip, req, ret, NDI_RA_TYPE_MEM, res_dip)); 4462 } 4463 4464 int 4465 pcmcia_alloc_io(dev_info_t *dip, ndi_ra_request_t *req, ra_return_t *ret, 4466 dev_info_t **res_dip) 4467 { 4468 return (pcmcia_ra_alloc(dip, req, ret, NDI_RA_TYPE_IO, res_dip)); 4469 } 4470 4471 static boolean_t 4472 is_subtractv(dev_info_t *dip) 4473 { 4474 uint_t class; 4475 4476 if (dip == NULL) 4477 return (B_FALSE); 4478 class = ddi_getprop(DDI_DEV_T_ANY, dip, 4479 DDI_PROP_CANSLEEP|DDI_PROP_DONTPASS, 4480 "class-code", 0xff); 4481 if (class == PPB_SUBTRACTIVE) { 4482 return (B_TRUE); 4483 } 4484 return (B_FALSE); 4485 } 4486 4487 /* 4488 * pcmcia_pci_alloc() 4489 * allocate mem or I/O resource from the ancestor of the cardbus bridge. 4490 * First start from the parent node. If the parent is a subtractive 4491 * decode bridge and it does not have the requested resource, go up the 4492 * device tree to find the resource. 4493 * 4494 * dip the parent node of the cardbus bridge 4495 * 4496 * res_dip returns a pointer to the node from which the 4497 * resource is obtained. *res_dip could point to 4498 * the parent or a higher level ancestor. *res_dip 4499 * should be saved by the caller and later passed 4500 * to pcmcia_ra_free(); 4501 */ 4502 int 4503 pcmcia_pci_alloc(dev_info_t *dip, ndi_ra_request_t *req, ra_return_t *ret, 4504 char *type, dev_info_t **res_dip) 4505 { 4506 uint64_t base = 0; 4507 uint64_t len = 0; 4508 4509 if ((ndi_ra_alloc(dip, req, &base, &len, type, NDI_RA_PASS) 4510 == NDI_FAILURE) || 4511 ((base >> 32) != 0)) { 4512 if (is_subtractv(dip)) { 4513 return (pcmcia_pci_alloc(ddi_get_parent(dip), 4514 req, ret, type, res_dip)); 4515 4516 } else { 4517 ret->ra_addr_hi = 0; 4518 ret->ra_addr_lo = 0; 4519 ret->ra_len = 0; 4520 return (DDI_FAILURE); 4521 } 4522 } 4523 ret->ra_addr_lo = base & 0xffffffff; 4524 ret->ra_addr_hi = 0; 4525 ret->ra_len = len; 4526 *res_dip = dip; 4527 return (DDI_SUCCESS); 4528 } 4529 4530 int 4531 pcmcia_ra_alloc(dev_info_t *dip, ndi_ra_request_t *req, ra_return_t *ret, 4532 char *type, dev_info_t **res_dip) 4533 { 4534 uint64_t base = 0; 4535 uint64_t len = 0; 4536 4537 /* 4538 * Allocate space from busra resource list 4539 * should not return an address > 32 bits 4540 */ 4541 4542 if ((ndi_ra_alloc(dip, req, &base, &len, type, NDI_RA_PASS) 4543 == NDI_FAILURE) || 4544 ((base >> 32) != 0)) { 4545 return (pcmcia_pci_alloc(ddi_get_parent(dip), req, ret, 4546 type, res_dip)); 4547 } else { 4548 ret->ra_addr_lo = base & 0xffffffff; 4549 ret->ra_addr_hi = 0; 4550 ret->ra_len = len; 4551 *res_dip = dip; 4552 return (DDI_SUCCESS); 4553 } 4554 } 4555 4556 int 4557 pcmcia_free_mem(dev_info_t *dip, ra_return_t *ret) 4558 { 4559 return (pcmcia_ra_free(dip, ret, NDI_RA_TYPE_MEM)); 4560 } 4561 4562 int 4563 pcmcia_free_io(dev_info_t *dip, ra_return_t *ret) 4564 { 4565 return (pcmcia_ra_free(dip, ret, NDI_RA_TYPE_IO)); 4566 } 4567 4568 int 4569 pcmcia_ra_free(dev_info_t *dip, ra_return_t *ret, char *type) 4570 { 4571 if (dip == (dev_info_t *)-1) 4572 return (DDI_FAILURE); 4573 if (ndi_ra_free(dip, (uint64_t)ret->ra_addr_lo, (uint64_t)ret->ra_len, 4574 type, NDI_RA_PASS) == NDI_SUCCESS) { 4575 return (DDI_SUCCESS); 4576 } else { 4577 return (DDI_FAILURE); 4578 } 4579 } 4580 4581 4582 /* 4583 * when the low level device configuration does resource assignment 4584 * (devconf) then free the allocated resources so we can reassign them 4585 * later. Walk the child list to get them. 4586 */ 4587 void 4588 pcmcia_free_resources(dev_info_t *self) 4589 { 4590 struct regspec *assigned; 4591 int len; 4592 dev_info_t *dip; 4593 int circular; 4594 4595 ndi_devi_enter(self, &circular); 4596 /* do searches in compatible property order */ 4597 for (dip = (dev_info_t *)DEVI(self)->devi_child; 4598 dip != NULL; 4599 dip = (dev_info_t *)DEVI(dip)->devi_sibling) { 4600 len = 0; 4601 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 4602 DDI_PROP_DONTPASS|DDI_PROP_CANSLEEP, 4603 "assigned-addresses", 4604 (caddr_t)&assigned, 4605 &len) == DDI_PROP_SUCCESS) { 4606 /* 4607 * if there are assigned resources at this point, 4608 * then the OBP or devconf have assigned them and 4609 * they need to be freed. 4610 */ 4611 kmem_free(assigned, len); 4612 } 4613 } 4614 ndi_devi_exit(self, circular); 4615 } 4616 4617 /* 4618 * this is the equivalent of pcm_get_intr using ra_allocs. 4619 * returns -1 if failed, otherwise returns the allocated irq. 4620 * The input request, if less than zero it means not a specific 4621 * irq requested. If larger then 0 then we are requesting that specific 4622 * irq 4623 */ 4624 int 4625 pcmcia_get_intr(dev_info_t *dip, int request) 4626 { 4627 ndi_ra_request_t req; 4628 uint64_t base; 4629 uint64_t len; 4630 int err; 4631 4632 bzero(&req, sizeof (req)); 4633 base = 0; 4634 len = 1; 4635 if (request >= 0) { 4636 req.ra_flags = NDI_RA_ALLOC_SPECIFIED; 4637 req.ra_len = 1; 4638 req.ra_addr = (uint64_t)request; 4639 } 4640 4641 req.ra_boundbase = 0; 4642 req.ra_boundlen = 0xffffffffUL; 4643 req.ra_flags |= NDI_RA_ALLOC_BOUNDED; 4644 4645 err = ndi_ra_alloc(dip, &req, &base, &len, NDI_RA_TYPE_INTR, 4646 NDI_RA_PASS); 4647 4648 if (err == NDI_FAILURE) { 4649 return (-1); 4650 } else { 4651 return ((int)base); 4652 } 4653 } 4654 4655 4656 int 4657 pcmcia_return_intr(dev_info_t *dip, int request) 4658 { 4659 if ((ndi_ra_free(dip, (uint64_t)request, 1, NDI_RA_TYPE_INTR, 4660 NDI_RA_PASS)) == NDI_SUCCESS) { 4661 return (0); 4662 } else 4663 return (-1); 4664 4665 } 4666 4667 #ifdef sparc 4668 4669 int 4670 pcmcia_add_intr_impl(dev_info_t *dip, dev_info_t *rdip, 4671 ddi_intr_handle_impl_t *hdlp) 4672 { 4673 4674 struct pcmcia_parent_private *ppd; 4675 pcmcia_logical_socket_t *sockp; 4676 int socket, ret; 4677 struct pcmcia_adapter *adapt; 4678 set_irq_handler_t handler; 4679 struct intrspec *pispec; 4680 4681 #if defined(PCMCIA_DEBUG) 4682 if (pcmcia_debug) { 4683 cmn_err(CE_CONT, 4684 "pcmcia_add_intr_impl() entered " 4685 "dip=%p rdip=%p hdlp=%p \n", 4686 (void *)dip, (void *)rdip, (void *)hdlp); 4687 } 4688 #endif 4689 4690 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip); 4691 socket = ppd->ppd_socket; 4692 sockp = pcmcia_sockets[socket]; 4693 adapt = sockp->ls_adapter; 4694 4695 #if defined(PCMCIA_DEBUG) 4696 if (pcmcia_debug) { 4697 cmn_err(CE_CONT, "pcmcia_add_intr_impl()" 4698 " ppd_flags=0X%x PPD_CARD_MULTI=0X%x\n" 4699 " ppd_intrspec=%p ls_inthandlers=%p\n", 4700 ppd->ppd_flags, PPD_CARD_MULTI, 4701 (void *) ppd->ppd_intrspec, 4702 (void *)sockp->ls_inthandlers); 4703 } 4704 #endif 4705 4706 /* 4707 * calculate IPL level when we support multiple levels 4708 */ 4709 pispec = ppd->ppd_intrspec; 4710 if (pispec == NULL) { 4711 sockp->ls_error = BAD_IRQ; 4712 return (DDI_FAILURE); 4713 } 4714 4715 handler.socket = sockp->ls_socket; 4716 handler.irq = 0; /* default case */ 4717 handler.handler = (f_tt *)hdlp->ih_cb_func; 4718 handler.arg1 = hdlp->ih_cb_arg1; 4719 handler.arg2 = hdlp->ih_cb_arg2; 4720 handler.handler_id = (uint32_t)(uintptr_t)rdip; 4721 4722 /* 4723 * check if multifunction and do the right thing 4724 * we put an intercept in between the mfc handler and 4725 * us so we can catch and process. We might be able 4726 * to optimize this depending on the card features 4727 * (a future option). 4728 */ 4729 if (ppd->ppd_flags & PPD_CARD_MULTI) { 4730 inthandler_t *intr; 4731 /* 4732 * note that the first function is a special 4733 * case since it sets things up. We fall through 4734 * to the lower code and get the hardware set up. 4735 * subsequent times we just lock the list and insert 4736 * the handler and all is well. 4737 */ 4738 intr = kmem_zalloc(sizeof (inthandler_t), KM_NOSLEEP); 4739 if (intr == NULL) { 4740 sockp->ls_error = BAD_IRQ; 4741 return (DDI_FAILURE); 4742 } 4743 intr->intr = hdlp->ih_cb_func; 4744 intr->handler_id = (uint_t)(uintptr_t)rdip; 4745 intr->arg1 = hdlp->ih_cb_arg1; 4746 intr->arg2 = hdlp->ih_cb_arg2; 4747 intr->socket = socket; 4748 4749 mutex_enter(&sockp->ls_ilock); 4750 if (sockp->ls_inthandlers == NULL) { 4751 intr->next = intr->prev = intr; 4752 sockp->ls_inthandlers = intr; 4753 sockp->ls_mfintr_dip = rdip; 4754 mutex_exit(&sockp->ls_ilock); 4755 4756 /* 4757 * replace first function handler with 4758 * the mfc handler 4759 */ 4760 handler.handler = (f_tt *)pcmcia_mfc_intr; 4761 handler.arg1 = (caddr_t)sockp; 4762 handler.arg2 = NULL; 4763 } else { 4764 insque(intr, sockp->ls_inthandlers); 4765 mutex_exit(&sockp->ls_ilock); 4766 4767 pispec->intrspec_vec = sockp->ls_intr_vec; 4768 pispec->intrspec_pri = sockp->ls_intr_pri; 4769 hdlp->ih_pri = sockp->ls_intr_pri; 4770 4771 return (DDI_SUCCESS); 4772 } 4773 } 4774 4775 #if defined(PCMCIA_DEBUG) 4776 if (pcmcia_debug) { 4777 cmn_err(CE_CONT, "pcmcia_add_intr_impl() let adapter do it\n"); 4778 } 4779 #endif 4780 pispec->intrspec_func = (uint32_t (*)())handler.handler; 4781 4782 /* set default IPL then check for override */ 4783 4784 pispec->intrspec_pri = sockp->ls_intr_pri; 4785 hdlp->ih_pri = pispec->intrspec_pri; 4786 4787 #if defined(PCMCIA_DEBUG) 4788 if (pcmcia_debug) { 4789 cmn_err(CE_CONT, "pcmcia_add_intr_impl() socket=%d irq=%d" 4790 " handler_id=0X%x handler=%p arg1=%p arg2=%p\n", 4791 handler.socket, handler.irq, 4792 handler.handler_id, (void *)handler.handler, handler.arg1, 4793 handler.arg2); 4794 } 4795 #endif 4796 4797 if ((ret = SET_IRQ(sockp->ls_if, adapt->pca_dip, &handler)) != 4798 SUCCESS) { 4799 sockp->ls_error = ret; 4800 return (DDI_FAILURE); 4801 } 4802 4803 #if defined(PCMCIA_DEBUG) 4804 if (pcmcia_debug) { 4805 cmn_err(CE_CONT, "pcmcia_add_intr_impl()" 4806 " iblk_cookie=%p idev_cookie=%p\n" 4807 " ls_flags=0X%x PCS_COOKIES_VALID=0X%x\n", 4808 (void *)handler.iblk_cookie, 4809 (void *)handler.idev_cookie, 4810 sockp->ls_flags, PCS_COOKIES_VALID); 4811 } 4812 #endif 4813 4814 if (!(sockp->ls_flags & PCS_COOKIES_VALID)) { 4815 hdlp->ih_pri = (uint_t)(uintptr_t)*handler.iblk_cookie; 4816 sockp->ls_iblk = *handler.iblk_cookie; 4817 sockp->ls_idev = *handler.idev_cookie; 4818 sockp->ls_flags |= PCS_COOKIES_VALID; 4819 } 4820 4821 return (DDI_SUCCESS); 4822 } 4823 4824 void 4825 pcmcia_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip, 4826 ddi_intr_handle_impl_t *hdlp) 4827 { 4828 4829 struct pcmcia_parent_private *ppd; 4830 pcmcia_logical_socket_t *sockp; 4831 clear_irq_handler_t handler; 4832 struct intrspec *pispec; 4833 int socket; 4834 4835 #if defined(PCMCIA_DEBUG) 4836 if (pcmcia_debug) { 4837 cmn_err(CE_CONT, "pcmcia_remove_intr_impl() entered" 4838 " dip=%p rdip=%p hdlp=%p\n", 4839 (void *)dip, (void *)rdip, (void *)hdlp); 4840 } 4841 #endif 4842 4843 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip); 4844 socket = ppd->ppd_socket; 4845 sockp = pcmcia_sockets[socket]; 4846 pispec = ppd->ppd_intrspec; 4847 4848 #if defined(PCMCIA_DEBUG) 4849 if (pcmcia_debug) { 4850 cmn_err(CE_CONT, "pcmcia_remove_intr_impl()" 4851 " ls_inthandlers=%p ls_intrspec=%p\n", 4852 (void *)sockp->ls_inthandlers, 4853 (void *)&sockp->ls_intrspec); 4854 } 4855 #endif 4856 4857 /* first handle the multifunction case since it is simple */ 4858 mutex_enter(&sockp->ls_ilock); 4859 if (sockp->ls_inthandlers != NULL) { 4860 /* we must be MFC */ 4861 inthandler_t *intr; 4862 int remhandler = 0; 4863 intr = sockp->ls_inthandlers; 4864 4865 /* Check if there is only one handler left */ 4866 if ((intr->next == intr) && (intr->prev == intr)) { 4867 if (intr->handler_id == (unsigned)(uintptr_t)rdip) { 4868 sockp->ls_inthandlers = NULL; 4869 remhandler++; 4870 kmem_free(intr, sizeof (inthandler_t)); 4871 } 4872 } else { 4873 inthandler_t *first; 4874 int done; 4875 4876 for (done = 0, first = intr; !done; intr = intr->next) { 4877 if (intr->next == first) 4878 done++; 4879 if (intr->handler_id == 4880 (unsigned)(uintptr_t)rdip) { 4881 done++; 4882 4883 /* 4884 * If we're about to remove the 4885 * handler at the head of 4886 * the list, make the next 4887 * handler in line the head. 4888 */ 4889 if (sockp->ls_inthandlers == intr) 4890 sockp->ls_inthandlers = 4891 intr->next; 4892 4893 remque(intr); 4894 kmem_free(intr, sizeof (inthandler_t)); 4895 break; 4896 } /* handler_id */ 4897 } /* for */ 4898 } /* intr->next */ 4899 4900 if (!remhandler) { 4901 mutex_exit(&sockp->ls_ilock); 4902 return; 4903 } 4904 4905 /* need to get the dip that was used to add the handler */ 4906 rdip = sockp->ls_mfintr_dip; 4907 } 4908 4909 mutex_exit(&sockp->ls_ilock); 4910 4911 #if defined(PCMCIA_DEBUG) 4912 if (pcmcia_debug) { 4913 cmn_err(CE_CONT, "pcmcia_remove_intr_impl()" 4914 " pispec=%p rdip=%p\n", 4915 (void *)pispec, (void *)rdip); 4916 } 4917 #endif 4918 4919 handler.socket = sockp->ls_socket; 4920 handler.handler_id = (uint32_t)(uintptr_t)rdip; 4921 handler.handler = (f_tt *)pispec->intrspec_func; 4922 CLEAR_IRQ(sockp->ls_if, dip, &handler); 4923 } 4924 4925 4926 /* Consolidated interrupt processing interface */ 4927 /*ARGSUSED*/ 4928 int 4929 pcmcia_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 4930 ddi_intr_handle_impl_t *hdlp, void *result) 4931 { 4932 int ret = DDI_SUCCESS; 4933 4934 #if defined(PCMCIA_DEBUG) 4935 if (pcmcia_debug) { 4936 cmn_err(CE_CONT, "pcmcia_intr_ops() intr_op=%d\n", 4937 (int)intr_op); 4938 } 4939 #endif 4940 4941 switch (intr_op) { 4942 case DDI_INTROP_GETCAP: 4943 *(int *)result = DDI_INTR_FLAG_LEVEL; 4944 break; 4945 case DDI_INTROP_SETCAP: 4946 ret = DDI_ENOTSUP; 4947 break; 4948 case DDI_INTROP_ALLOC: 4949 *(int *)result = hdlp->ih_scratch1; 4950 break; 4951 case DDI_INTROP_FREE: 4952 break; 4953 case DDI_INTROP_GETPRI: 4954 if (pcmcia_add_intr_impl(dip, rdip, hdlp) != DDI_SUCCESS) 4955 return (DDI_FAILURE); 4956 *(int *)result = hdlp->ih_pri; 4957 pcmcia_remove_intr_impl(dip, rdip, hdlp); 4958 break; 4959 case DDI_INTROP_SETPRI: 4960 break; 4961 case DDI_INTROP_ADDISR: 4962 ret = pcmcia_add_intr_impl(dip, rdip, hdlp); 4963 break; 4964 case DDI_INTROP_REMISR: 4965 pcmcia_remove_intr_impl(dip, rdip, hdlp); 4966 break; 4967 case DDI_INTROP_ENABLE: 4968 case DDI_INTROP_DISABLE: 4969 break; 4970 case DDI_INTROP_NINTRS: 4971 case DDI_INTROP_NAVAIL: 4972 *(int *)result = i_ddi_get_intx_nintrs(rdip); 4973 break; 4974 case DDI_INTROP_SUPPORTED_TYPES: 4975 /* PCI nexus driver supports only fixed interrupts */ 4976 *(int *)result = i_ddi_get_intx_nintrs(rdip) ? 4977 DDI_INTR_TYPE_FIXED : 0; 4978 break; 4979 default: 4980 ret = DDI_ENOTSUP; 4981 break; 4982 } 4983 4984 return (ret); 4985 } 4986 4987 #elif defined(__x86) || defined(__amd64) 4988 4989 static struct intrspec *pcmcia_intr_get_ispec(dev_info_t *, int, 4990 pcmcia_logical_socket_t **); 4991 static struct intrspec *pcmcia_intr_add_isr(dev_info_t *, dev_info_t *, 4992 ddi_intr_handle_impl_t *); 4993 static int pcmcia_intr_enable_isr(dev_info_t *, dev_info_t *, 4994 ddi_intr_handle_impl_t *); 4995 static void pcmcia_intr_remove_isr(dev_info_t *, dev_info_t *, 4996 ddi_intr_handle_impl_t *); 4997 static void pcmcia_intr_disable_isr(dev_info_t *, dev_info_t *, 4998 ddi_intr_handle_impl_t *); 4999 5000 /* 5001 * pcmcia_intr_get_ispec: 5002 * This is mostly copied from older 'pcmcia_get_intrspec' function 5003 */ 5004 static struct intrspec * 5005 pcmcia_intr_get_ispec(dev_info_t *rdip, int inum, 5006 pcmcia_logical_socket_t **sockp) 5007 { 5008 int socket; 5009 struct intrspec *intrspec; 5010 struct pcmcia_parent_private *ppd; 5011 5012 if ((int)inum > 0 || (ddi_getprop(DDI_DEV_T_ANY, rdip, 5013 DDI_PROP_DONTPASS, "interrupts", -1) < 0)) 5014 return (NULL); 5015 5016 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip); 5017 if (ppd == NULL || ppd->ppd_intrspec == NULL) 5018 return (NULL); 5019 5020 if ((socket = ppd->ppd_socket) < 0) 5021 return (NULL); 5022 5023 if ((*sockp = pcmcia_sockets[socket]) == NULL) 5024 return (NULL); 5025 5026 intrspec = ppd->ppd_intrspec; 5027 if (intrspec->intrspec_vec == 0 && (*sockp)->ls_intr_vec != 0) 5028 intrspec->intrspec_vec = (*sockp)->ls_intr_vec; 5029 5030 return (intrspec); 5031 } 5032 5033 static struct intrspec * 5034 pcmcia_intr_add_isr(dev_info_t *dip, dev_info_t *rdip, 5035 ddi_intr_handle_impl_t *hdlp) 5036 { 5037 int socket; 5038 struct intrspec *ispecp; 5039 struct pcmcia_adapter *adapt; 5040 pcmcia_logical_socket_t *sockp; 5041 struct pcmcia_parent_private *ppd; 5042 5043 #if defined(PCMCIA_DEBUG) 5044 if (pcmcia_debug) 5045 cmn_err(CE_CONT, "pcmcia_intr_add_isr: " 5046 "dip=0x%p rdip=0x%p hdlp=0x%p\n", 5047 (void *)dip, (void *)rdip, (void *)hdlp); 5048 #endif /* PCMCIA_DEBUG */ 5049 5050 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip); 5051 socket = ppd->ppd_socket; 5052 sockp = pcmcia_sockets[socket]; 5053 adapt = sockp->ls_adapter; 5054 5055 ispecp = ppd->ppd_intrspec; 5056 if (ispecp == NULL) { 5057 sockp->ls_error = BAD_IRQ; 5058 return (ispecp); 5059 } 5060 5061 /* 5062 * check if multifunction and do the right thing 5063 * we put an intercept in between the mfc handler and us so we can 5064 * catch and process. We might be able to optimize this depending 5065 * on the card features (a future option). 5066 */ 5067 if (ppd->ppd_flags & PPD_CARD_MULTI && 5068 hdlp->ih_cb_func != pcmcia_mfc_intr) { 5069 inthandler_t *intr; 5070 5071 /* 5072 * note that the first function is a special case since it 5073 * sets things up. We fall through to the lower code and 5074 * get the hardware set up. Subsequent times we just lock 5075 * the list and insert the handler and all is well. 5076 */ 5077 intr = kmem_zalloc(sizeof (inthandler_t), KM_NOSLEEP); 5078 if (intr == NULL) { 5079 sockp->ls_error = BAD_IRQ; 5080 return (NULL); 5081 } 5082 5083 intr->intr = (uint32_t (*)())hdlp->ih_cb_func; 5084 intr->handler_id = (uint32_t)(uintptr_t)rdip; 5085 intr->arg1 = hdlp->ih_cb_arg1; 5086 intr->arg2 = hdlp->ih_cb_arg2; 5087 intr->socket = socket; 5088 mutex_enter(&sockp->ls_ilock); 5089 if (sockp->ls_inthandlers == NULL) { 5090 intr->next = intr->prev = intr; 5091 sockp->ls_inthandlers = intr; 5092 sockp->ls_mfintr_dip = rdip; 5093 } else { 5094 insque(intr, sockp->ls_inthandlers); 5095 } 5096 mutex_exit(&sockp->ls_ilock); 5097 return (ispecp); 5098 } 5099 5100 /* 5101 * Do we need to allocate an IRQ at this point or not? 5102 */ 5103 if (adapt->pca_flags & PCA_RES_NEED_IRQ) { 5104 int i, irq; 5105 5106 /* 5107 * this adapter needs IRQ allocations 5108 * this is only necessary if it is the first function on the 5109 * card being setup. The socket will keep the allocation info 5110 */ 5111 /* all functions use same intrspec except mfc handler */ 5112 if (hdlp->ih_cb_func == pcmcia_mfc_intr) { 5113 /* 5114 * We treat this special in order to allow things to 5115 * work properly for MFC cards. The intrspec for the 5116 * mfc dispatcher is intercepted and taken from the 5117 * logical socket in order to not be trying to 5118 * multiplex the meaning when ENABLE is called. 5119 */ 5120 ispecp = &sockp->ls_intrspec; 5121 ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispecp; 5122 } 5123 5124 if (adapt->pca_flags & PCA_IRQ_ISA) { 5125 for (irq = -1, i = 1; irq == -1 && i < 16; i++) { 5126 /* find available and usable IRQ level */ 5127 if (adapt->pca_avail_intr & (1 << i)) 5128 irq = pcmcia_get_intr(dip, i); 5129 } 5130 } 5131 if (irq < 0) { 5132 sockp->ls_error = NO_RESOURCE; 5133 return (NULL); 5134 } 5135 hdlp->ih_vector = sockp->ls_intr_vec = irq; 5136 5137 5138 #if defined(PCMCIA_DEBUG) 5139 if (pcmcia_debug) 5140 cmn_err(CE_CONT, "allocated irq=%x\n", irq); 5141 #endif /* PCMCIA_DEBUG */ 5142 5143 ispecp->intrspec_vec = sockp->ls_intr_vec; 5144 ispecp->intrspec_pri = sockp->ls_intr_pri; 5145 return (ispecp); 5146 } 5147 5148 if (ispecp->intrspec_func != NULL) 5149 ispecp->intrspec_func = hdlp->ih_cb_func; 5150 5151 /* set default IPL then check for override */ 5152 ispecp->intrspec_pri = sockp->ls_intr_pri; 5153 return (ispecp); 5154 } 5155 5156 5157 static int 5158 pcmcia_intr_enable_isr(dev_info_t *dip, dev_info_t *rdip, 5159 ddi_intr_handle_impl_t *hdlp) 5160 { 5161 int socket, ret; 5162 int irq = 0; /* default case */ 5163 dev_info_t *parent = ddi_root_node(); 5164 struct intrspec *ispecp; 5165 set_irq_handler_t handler; 5166 struct pcmcia_adapter *adapt; 5167 pcmcia_logical_socket_t *sockp; 5168 struct pcmcia_parent_private *ppd; 5169 5170 #if defined(PCMCIA_DEBUG) 5171 if (pcmcia_debug) 5172 cmn_err(CE_CONT, "pcmcia_intr_enable_isr: " 5173 "dip=0x%p rdip=0x%p hdlp=0x%p\n", 5174 (void *)dip, (void *)rdip, (void *)hdlp); 5175 #endif /* PCMCIA_DEBUG */ 5176 5177 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip); 5178 socket = ppd->ppd_socket; 5179 sockp = pcmcia_sockets[socket]; 5180 adapt = sockp->ls_adapter; 5181 5182 ispecp = ppd->ppd_intrspec; 5183 ASSERT(ispecp); 5184 5185 mutex_enter(&sockp->ls_ilock); 5186 if ((sockp->ls_inthandlers != NULL) && 5187 ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp != 5188 &sockp->ls_intrspec) { 5189 inthandler_t *intr = sockp->ls_inthandlers; 5190 5191 ASSERT(ppd->ppd_flags & PPD_CARD_MULTI); 5192 5193 /* Only one handler. So, call ddi_add_intr on it */ 5194 if ((intr->next == intr) && (intr->prev == intr)) { 5195 hdlp->ih_cb_func = pcmcia_mfc_intr; 5196 hdlp->ih_cb_arg1 = (caddr_t)sockp; 5197 hdlp->ih_cb_arg2 = NULL; 5198 5199 ret = (*(DEVI(parent)->devi_ops->devo_bus_ops-> 5200 bus_intr_op))(parent, rdip, DDI_INTROP_ENABLE, 5201 hdlp, NULL); 5202 5203 if (ret == DDI_FAILURE) { 5204 sockp->ls_inthandlers = NULL; 5205 kmem_free(intr, sizeof (inthandler_t)); 5206 sockp->ls_error = BAD_IRQ; 5207 mutex_exit(&sockp->ls_ilock); 5208 return (ret); 5209 } 5210 } 5211 mutex_exit(&sockp->ls_ilock); 5212 hdlp->ih_vector = ispecp->intrspec_vec = sockp->ls_intr_vec; 5213 hdlp->ih_pri = sockp->ls_intr_pri; 5214 sockp->ls_iblk = (ddi_iblock_cookie_t)(uintptr_t) 5215 sockp->ls_intr_pri; 5216 sockp->ls_idev.idev_vector = (ushort_t)hdlp->ih_vector; 5217 sockp->ls_idev.idev_priority = (ushort_t)sockp->ls_intr_pri; 5218 return (DDI_SUCCESS); 5219 } 5220 mutex_exit(&sockp->ls_ilock); 5221 5222 if (adapt->pca_flags & PCA_RES_NEED_IRQ) { 5223 if (hdlp->ih_cb_func == pcmcia_mfc_intr) 5224 ispecp = (struct intrspec *)&sockp->ls_intrspec; 5225 5226 /* XXX: remove it later as this is done in _add_isr as well */ 5227 ispecp->intrspec_vec = sockp->ls_intr_vec; 5228 ispecp->intrspec_pri = sockp->ls_intr_pri; 5229 5230 /* Enable interrupts */ 5231 ret = (*(DEVI(parent)->devi_ops->devo_bus_ops->bus_intr_op))( 5232 parent, rdip, DDI_INTROP_ENABLE, hdlp, NULL); 5233 5234 sockp->ls_iblk = (ddi_iblock_cookie_t)(uintptr_t) 5235 sockp->ls_intr_pri; 5236 sockp->ls_idev.idev_vector = (ushort_t)sockp->ls_intr_vec; 5237 sockp->ls_idev.idev_priority = (ushort_t)sockp->ls_intr_pri; 5238 5239 if (ret != DDI_SUCCESS) 5240 sockp->ls_error = BAD_IRQ; 5241 return (ret); 5242 } 5243 5244 #if defined(PCMCIA_DEBUG) 5245 if (pcmcia_debug) 5246 cmn_err(CE_CONT, "pcmcia_intr_enable_isr; let adapter do it\n"); 5247 #endif /* PCMCIA_DEBUG */ 5248 5249 handler.socket = sockp->ls_socket; 5250 handler.irq = irq; 5251 handler.handler = (f_tt *)hdlp->ih_cb_func; 5252 handler.arg1 = hdlp->ih_cb_arg1; 5253 handler.arg2 = hdlp->ih_cb_arg2; 5254 handler.handler_id = (uint32_t)(uintptr_t)rdip; 5255 if (ispecp->intrspec_func != NULL) 5256 ispecp->intrspec_func = hdlp->ih_cb_func; 5257 5258 /* set default IPL then check for override */ 5259 ispecp->intrspec_pri = sockp->ls_intr_pri; 5260 5261 if ((ret = SET_IRQ(sockp->ls_if, adapt->pca_dip, &handler)) != 5262 SUCCESS) { 5263 sockp->ls_error = ret; 5264 return (DDI_FAILURE); 5265 } 5266 ispecp->intrspec_func = hdlp->ih_cb_func; 5267 if (!(sockp->ls_flags & PCS_COOKIES_VALID)) { 5268 sockp->ls_iblk = *handler.iblk_cookie; 5269 sockp->ls_idev = *handler.idev_cookie; 5270 sockp->ls_flags |= PCS_COOKIES_VALID; 5271 } 5272 return (DDI_SUCCESS); 5273 } 5274 5275 /* ARGSUSED */ 5276 static void 5277 pcmcia_intr_remove_isr(dev_info_t *dip, dev_info_t *rdip, 5278 ddi_intr_handle_impl_t *hdlp) 5279 { 5280 int done, remhandler = 0; 5281 inthandler_t *intr, *first; 5282 struct intrspec *ispecp; 5283 pcmcia_logical_socket_t *sockp; 5284 5285 #if defined(PCMCIA_DEBUG) 5286 if (pcmcia_debug) 5287 cmn_err(CE_CONT, "pcmcia_intr_remove_isr: " 5288 "dip=0x%p rdip=0x%p hdlp=0x%p\n", 5289 (void *)dip, (void *)rdip, (void *)hdlp); 5290 #endif /* PCMCIA_DEBUG */ 5291 5292 ispecp = pcmcia_intr_get_ispec(rdip, hdlp->ih_inum, &sockp); 5293 ASSERT(ispecp); 5294 5295 /* first handle the multifunction case since it is simple */ 5296 mutex_enter(&sockp->ls_ilock); 5297 if (sockp->ls_inthandlers != NULL && 5298 ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp != 5299 &sockp->ls_intrspec) { 5300 5301 intr = sockp->ls_inthandlers; 5302 5303 /* Check if there is only one handler left */ 5304 if ((intr->next == intr) && (intr->prev == intr)) { 5305 if (intr->handler_id == (uint32_t)(uintptr_t)rdip) { 5306 sockp->ls_inthandlers = NULL; 5307 remhandler++; 5308 kmem_free(intr, sizeof (inthandler_t)); 5309 } 5310 5311 } else { 5312 for (done = 0, first = intr; !done; intr = intr->next) { 5313 if (intr->next == first) 5314 done++; 5315 if (intr->handler_id == 5316 (uint32_t)(uintptr_t)rdip) { 5317 done++; 5318 5319 /* 5320 * If we're about to remove the handler 5321 * at the head of the list, make the 5322 * next handler in line the head. 5323 */ 5324 if (sockp->ls_inthandlers == intr) 5325 sockp->ls_inthandlers = intr->next; 5326 5327 remque(intr); 5328 kmem_free(intr, sizeof (inthandler_t)); 5329 break; 5330 } /* handler_id */ 5331 } /* end of for */ 5332 } /* end of if intr->next */ 5333 5334 if (!remhandler) { 5335 mutex_exit(&sockp->ls_ilock); 5336 return; 5337 } 5338 } 5339 mutex_exit(&sockp->ls_ilock); 5340 5341 if (sockp->ls_adapter->pca_flags & PCA_RES_NEED_IRQ) { 5342 sockp->ls_intr_vec = 0; 5343 ispecp->intrspec_vec = 0; 5344 } 5345 } 5346 5347 5348 static void 5349 pcmcia_intr_disable_isr(dev_info_t *dip, dev_info_t *rdip, 5350 ddi_intr_handle_impl_t *hdlp) 5351 { 5352 int socket, ret; 5353 dev_info_t *parent; 5354 struct intrspec *ispecp; 5355 clear_irq_handler_t handler; 5356 struct pcmcia_adapter *adapt; 5357 pcmcia_logical_socket_t *sockp; 5358 struct pcmcia_parent_private *ppd; 5359 ihdl_plat_t *ihdl_plat_datap = 5360 (ihdl_plat_t *)hdlp->ih_private; 5361 5362 #if defined(PCMCIA_DEBUG) 5363 if (pcmcia_debug) 5364 cmn_err(CE_CONT, "pcmcia_intr_disable_isr: " 5365 "dip=0x%p rdip=0x%p hdlp=0x%p\n", 5366 (void *)dip, (void *)rdip, (void *)hdlp); 5367 #endif /* PCMCIA_DEBUG */ 5368 5369 ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip); 5370 socket = ppd->ppd_socket; 5371 sockp = pcmcia_sockets[socket]; 5372 adapt = sockp->ls_adapter; 5373 ispecp = ppd->ppd_intrspec; 5374 ASSERT(ispecp); 5375 5376 mutex_enter(&sockp->ls_ilock); 5377 if (sockp->ls_inthandlers != NULL && 5378 ihdl_plat_datap->ip_ispecp != &sockp->ls_intrspec) { 5379 inthandler_t *intr = sockp->ls_inthandlers; 5380 5381 /* Check if there is only one handler left */ 5382 if ((intr->next == intr) && (intr->prev == intr)) { 5383 if (intr->handler_id != (uint32_t)(uintptr_t)rdip) 5384 /* 5385 * need to get the dip that was 5386 * used to add the handler 5387 */ 5388 rdip = sockp->ls_mfintr_dip; 5389 ispecp = (struct intrspec *)&sockp->ls_intrspec; 5390 } else { 5391 /* Don't call cleanup if list still has members */ 5392 mutex_exit(&sockp->ls_ilock); 5393 return; 5394 } 5395 } 5396 mutex_exit(&sockp->ls_ilock); 5397 5398 if (ihdl_plat_datap->ip_ispecp == 5399 (struct intrspec *)&sockp->ls_intrspec) 5400 ispecp = ihdl_plat_datap->ip_ispecp; 5401 5402 if (adapt->pca_flags & PCA_RES_NEED_IRQ) { 5403 ret = ispecp->intrspec_vec; 5404 parent = ddi_root_node(); 5405 ret = (*(DEVI(parent)->devi_ops->devo_bus_ops->bus_intr_op))( 5406 parent, rdip, DDI_INTROP_DISABLE, hdlp, NULL); 5407 (void) pcmcia_return_intr(dip, hdlp->ih_vector); 5408 #if defined(PCMCIA_DEBUG) 5409 if (pcmcia_debug) 5410 cmn_err(CE_CONT, "pcmcia_intr_disable_isr: " 5411 "INTROP_DISABLE returned %x\n", ret); 5412 #endif /* PCMCIA_DEBUG */ 5413 } else { 5414 handler.socket = sockp->ls_socket; 5415 handler.handler_id = (uint32_t)(uintptr_t)rdip; 5416 handler.handler = (f_tt *)ispecp->intrspec_func; 5417 ret = CLEAR_IRQ(sockp->ls_if, dip, &handler); 5418 #if defined(PCMCIA_DEBUG) 5419 if (pcmcia_debug) 5420 cmn_err(CE_CONT, "pcmcia_intr_disable_isr: " 5421 "CLEAR_IRQ returned %x\n", ret); 5422 #endif /* PCMCIA_DEBUG */ 5423 } 5424 } 5425 5426 /* Consolidated interrupt processing interface */ 5427 int 5428 pcmcia_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 5429 ddi_intr_handle_impl_t *hdlp, void *result) 5430 { 5431 struct intrspec *ispecp; 5432 pcmcia_logical_socket_t *sockp; 5433 5434 #if defined(PCMCIA_DEBUG) 5435 if (pcmcia_debug) 5436 cmn_err(CE_CONT, "pcmcia_intr_ops: " 5437 "dip=0x%p rdip=0x%p op=0x%x hdlp=0x%p\n", 5438 (void *)dip, (void *)rdip, intr_op, (void *)hdlp); 5439 #endif /* PCMCIA_DEBUG */ 5440 5441 switch (intr_op) { 5442 case DDI_INTROP_SUPPORTED_TYPES: 5443 if (ddi_get_parent_data(rdip) == NULL) { 5444 *(int *)result = 0; 5445 return (DDI_FAILURE); 5446 } 5447 *(int *)result = DDI_INTR_TYPE_FIXED; 5448 break; 5449 case DDI_INTROP_GETCAP: 5450 *(int *)result = DDI_INTR_FLAG_LEVEL; 5451 break; 5452 case DDI_INTROP_NINTRS: 5453 case DDI_INTROP_NAVAIL: 5454 if (i_ddi_get_intx_nintrs(rdip) == 0) { 5455 *(int *)result = 0; 5456 return (DDI_FAILURE); 5457 } 5458 *(int *)result = 1; /* for PCMCIA there is only one intr */ 5459 break; 5460 case DDI_INTROP_ALLOC: 5461 if ((ispecp = pcmcia_intr_get_ispec(rdip, hdlp->ih_inum, 5462 &sockp)) == NULL) 5463 return (DDI_FAILURE); 5464 *(int *)result = hdlp->ih_scratch1; 5465 break; 5466 case DDI_INTROP_FREE: 5467 break; 5468 case DDI_INTROP_GETPRI: 5469 ispecp = pcmcia_intr_get_ispec(rdip, hdlp->ih_inum, &sockp); 5470 if (ispecp == NULL) { 5471 *(int *)result = 0; 5472 return (DDI_FAILURE); 5473 } 5474 5475 *(int *)result = ispecp->intrspec_pri = sockp->ls_intr_pri; 5476 break; 5477 case DDI_INTROP_SETPRI: 5478 if (*(int *)result > LOCK_LEVEL) 5479 return (DDI_FAILURE); 5480 ispecp = pcmcia_intr_get_ispec(rdip, hdlp->ih_inum, &sockp); 5481 ASSERT(ispecp); 5482 ispecp->intrspec_pri = sockp->ls_intr_pri = *(int *)result; 5483 break; 5484 case DDI_INTROP_ADDISR: 5485 if ((ispecp = pcmcia_intr_add_isr(dip, rdip, hdlp)) == NULL) 5486 return (DDI_FAILURE); 5487 ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispecp; 5488 break; 5489 case DDI_INTROP_REMISR: 5490 pcmcia_intr_remove_isr(dip, rdip, hdlp); 5491 break; 5492 case DDI_INTROP_ENABLE: 5493 if (pcmcia_intr_enable_isr(dip, rdip, hdlp) != DDI_SUCCESS) 5494 return (DDI_FAILURE); 5495 break; 5496 case DDI_INTROP_DISABLE: 5497 pcmcia_intr_disable_isr(dip, rdip, hdlp); 5498 break; 5499 default: 5500 return (DDI_ENOTSUP); 5501 } 5502 5503 return (DDI_SUCCESS); 5504 } 5505 #endif 5506