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