pccard.c revision 59193
1/* $NetBSD: pcmcia.c,v 1.13 1998/12/24 04:51:59 marc Exp $ */ 2/* $FreeBSD: head/sys/dev/pccard/pccard.c 59193 2000-04-13 06:42:58Z imp $ */ 3 4/* 5 * Copyright (c) 1997 Marc Horowitz. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Marc Horowitz. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/malloc.h> 36#include <sys/module.h> 37#include <sys/kernel.h> 38#include <sys/queue.h> 39#include <sys/types.h> 40 41#include <sys/bus.h> 42#include <machine/bus.h> 43#include <sys/rman.h> 44#include <machine/resource.h> 45 46#include <dev/pccard/pccardreg.h> 47#include <dev/pccard/pccardchip.h> 48#include <dev/pccard/pccardvar.h> 49 50#include "power_if.h" 51#include "card_if.h" 52 53#define PCCARDDEBUG 54 55#ifdef PCCARDDEBUG 56int pccard_debug = 1; 57#define DPRINTF(arg) if (pccard_debug) printf arg 58#define DEVPRINTF(arg) if (pccard_debug) device_printf arg 59#else 60#define DPRINTF(arg) 61#define DEVPRINTF(arg) 62#endif 63 64#ifdef PCCARDVERBOSE 65int pccard_verbose = 1; 66#else 67int pccard_verbose = 0; 68#endif 69 70int pccard_print(void *, const char *); 71 72int 73pccard_ccr_read(pf, ccr) 74 struct pccard_function *pf; 75 int ccr; 76{ 77 return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh, 78 pf->pf_ccr_offset + ccr)); 79} 80 81void 82pccard_ccr_write(pf, ccr, val) 83 struct pccard_function *pf; 84 int ccr; 85 int val; 86{ 87 88 if ((pf->ccr_mask) & (1 << (ccr / 2))) { 89 bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh, 90 pf->pf_ccr_offset + ccr, val); 91 } 92} 93 94static int 95pccard_attach_card(device_t dev) 96{ 97 struct pccard_softc *sc = (struct pccard_softc *) 98 device_get_softc(dev); 99 struct pccard_function *pf; 100 int attached; 101 102 DEVPRINTF((dev, "pccard_card_attach\n")); 103 /* 104 * this is here so that when socket_enable calls gettype, trt happens 105 */ 106 STAILQ_INIT(&sc->card.pf_head); 107 108 DEVPRINTF((dev, "chip_socket_enable\n")); 109 POWER_ENABLE_SOCKET(device_get_parent(dev), dev); 110 111 DEVPRINTF((dev, "read_cis\n")); 112 pccard_read_cis(sc); 113 114 DEVPRINTF((dev, "chip_socket_disable\n")); 115 POWER_DISABLE_SOCKET(device_get_parent(dev), dev); 116 117 DEVPRINTF((dev, "check_cis_quirks\n")); 118 pccard_check_cis_quirks(dev); 119 120 /* 121 * bail now if the card has no functions, or if there was an error in 122 * the cis. 123 */ 124 125 if (sc->card.error) 126 return (1); 127 if (STAILQ_EMPTY(&sc->card.pf_head)) 128 return (1); 129 130 if (pccard_verbose) 131 pccard_print_cis(dev); 132 133 attached = 0; 134 135 DEVPRINTF((dev, "functions scanning\n")); 136 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) { 137 if (STAILQ_EMPTY(&pf->cfe_head)) 138 continue; 139 140 pf->sc = sc; 141 pf->cfe = NULL; 142 pf->ih_fct = NULL; 143 pf->ih_arg = NULL; 144 } 145 146 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) { 147 if (STAILQ_EMPTY(&pf->cfe_head)) 148 continue; 149 150#if XXX 151 if (attach_child()) { 152 attached++; 153 154 DEVPRINTF((sc->dev, "function %d CCR at %d " 155 "offset %lx: %x %x %x %x, %x %x %x %x, %x\n", 156 pf->number, pf->pf_ccr_window, pf->pf_ccr_offset, 157 pccard_ccr_read(pf, 0x00), 158 pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04), 159 pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A), 160 pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E), 161 pccard_ccr_read(pf, 0x10), pccard_ccr_read(pf, 0x12))); 162 } 163#endif 164 } 165 166 return (attached ? 0 : 1); 167} 168 169static int 170pccard_detach_card(device_t dev, int flags) 171{ 172 struct pccard_softc *sc = (struct pccard_softc *) 173 device_get_softc(dev); 174 struct pccard_function *pf; 175#if XXX 176 int error; 177#endif 178 179 /* 180 * We are running on either the PCCARD socket's event thread 181 * or in user context detaching a device by user request. 182 */ 183 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) { 184 if (STAILQ_FIRST(&pf->cfe_head) == NULL) 185 continue; 186#if XXX 187 DEVPRINTF((sc->dev, "detaching %s (function %d)\n", 188 device_get_name(pf->child), pf->number)); 189 if ((error = config_detach(pf->child, flags)) != 0) { 190 device_printf(sc->dev, 191 "error %d detaching %s (function %d)\n", 192 error, device_get_name(pf->child), pf->number); 193 } else 194 pf->child = NULL; 195#endif 196 } 197 return 0; 198} 199 200static int 201pccard_card_gettype(device_t dev, int *type) 202{ 203 struct pccard_softc *sc = (struct pccard_softc *) 204 device_get_softc(dev); 205 struct pccard_function *pf; 206 207 /* 208 * set the iftype to memory if this card has no functions (not yet 209 * probed), or only one function, and that is not initialized yet or 210 * that is memory. 211 */ 212 pf = STAILQ_FIRST(&sc->card.pf_head); 213 if (pf == NULL || 214 (STAILQ_NEXT(pf, pf_list) == NULL && 215 (pf->cfe == NULL || pf->cfe->iftype == PCCARD_IFTYPE_MEMORY))) 216 *type = PCCARD_IFTYPE_MEMORY; 217 else 218 *type = PCCARD_IFTYPE_IO; 219 return 0; 220} 221 222/* 223 * Initialize a PCCARD function. May be called as long as the function is 224 * disabled. 225 */ 226void 227pccard_function_init(struct pccard_function *pf, 228 struct pccard_config_entry *cfe) 229{ 230 if (pf->pf_flags & PFF_ENABLED) 231 panic("pccard_function_init: function is enabled"); 232 233 /* Remember which configuration entry we are using. */ 234 pf->cfe = cfe; 235} 236 237/* Enable a PCCARD function */ 238int 239pccard_function_enable(struct pccard_function *pf) 240{ 241 struct pccard_function *tmp; 242 int reg; 243 device_t dev = pf->sc->dev; 244 245 if (pf->cfe == NULL) 246 panic("pccard_function_enable: function not initialized"); 247 248 /* 249 * Increase the reference count on the socket, enabling power, if 250 * necessary. 251 */ 252 if (pf->sc->sc_enabled_count++ == 0) 253 POWER_ENABLE_SOCKET(device_get_parent(dev), dev); 254 DEVPRINTF((dev, "++enabled_count = %d\n", pf->sc->sc_enabled_count)); 255 256 if (pf->pf_flags & PFF_ENABLED) { 257 /* 258 * Don't do anything if we're already enabled. 259 */ 260 return (0); 261 } 262 263 /* 264 * it's possible for different functions' CCRs to be in the same 265 * underlying page. Check for that. 266 */ 267 268 STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) { 269 if ((tmp->pf_flags & PFF_ENABLED) && 270 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) && 271 ((pf->ccr_base + PCCARD_CCR_SIZE) <= 272 (tmp->ccr_base - tmp->pf_ccr_offset + 273 tmp->pf_ccr_realsize))) { 274 pf->pf_ccrt = tmp->pf_ccrt; 275 pf->pf_ccrh = tmp->pf_ccrh; 276 pf->pf_ccr_realsize = tmp->pf_ccr_realsize; 277 278 /* 279 * pf->pf_ccr_offset = (tmp->pf_ccr_offset - 280 * tmp->ccr_base) + pf->ccr_base; 281 */ 282 pf->pf_ccr_offset = 283 (tmp->pf_ccr_offset + pf->ccr_base) - 284 tmp->ccr_base; 285 pf->pf_ccr_window = tmp->pf_ccr_window; 286 break; 287 } 288 } 289 290 if (tmp == NULL) { 291 pf->ccr_rid = 0; 292 pf->ccr_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 293 &pf->ccr_rid, pf->ccr_base, pf->ccr_base + PCCARD_CCR_SIZE, 294 PCCARD_CCR_SIZE, RF_ACTIVE); 295 /* XXX SET MEM_ATTR */ 296 if (!pf->ccr_res) 297 goto bad; 298 pf->pf_ccrt = rman_get_bustag(pf->ccr_res); 299 pf->pf_ccrh = rman_get_bushandle(pf->ccr_res); 300 pf->pf_ccr_offset = rman_get_start(pf->ccr_res); 301 pf->pf_ccr_realsize = 1; 302 } 303 304 reg = (pf->cfe->number & PCCARD_CCR_OPTION_CFINDEX); 305 reg |= PCCARD_CCR_OPTION_LEVIREQ; 306 if (pccard_mfc(pf->sc)) { 307 reg |= (PCCARD_CCR_OPTION_FUNC_ENABLE | 308 PCCARD_CCR_OPTION_ADDR_DECODE); 309 if (pf->ih_fct) 310 reg |= PCCARD_CCR_OPTION_IREQ_ENABLE; 311 312 } 313 pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg); 314 315 reg = 0; 316 317 if ((pf->cfe->flags & PCCARD_CFE_IO16) == 0) 318 reg |= PCCARD_CCR_STATUS_IOIS8; 319 if (pf->cfe->flags & PCCARD_CFE_AUDIO) 320 reg |= PCCARD_CCR_STATUS_AUDIO; 321 pccard_ccr_write(pf, PCCARD_CCR_STATUS, reg); 322 323 pccard_ccr_write(pf, PCCARD_CCR_SOCKETCOPY, 0); 324 325 if (pccard_mfc(pf->sc)) { 326 long tmp, iosize; 327 328 tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase; 329 /* round up to nearest (2^n)-1 */ 330 for (iosize = 1; iosize < tmp; iosize <<= 1) 331 ; 332 iosize--; 333 334 pccard_ccr_write(pf, PCCARD_CCR_IOBASE0, 335 pf->pf_mfc_iobase & 0xff); 336 pccard_ccr_write(pf, PCCARD_CCR_IOBASE1, 337 (pf->pf_mfc_iobase >> 8) & 0xff); 338 pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0); 339 pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0); 340 341 pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize); 342 } 343 344#ifdef PCCARDDEBUG 345 if (pccard_debug) { 346 STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) { 347 device_printf(tmp->sc->dev, 348 "function %d CCR at %d offset %x: " 349 "%x %x %x %x, %x %x %x %x, %x\n", 350 tmp->number, tmp->pf_ccr_window, 351 tmp->pf_ccr_offset, 352 pccard_ccr_read(tmp, 0x00), 353 pccard_ccr_read(tmp, 0x02), 354 pccard_ccr_read(tmp, 0x04), 355 pccard_ccr_read(tmp, 0x06), 356 pccard_ccr_read(tmp, 0x0A), 357 pccard_ccr_read(tmp, 0x0C), 358 pccard_ccr_read(tmp, 0x0E), 359 pccard_ccr_read(tmp, 0x10), 360 pccard_ccr_read(tmp, 0x12)); 361 } 362 } 363#endif 364 pf->pf_flags |= PFF_ENABLED; 365 return (0); 366 367 bad: 368 /* 369 * Decrement the reference count, and power down the socket, if 370 * necessary. 371 */ 372 if (--pf->sc->sc_enabled_count == 0) 373 POWER_DISABLE_SOCKET(device_get_parent(dev), dev); 374 DEVPRINTF((dev, "--enabled_count = %d\n", pf->sc->sc_enabled_count)); 375 376 return (1); 377} 378 379/* Disable PCCARD function. */ 380void 381pccard_function_disable(struct pccard_function *pf) 382{ 383 struct pccard_function *tmp; 384 device_t dev = pf->sc->dev; 385 386 if (pf->cfe == NULL) 387 panic("pccard_function_enable: function not initialized"); 388 389 if ((pf->pf_flags & PFF_ENABLED) == 0) { 390 /* 391 * Don't do anything if we're already disabled. 392 */ 393 return; 394 } 395 396 /* 397 * it's possible for different functions' CCRs to be in the same 398 * underlying page. Check for that. Note we mark us as disabled 399 * first to avoid matching ourself. 400 */ 401 402 pf->pf_flags &= ~PFF_ENABLED; 403 STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) { 404 if ((tmp->pf_flags & PFF_ENABLED) && 405 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) && 406 ((pf->ccr_base + PCCARD_CCR_SIZE) <= 407 (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize))) 408 break; 409 } 410 411 /* Not used by anyone else; unmap the CCR. */ 412 if (tmp == NULL) { 413 bus_release_resource(dev, SYS_RES_MEMORY, pf->ccr_rid, 414 pf->ccr_res); 415 pf->ccr_res = NULL; 416 } 417 418 /* 419 * Decrement the reference count, and power down the socket, if 420 * necessary. 421 */ 422 if (--pf->sc->sc_enabled_count == 0) 423 POWER_DISABLE_SOCKET(device_get_parent(dev), dev); 424 DEVPRINTF((dev, "--enabled_count = %d\n", pf->sc->sc_enabled_count)); 425} 426 427#if 0 428/* XXX These functions are needed, but not like this XXX */ 429int 430pccard_io_map(struct pccard_function *pf, int width, bus_addr_t offset, 431 bus_size_t size, struct pccard_io_handle *pcihp, int *windowp) 432{ 433 int reg; 434 435 if (pccard_chip_io_map(pf->sc->pct, pf->sc->pch, 436 width, offset, size, pcihp, windowp)) 437 return (1); 438 439 /* 440 * XXX in the multifunction multi-iospace-per-function case, this 441 * needs to cooperate with io_alloc to make sure that the spaces 442 * don't overlap, and that the ccr's are set correctly 443 */ 444 445 if (pccard_mfc(pf->sc)) { 446 long tmp, iosize; 447 448 if (pf->pf_mfc_iomax == 0) { 449 pf->pf_mfc_iobase = pcihp->addr + offset; 450 pf->pf_mfc_iomax = pf->pf_mfc_iobase + size; 451 } else { 452 /* this makes the assumption that nothing overlaps */ 453 if (pf->pf_mfc_iobase > pcihp->addr + offset) 454 pf->pf_mfc_iobase = pcihp->addr + offset; 455 if (pf->pf_mfc_iomax < pcihp->addr + offset + size) 456 pf->pf_mfc_iomax = pcihp->addr + offset + size; 457 } 458 459 tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase; 460 /* round up to nearest (2^n)-1 */ 461 for (iosize = 1; iosize >= tmp; iosize <<= 1) 462 ; 463 iosize--; 464 465 pccard_ccr_write(pf, PCCARD_CCR_IOBASE0, 466 pf->pf_mfc_iobase & 0xff); 467 pccard_ccr_write(pf, PCCARD_CCR_IOBASE1, 468 (pf->pf_mfc_iobase >> 8) & 0xff); 469 pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0); 470 pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0); 471 472 pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize); 473 474 reg = pccard_ccr_read(pf, PCCARD_CCR_OPTION); 475 reg |= PCCARD_CCR_OPTION_ADDR_DECODE; 476 pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg); 477 } 478 return (0); 479} 480 481void 482pccard_io_unmap(struct pccard_function *pf, int window) 483{ 484 485 pccard_chip_io_unmap(pf->sc->pct, pf->sc->pch, window); 486 487 /* XXX Anything for multi-function cards? */ 488} 489#endif 490 491#define PCCARD_NPORT 2 492#define PCCARD_NMEM 5 493#define PCCARD_NIRQ 1 494#define PCCARD_NDRQ 0 495 496static int 497pccard_add_children(device_t dev, int busno) 498{ 499 /* Call parent to scan for any current children */ 500 return 0; 501} 502 503static int 504pccard_probe(device_t dev) 505{ 506 device_set_desc(dev, "PC Card bus -- newconfig version"); 507 return pccard_add_children(dev, device_get_unit(dev)); 508} 509 510static int 511pccard_attach(device_t dev) 512{ 513 struct pccard_softc *sc; 514 515 sc = (struct pccard_softc *) device_get_softc(dev); 516 sc->dev = dev; 517 518 return bus_generic_attach(dev); 519} 520 521static void 522pccard_print_resources(struct resource_list *rl, const char *name, int type, 523 int count, const char *format) 524{ 525 struct resource_list_entry *rle; 526 int printed; 527 int i; 528 529 printed = 0; 530 for (i = 0; i < count; i++) { 531 rle = resource_list_find(rl, type, i); 532 if (rle) { 533 if (printed == 0) 534 printf(" %s ", name); 535 else if (printed > 0) 536 printf(","); 537 printed++; 538 printf(format, rle->start); 539 if (rle->count > 1) { 540 printf("-"); 541 printf(format, rle->start + rle->count - 1); 542 } 543 } else if (i > 3) { 544 /* check the first few regardless */ 545 break; 546 } 547 } 548} 549 550static int 551pccard_print_child(device_t dev, device_t child) 552{ 553 struct pccard_ivar *devi = (struct pccard_ivar *) device_get_ivars(child); 554 struct resource_list *rl = &devi->resources; 555 int retval = 0; 556 557 retval += bus_print_child_header(dev, child); 558 retval += printf(" at"); 559 560 if (devi) { 561 pccard_print_resources(rl, "port", SYS_RES_IOPORT, 562 PCCARD_NPORT, "%#lx"); 563 pccard_print_resources(rl, "iomem", SYS_RES_MEMORY, 564 PCCARD_NMEM, "%#lx"); 565 pccard_print_resources(rl, "irq", SYS_RES_IRQ, PCCARD_NIRQ, 566 "%ld"); 567 pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ, 568 "%ld"); 569 retval += printf(" slot %d", devi->slotnum); 570 } 571 572 retval += bus_print_child_footer(dev, child); 573 574 return (retval); 575} 576 577static int 578pccard_set_resource(device_t dev, device_t child, int type, int rid, 579 u_long start, u_long count) 580{ 581 struct pccard_ivar *devi = (struct pccard_ivar *) device_get_ivars(child); 582 struct resource_list *rl = &devi->resources; 583 584 if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY 585 && type != SYS_RES_IRQ && type != SYS_RES_DRQ) 586 return EINVAL; 587 if (rid < 0) 588 return EINVAL; 589 if (type == SYS_RES_IOPORT && rid >= PCCARD_NPORT) 590 return EINVAL; 591 if (type == SYS_RES_MEMORY && rid >= PCCARD_NMEM) 592 return EINVAL; 593 if (type == SYS_RES_IRQ && rid >= PCCARD_NIRQ) 594 return EINVAL; 595 if (type == SYS_RES_DRQ && rid >= PCCARD_NDRQ) 596 return EINVAL; 597 598 resource_list_add(rl, type, rid, start, start + count - 1, count); 599 600 return 0; 601} 602 603static int 604pccard_get_resource(device_t dev, device_t child, int type, int rid, 605 u_long *startp, u_long *countp) 606{ 607 struct pccard_ivar *devi = (struct pccard_ivar *) device_get_ivars(child); 608 struct resource_list *rl = &devi->resources; 609 struct resource_list_entry *rle; 610 611 rle = resource_list_find(rl, type, rid); 612 if (!rle) 613 return ENOENT; 614 615 if (startp) 616 *startp = rle->start; 617 if (countp) 618 *countp = rle->count; 619 620 return 0; 621} 622 623static void 624pccard_delete_resource(device_t dev, device_t child, int type, int rid) 625{ 626 struct pccard_ivar *devi = (struct pccard_ivar *) device_get_ivars(child); 627 struct resource_list *rl = &devi->resources; 628 resource_list_delete(rl, type, rid); 629} 630 631static int 632pccard_set_res_flags(device_t dev, device_t child, int type, int rid, 633 u_int32_t flags) 634{ 635 return CARD_SET_RES_FLAGS(device_get_parent(dev), child, type, 636 rid, flags); 637} 638 639static int 640pccard_set_memory_offset(device_t dev, device_t child, int rid, 641 u_int32_t offset) 642{ 643 return CARD_SET_MEMORY_OFFSET(device_get_parent(dev), child, rid, 644 offset); 645} 646 647static device_method_t pccard_methods[] = { 648 /* Device interface */ 649 DEVMETHOD(device_probe, pccard_probe), 650 DEVMETHOD(device_attach, pccard_attach), 651 DEVMETHOD(device_shutdown, bus_generic_shutdown), 652 DEVMETHOD(device_suspend, bus_generic_suspend), 653 DEVMETHOD(device_resume, bus_generic_resume), 654 655 /* Bus interface */ 656 DEVMETHOD(bus_print_child, pccard_print_child), 657 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 658 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 659 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 660 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 661 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 662 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 663 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 664 DEVMETHOD(bus_set_resource, pccard_set_resource), 665 DEVMETHOD(bus_get_resource, pccard_get_resource), 666 DEVMETHOD(bus_delete_resource, pccard_delete_resource), 667 668 /* Card Interface */ 669 DEVMETHOD(card_set_res_flags, pccard_set_res_flags), 670 DEVMETHOD(card_set_memory_offset, pccard_set_memory_offset), 671 DEVMETHOD(card_get_type, pccard_card_gettype), 672 DEVMETHOD(card_attach_card, pccard_attach_card), 673 DEVMETHOD(card_detach_card, pccard_detach_card), 674 675 { 0, 0 } 676}; 677 678static driver_t pccard_driver = { 679 "pccard", 680 pccard_methods, 681 1, /* no softc */ 682}; 683 684devclass_t pccard_devclass; 685 686DRIVER_MODULE(pccard, pcic, pccard_driver, pccard_devclass, 0, 0); 687DRIVER_MODULE(pccard, pc98pcic, pccard_driver, pccard_devclass, 0, 0); 688DRIVER_MODULE(pccard, pccbb, pccard_driver, pccard_devclass, 0, 0); 689DRIVER_MODULE(pccard, tcic, pccard_driver, pccard_devclass, 0, 0); 690