| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: i82365.c,v 1.102 2008/04/08 12:07:26 cegger Exp $ */ | | 1 | /* $NetBSD: i82365.c,v 1.102.14.1 2009/08/14 21:37:03 snj Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2004 Charles M. Hannum. All rights reserved. | | 4 | * Copyright (c) 2004 Charles M. Hannum. All rights reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * 3. All advertising materials mentioning features or use of this software | | 14 | * 3. All advertising materials mentioning features or use of this software |
| @@ -39,27 +39,27 @@ | | | @@ -39,27 +39,27 @@ |
39 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 39 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
40 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 40 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
41 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 41 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
42 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 42 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
43 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 43 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
44 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 44 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
45 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 45 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
46 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 46 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
47 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 47 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
48 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 48 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
49 | */ | | 49 | */ |
50 | | | 50 | |
51 | #include <sys/cdefs.h> | | 51 | #include <sys/cdefs.h> |
52 | __KERNEL_RCSID(0, "$NetBSD: i82365.c,v 1.102 2008/04/08 12:07:26 cegger Exp $"); | | 52 | __KERNEL_RCSID(0, "$NetBSD: i82365.c,v 1.102.14.1 2009/08/14 21:37:03 snj Exp $"); |
53 | | | 53 | |
54 | #define PCICDEBUG | | 54 | #define PCICDEBUG |
55 | | | 55 | |
56 | #include <sys/param.h> | | 56 | #include <sys/param.h> |
57 | #include <sys/systm.h> | | 57 | #include <sys/systm.h> |
58 | #include <sys/device.h> | | 58 | #include <sys/device.h> |
59 | #include <sys/extent.h> | | 59 | #include <sys/extent.h> |
60 | #include <sys/kernel.h> | | 60 | #include <sys/kernel.h> |
61 | #include <sys/malloc.h> | | 61 | #include <sys/malloc.h> |
62 | #include <sys/kthread.h> | | 62 | #include <sys/kthread.h> |
63 | | | 63 | |
64 | #include <sys/bus.h> | | 64 | #include <sys/bus.h> |
65 | #include <sys/intr.h> | | 65 | #include <sys/intr.h> |
| @@ -387,68 +387,52 @@ pcic_power(why, arg) | | | @@ -387,68 +387,52 @@ pcic_power(why, arg) |
387 | } | | 387 | } |
388 | | | 388 | |
389 | | | 389 | |
390 | /* | | 390 | /* |
391 | * attach a socket -- we don't know about irqs yet | | 391 | * attach a socket -- we don't know about irqs yet |
392 | */ | | 392 | */ |
393 | void | | 393 | void |
394 | pcic_attach_socket(h) | | 394 | pcic_attach_socket(h) |
395 | struct pcic_handle *h; | | 395 | struct pcic_handle *h; |
396 | { | | 396 | { |
397 | struct pcmciabus_attach_args paa; | | 397 | struct pcmciabus_attach_args paa; |
398 | struct pcic_softc *sc = (struct pcic_softc *)h->ph_parent; | | 398 | struct pcic_softc *sc = (struct pcic_softc *)h->ph_parent; |
399 | int locs[PCMCIABUSCF_NLOCS]; | | 399 | int locs[PCMCIABUSCF_NLOCS]; |
400 | char cs[4]; | | | |
401 | | | 400 | |
402 | /* initialize the rest of the handle */ | | 401 | /* initialize the rest of the handle */ |
403 | | | 402 | |
404 | h->shutdown = 0; | | 403 | h->shutdown = 0; |
405 | h->memalloc = 0; | | 404 | h->memalloc = 0; |
406 | h->ioalloc = 0; | | 405 | h->ioalloc = 0; |
407 | h->ih_irq = 0; | | 406 | h->ih_irq = 0; |
408 | | | 407 | |
409 | /* now, config one pcmcia device per socket */ | | 408 | /* now, config one pcmcia device per socket */ |
410 | | | 409 | |
411 | paa.paa_busname = "pcmcia"; | | 410 | paa.paa_busname = "pcmcia"; |
412 | paa.pct = (pcmcia_chipset_tag_t) sc->pct; | | 411 | paa.pct = (pcmcia_chipset_tag_t) sc->pct; |
413 | paa.pch = (pcmcia_chipset_handle_t) h; | | 412 | paa.pch = (pcmcia_chipset_handle_t) h; |
414 | paa.iobase = sc->iobase; | | 413 | paa.iobase = sc->iobase; |
415 | paa.iosize = sc->iosize; | | 414 | paa.iosize = sc->iosize; |
416 | | | 415 | |
417 | locs[PCMCIABUSCF_CONTROLLER] = h->chip; | | 416 | locs[PCMCIABUSCF_CONTROLLER] = h->chip; |
418 | locs[PCMCIABUSCF_SOCKET] = h->socket; | | 417 | locs[PCMCIABUSCF_SOCKET] = h->socket; |
419 | | | 418 | |
420 | h->pcmcia = config_found_sm_loc(&sc->dev, "pcmciabus", locs, &paa, | | 419 | h->pcmcia = config_found_sm_loc(&sc->dev, "pcmciabus", locs, &paa, |
421 | pcic_print, config_stdsubmatch); | | 420 | pcic_print, config_stdsubmatch); |
422 | if (h->pcmcia == NULL) { | | 421 | if (h->pcmcia == NULL) { |
423 | h->flags &= ~PCIC_FLAG_SOCKETP; | | 422 | h->flags &= ~PCIC_FLAG_SOCKETP; |
424 | return; | | 423 | return; |
425 | } | | 424 | } |
426 | | | 425 | |
427 | /* | | | |
428 | * queue creation of a kernel thread to handle insert/removal events. | | | |
429 | */ | | | |
430 | #ifdef DIAGNOSTIC | | | |
431 | if (h->event_thread != NULL) | | | |
432 | panic("pcic_attach_socket: event thread"); | | | |
433 | #endif | | | |
434 | config_pending_incr(); | | | |
435 | snprintf(cs, sizeof(cs), "%d,%d", h->chip, h->socket); | | | |
436 | | | | |
437 | if (kthread_create(PRI_NONE, 0, NULL, pcic_event_thread, h, | | | |
438 | &h->event_thread, "%s,%s", device_xname(h->ph_parent), cs)) { | | | |
439 | aprint_error_dev(h->ph_parent, "unable to create event thread for sock 0x%02x\n", h->sock); | | | |
440 | panic("pcic_attach_socket"); | | | |
441 | } | | | |
442 | } | | 426 | } |
443 | | | 427 | |
444 | /* | | 428 | /* |
445 | * now finish attaching the sockets, we are ready to allocate | | 429 | * now finish attaching the sockets, we are ready to allocate |
446 | * interrupts | | 430 | * interrupts |
447 | */ | | 431 | */ |
448 | void | | 432 | void |
449 | pcic_attach_sockets_finish(sc) | | 433 | pcic_attach_sockets_finish(sc) |
450 | struct pcic_softc *sc; | | 434 | struct pcic_softc *sc; |
451 | { | | 435 | { |
452 | int i; | | 436 | int i; |
453 | | | 437 | |
454 | for (i = 0; i < __arraycount(sc->handle); i++) | | 438 | for (i = 0; i < __arraycount(sc->handle); i++) |
| @@ -456,26 +440,27 @@ pcic_attach_sockets_finish(sc) | | | @@ -456,26 +440,27 @@ pcic_attach_sockets_finish(sc) |
456 | pcic_attach_socket_finish(&sc->handle[i]); | | 440 | pcic_attach_socket_finish(&sc->handle[i]); |
457 | } | | 441 | } |
458 | | | 442 | |
459 | /* | | 443 | /* |
460 | * finishing attaching the socket. Interrupts may now be on | | 444 | * finishing attaching the socket. Interrupts may now be on |
461 | * if so expects the pcic interrupt to be blocked | | 445 | * if so expects the pcic interrupt to be blocked |
462 | */ | | 446 | */ |
463 | void | | 447 | void |
464 | pcic_attach_socket_finish(h) | | 448 | pcic_attach_socket_finish(h) |
465 | struct pcic_handle *h; | | 449 | struct pcic_handle *h; |
466 | { | | 450 | { |
467 | struct pcic_softc *sc = (struct pcic_softc *)h->ph_parent; | | 451 | struct pcic_softc *sc = (struct pcic_softc *)h->ph_parent; |
468 | int reg; | | 452 | int reg; |
| | | 453 | char cs[4]; |
469 | | | 454 | |
470 | DPRINTF(("%s: attach finish socket %ld\n", device_xname(h->ph_parent), | | 455 | DPRINTF(("%s: attach finish socket %ld\n", device_xname(h->ph_parent), |
471 | (long) (h - &sc->handle[0]))); | | 456 | (long) (h - &sc->handle[0]))); |
472 | | | 457 | |
473 | /* | | 458 | /* |
474 | * Set up a powerhook to ensure it continues to interrupt on | | 459 | * Set up a powerhook to ensure it continues to interrupt on |
475 | * card detect even after suspend. | | 460 | * card detect even after suspend. |
476 | * (this works around a bug seen in suspend-to-disk on the | | 461 | * (this works around a bug seen in suspend-to-disk on the |
477 | * Sony VAIO Z505; on resume, the CSC_INTR state is not preserved). | | 462 | * Sony VAIO Z505; on resume, the CSC_INTR state is not preserved). |
478 | */ | | 463 | */ |
479 | powerhook_establish(device_xname(h->ph_parent), pcic_power, h); | | 464 | powerhook_establish(device_xname(h->ph_parent), pcic_power, h); |
480 | | | 465 | |
481 | /* enable interrupts on card detect, poll for them if no irq avail */ | | 466 | /* enable interrupts on card detect, poll for them if no irq avail */ |
| @@ -510,26 +495,42 @@ pcic_attach_socket_finish(h) | | | @@ -510,26 +495,42 @@ pcic_attach_socket_finish(h) |
510 | pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg); | | 495 | pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg); |
511 | } | | 496 | } |
512 | } | | 497 | } |
513 | | | 498 | |
514 | /* if there's a card there, then attach it. */ | | 499 | /* if there's a card there, then attach it. */ |
515 | reg = pcic_read(h, PCIC_IF_STATUS); | | 500 | reg = pcic_read(h, PCIC_IF_STATUS); |
516 | if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) == | | 501 | if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) == |
517 | PCIC_IF_STATUS_CARDDETECT_PRESENT) { | | 502 | PCIC_IF_STATUS_CARDDETECT_PRESENT) { |
518 | pcic_queue_event(h, PCIC_EVENT_INSERTION); | | 503 | pcic_queue_event(h, PCIC_EVENT_INSERTION); |
519 | h->laststate = PCIC_LASTSTATE_PRESENT; | | 504 | h->laststate = PCIC_LASTSTATE_PRESENT; |
520 | } else { | | 505 | } else { |
521 | h->laststate = PCIC_LASTSTATE_EMPTY; | | 506 | h->laststate = PCIC_LASTSTATE_EMPTY; |
522 | } | | 507 | } |
| | | 508 | |
| | | 509 | /* |
| | | 510 | * queue creation of a kernel thread to handle insert/removal events. |
| | | 511 | */ |
| | | 512 | #ifdef DIAGNOSTIC |
| | | 513 | if (h->event_thread != NULL) |
| | | 514 | panic("pcic_attach_socket: event thread"); |
| | | 515 | #endif |
| | | 516 | config_pending_incr(); |
| | | 517 | snprintf(cs, sizeof(cs), "%d,%d", h->chip, h->socket); |
| | | 518 | |
| | | 519 | if (kthread_create(PRI_NONE, 0, NULL, pcic_event_thread, h, |
| | | 520 | &h->event_thread, "%s,%s", device_xname(h->ph_parent), cs)) { |
| | | 521 | aprint_error_dev(h->ph_parent, "unable to create event thread for sock 0x%02x\n", h->sock); |
| | | 522 | panic("pcic_attach_socket"); |
| | | 523 | } |
523 | } | | 524 | } |
524 | | | 525 | |
525 | void | | 526 | void |
526 | pcic_event_thread(arg) | | 527 | pcic_event_thread(arg) |
527 | void *arg; | | 528 | void *arg; |
528 | { | | 529 | { |
529 | struct pcic_handle *h = arg; | | 530 | struct pcic_handle *h = arg; |
530 | struct pcic_event *pe; | | 531 | struct pcic_event *pe; |
531 | int s, first = 1; | | 532 | int s, first = 1; |
532 | struct pcic_softc *sc = (struct pcic_softc *)h->ph_parent; | | 533 | struct pcic_softc *sc = (struct pcic_softc *)h->ph_parent; |
533 | | | 534 | |
534 | while (h->shutdown == 0) { | | 535 | while (h->shutdown == 0) { |
535 | /* | | 536 | /* |