root/dev/ic/i82365.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pcic_ident_ok
  2. pcic_vendor
  3. pcic_attach
  4. pcic_attach_sockets
  5. pcic_attach_socket
  6. pcic_create_event_thread
  7. pcic_event_thread
  8. pcic_event_process
  9. pcic_init_socket
  10. pcic_submatch
  11. pcic_print
  12. pcic_intr
  13. pcic_poll_intr
  14. pcic_intr_socket
  15. pcic_queue_event
  16. pcic_attach_card
  17. pcic_detach_card
  18. pcic_deactivate_card
  19. pcic_power
  20. pcic_chip_mem_alloc
  21. pcic_chip_mem_free
  22. pcic_chip_do_mem_map
  23. pcic_chip_mem_map
  24. pcic_chip_mem_unmap
  25. pcic_chip_io_alloc
  26. pcic_chip_io_free
  27. pcic_chip_do_io_map
  28. pcic_chip_io_map
  29. pcic_chip_io_unmap
  30. pcic_wait_ready
  31. pcic_chip_socket_enable
  32. pcic_chip_socket_disable
  33. st_pcic_read
  34. st_pcic_write

    1 /*      $OpenBSD: i82365.c,v 1.25 2005/11/23 11:39:37 mickey Exp $      */
    2 /*      $NetBSD: i82365.c,v 1.10 1998/06/09 07:36:55 thorpej Exp $      */
    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/types.h>
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/device.h>
   37 #include <sys/extent.h>
   38 #include <sys/kernel.h>
   39 #include <sys/malloc.h>
   40 #include <sys/kthread.h>
   41 
   42 #include <uvm/uvm_extern.h>
   43 
   44 #include <machine/bus.h>
   45 #include <machine/intr.h>
   46 
   47 #include <dev/pcmcia/pcmciareg.h>
   48 #include <dev/pcmcia/pcmciavar.h>
   49 
   50 #include <dev/ic/i82365reg.h>
   51 #include <dev/ic/i82365var.h>
   52 
   53 #ifdef PCICDEBUG
   54 #define DPRINTF(arg)    printf arg;
   55 #else
   56 #define DPRINTF(arg)
   57 #endif
   58 
   59 #define PCIC_VENDOR_UNKNOWN             0
   60 #define PCIC_VENDOR_I82365SLR0          1
   61 #define PCIC_VENDOR_I82365SLR1          2
   62 #define PCIC_VENDOR_I82365SLR2          3
   63 #define PCIC_VENDOR_CIRRUS_PD6710       4
   64 #define PCIC_VENDOR_CIRRUS_PD672X       5
   65 #define PCIC_VENDOR_VADEM_VG468         6
   66 #define PCIC_VENDOR_VADEM_VG469         7
   67 
   68 static char *pcic_vendor_to_string[] = {
   69         "Unknown",
   70         "Intel 82365SL rev 0",
   71         "Intel 82365SL rev 1",
   72         "Intel 82365SL rev 2",
   73         "Cirrus PD6710",
   74         "Cirrus PD672X",
   75         "Vadem VG468",
   76         "Vadem VG469",
   77 };
   78 
   79 /*
   80  * Individual drivers will allocate their own memory and io regions. Memory
   81  * regions must be a multiple of 4k, aligned on a 4k boundary.
   82  */
   83 
   84 #define PCIC_MEM_ALIGN  PCIC_MEM_PAGESIZE
   85 
   86 void    pcic_attach_socket(struct pcic_handle *);
   87 void    pcic_init_socket(struct pcic_handle *);
   88 
   89 int     pcic_submatch(struct device *, void *, void *);
   90 int     pcic_print(void *arg, const char *pnp);
   91 int     pcic_intr_socket(struct pcic_handle *);
   92 
   93 void    pcic_attach_card(struct pcic_handle *);
   94 void    pcic_detach_card(struct pcic_handle *, int);
   95 void    pcic_deactivate_card(struct pcic_handle *);
   96 
   97 void    pcic_chip_do_mem_map(struct pcic_handle *, int);
   98 void    pcic_chip_do_io_map(struct pcic_handle *, int);
   99 
  100 void    pcic_create_event_thread(void *);
  101 void    pcic_event_thread(void *);
  102 void    pcic_event_process(struct pcic_handle *, struct pcic_event *);
  103 void    pcic_queue_event(struct pcic_handle *, int);
  104 
  105 void    pcic_wait_ready(struct pcic_handle *);
  106 
  107 u_int8_t st_pcic_read(struct pcic_handle *, int);
  108 void    st_pcic_write(struct pcic_handle *, int, int);
  109 
  110 struct cfdriver pcic_cd = {
  111         NULL, "pcic", DV_DULL
  112 };
  113 
  114 int
  115 pcic_ident_ok(ident)
  116         int ident;
  117 {
  118         /* this is very empirical and heuristic */
  119 
  120         if (ident == 0 || ident == 0xff || (ident & PCIC_IDENT_ZERO))
  121                 return (0);
  122 
  123         if ((ident & PCIC_IDENT_IFTYPE_MASK) != PCIC_IDENT_IFTYPE_MEM_AND_IO) {
  124 #ifdef DIAGNOSTIC
  125                 printf("pcic: does not support memory and I/O cards, "
  126                     "ignored (ident=%0x)\n", ident);
  127 #endif
  128                 return (0);
  129         }
  130         return (1);
  131 }
  132 
  133 int
  134 pcic_vendor(h)
  135         struct pcic_handle *h;
  136 {
  137         int vendor, reg;
  138 
  139         /*
  140          * the chip_id of the cirrus toggles between 11 and 00 after a write.
  141          * weird.
  142          */
  143 
  144         pcic_write(h, PCIC_CIRRUS_CHIP_INFO, 0);
  145         reg = pcic_read(h, -1);
  146 
  147         if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) ==
  148             PCIC_CIRRUS_CHIP_INFO_CHIP_ID) {
  149                 reg = pcic_read(h, -1);
  150                 if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) {
  151                         if (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS)
  152                                 return (PCIC_VENDOR_CIRRUS_PD672X);
  153                         else
  154                                 return (PCIC_VENDOR_CIRRUS_PD6710);
  155                 }
  156         }
  157 
  158         reg = pcic_read(h, PCIC_IDENT);
  159 
  160         switch (reg) {
  161         case PCIC_IDENT_REV_I82365SLR0:
  162                 vendor = PCIC_VENDOR_I82365SLR0;
  163                 break;
  164         case PCIC_IDENT_REV_I82365SLR1:
  165                 vendor = PCIC_VENDOR_I82365SLR1;
  166                 break;
  167         case PCIC_IDENT_REV_I82365SLR2:
  168                 vendor = PCIC_VENDOR_I82365SLR2;
  169                 break;
  170         default:
  171                 vendor = PCIC_VENDOR_UNKNOWN;
  172                 break;
  173         }
  174 
  175         pcic_write(h, 0x0e, -1);
  176         pcic_write(h, 0x37, -1);
  177 
  178         reg = pcic_read(h, PCIC_VG468_MISC);
  179         reg |= PCIC_VG468_MISC_VADEMREV;
  180         pcic_write(h, PCIC_VG468_MISC, reg);
  181 
  182         reg = pcic_read(h, PCIC_IDENT);
  183 
  184         if (reg & PCIC_IDENT_VADEM_MASK) {
  185                 if ((reg & 7) >= 4)
  186                         vendor = PCIC_VENDOR_VADEM_VG469;
  187                 else
  188                         vendor = PCIC_VENDOR_VADEM_VG468;
  189 
  190                 reg = pcic_read(h, PCIC_VG468_MISC);
  191                 reg &= ~PCIC_VG468_MISC_VADEMREV;
  192                 pcic_write(h, PCIC_VG468_MISC, reg);
  193         }
  194 
  195         return (vendor);
  196 }
  197 
  198 void
  199 pcic_attach(sc)
  200         struct pcic_softc *sc;
  201 {
  202         int vendor, count, i, reg;
  203 
  204         /* now check for each controller/socket */
  205 
  206         /*
  207          * this could be done with a loop, but it would violate the
  208          * abstraction
  209          */
  210 
  211         count = 0;
  212 
  213         DPRINTF(("pcic ident regs:"));
  214 
  215         sc->handle[0].ph_parent = (struct device *)sc;
  216         sc->handle[0].sock = C0SA;
  217         /* initialise pcic_read and pcic_write functions */
  218         sc->handle[0].ph_read = st_pcic_read;
  219         sc->handle[0].ph_write = st_pcic_write;
  220         sc->handle[0].ph_bus_t = sc->iot;
  221         sc->handle[0].ph_bus_h = sc->ioh;
  222         if (pcic_ident_ok(reg = pcic_read(&sc->handle[0], PCIC_IDENT))) {
  223                 sc->handle[0].flags = PCIC_FLAG_SOCKETP;
  224                 count++;
  225         } else {
  226                 sc->handle[0].flags = 0;
  227         }
  228         sc->handle[0].laststate = PCIC_LASTSTATE_EMPTY;
  229 
  230         DPRINTF((" 0x%02x", reg));
  231 
  232         sc->handle[1].ph_parent = (struct device *)sc;
  233         sc->handle[1].sock = C0SB;
  234         /* initialise pcic_read and pcic_write functions */
  235         sc->handle[1].ph_read = st_pcic_read;
  236         sc->handle[1].ph_write = st_pcic_write;
  237         sc->handle[1].ph_bus_t = sc->iot;
  238         sc->handle[1].ph_bus_h = sc->ioh;
  239         if (pcic_ident_ok(reg = pcic_read(&sc->handle[1], PCIC_IDENT))) {
  240                 sc->handle[1].flags = PCIC_FLAG_SOCKETP;
  241                 count++;
  242         } else {
  243                 sc->handle[1].flags = 0;
  244         }
  245         sc->handle[1].laststate = PCIC_LASTSTATE_EMPTY;
  246 
  247         DPRINTF((" 0x%02x", reg));
  248 
  249         /*
  250          * The CL-PD6729 has only one controller and always returns 0
  251          * if you try to read from the second one. Maybe pcic_ident_ok
  252          * shouldn't accept 0?
  253          */
  254         sc->handle[2].ph_parent = (struct device *)sc;
  255         sc->handle[2].sock = C1SA;
  256         /* initialise pcic_read and pcic_write functions */
  257         sc->handle[2].ph_read = st_pcic_read;
  258         sc->handle[2].ph_write = st_pcic_write;
  259         sc->handle[2].ph_bus_t = sc->iot;
  260         sc->handle[2].ph_bus_h = sc->ioh;
  261         if (pcic_vendor(&sc->handle[0]) != PCIC_VENDOR_CIRRUS_PD672X ||
  262             pcic_read(&sc->handle[2], PCIC_IDENT) != 0) {
  263                 if (pcic_ident_ok(reg = pcic_read(&sc->handle[2],
  264                     PCIC_IDENT))) {
  265                         sc->handle[2].flags = PCIC_FLAG_SOCKETP;
  266                         count++;
  267                 } else {
  268                         sc->handle[2].flags = 0;
  269                 }
  270                 sc->handle[2].laststate = PCIC_LASTSTATE_EMPTY;
  271 
  272                 DPRINTF((" 0x%02x", reg));
  273 
  274                 sc->handle[3].ph_parent = (struct device *)sc;
  275                 sc->handle[3].sock = C1SB;
  276                 /* initialise pcic_read and pcic_write functions */
  277                 sc->handle[3].ph_read = st_pcic_read;
  278                 sc->handle[3].ph_write = st_pcic_write;
  279                 sc->handle[3].ph_bus_t = sc->iot;
  280                 sc->handle[3].ph_bus_h = sc->ioh;
  281                 if (pcic_ident_ok(reg = pcic_read(&sc->handle[3],
  282                     PCIC_IDENT))) {
  283                         sc->handle[3].flags = PCIC_FLAG_SOCKETP;
  284                         count++;
  285                 } else {
  286                         sc->handle[3].flags = 0;
  287                 }
  288                 sc->handle[3].laststate = PCIC_LASTSTATE_EMPTY;
  289 
  290                 DPRINTF((" 0x%02x\n", reg));
  291         } else {
  292                 sc->handle[2].flags = 0;
  293                 sc->handle[3].flags = 0;
  294         }
  295 
  296         if (count == 0)
  297                 return;
  298 
  299         /* establish the interrupt */
  300 
  301         /* XXX block interrupts? */
  302 
  303         for (i = 0; i < PCIC_NSLOTS; i++) {
  304                 /*
  305                  * this should work, but w/o it, setting tty flags hangs at
  306                  * boot time.
  307                  */
  308                 if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) {
  309                         SIMPLEQ_INIT(&sc->handle[i].events);
  310                         pcic_write(&sc->handle[i], PCIC_CSC_INTR, 0);
  311                         pcic_read(&sc->handle[i], PCIC_CSC);
  312                 }
  313         }
  314 
  315         for (i = 0; i < PCIC_NSLOTS; i += 2) {
  316                 if ((sc->handle[i+0].flags & PCIC_FLAG_SOCKETP) ||
  317                     (sc->handle[i+1].flags & PCIC_FLAG_SOCKETP)) {
  318                         vendor = pcic_vendor(&sc->handle[i]);
  319 
  320                         printf("%s controller %d: <%s> has socket",
  321                             sc->dev.dv_xname, i/2,
  322                             pcic_vendor_to_string[vendor]);
  323 
  324                         if ((sc->handle[i+0].flags & PCIC_FLAG_SOCKETP) &&
  325                             (sc->handle[i+1].flags & PCIC_FLAG_SOCKETP))
  326                                 printf("s A and B\n");
  327                         else if (sc->handle[i+0].flags & PCIC_FLAG_SOCKETP)
  328                                 printf(" A only\n");
  329                         else
  330                                 printf(" B only\n");
  331 
  332                         if (sc->handle[i+0].flags & PCIC_FLAG_SOCKETP)
  333                                 sc->handle[i+0].vendor = vendor;
  334                         if (sc->handle[i+1].flags & PCIC_FLAG_SOCKETP)
  335                                 sc->handle[i+1].vendor = vendor;
  336                 }
  337         }
  338 }
  339 
  340 void
  341 pcic_attach_sockets(sc)
  342         struct pcic_softc *sc;
  343 {
  344         int i;
  345 
  346         for (i = 0; i < PCIC_NSLOTS; i++)
  347                 if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
  348                         pcic_attach_socket(&sc->handle[i]);
  349 }
  350 
  351 void
  352 pcic_attach_socket(h)
  353         struct pcic_handle *h;
  354 {
  355         struct pcmciabus_attach_args paa;
  356         struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
  357 
  358         /* initialize the rest of the handle */
  359 
  360         h->shutdown = 0;
  361         h->memalloc = 0;
  362         h->ioalloc = 0;
  363         h->ih_irq = 0;
  364 
  365         /* now, config one pcmcia device per socket */
  366 
  367         paa.paa_busname = "pcmcia";
  368         paa.pct = (pcmcia_chipset_tag_t) sc->pct;
  369         paa.pch = (pcmcia_chipset_handle_t) h;
  370         paa.iobase = sc->iobase;
  371         paa.iosize = sc->iosize;
  372 
  373         h->pcmcia = config_found_sm(&sc->dev, &paa, pcic_print,
  374             pcic_submatch);
  375 
  376         /* if there's actually a pcmcia device attached, initialize the slot */
  377 
  378         if (h->pcmcia)
  379                 pcic_init_socket(h);
  380         else
  381                 h->flags &= ~PCIC_FLAG_SOCKETP;
  382 }
  383 
  384 void
  385 pcic_create_event_thread(arg)
  386         void *arg;
  387 {
  388         struct pcic_handle *h = arg;
  389         const char *cs;
  390 
  391         switch (h->sock) {
  392         case C0SA:
  393                 cs = "0,0";
  394                 break;
  395         case C0SB:
  396                 cs = "0,1";
  397                 break;
  398         case C1SA:
  399                 cs = "1,0";
  400                 break;
  401         case C1SB:
  402                 cs = "1,1";
  403                 break;
  404         default:
  405                 panic("pcic_create_event_thread: unknown pcic socket");
  406         }
  407 
  408         if (kthread_create(pcic_event_thread, h, &h->event_thread,
  409             "%s,%s", h->ph_parent->dv_xname, cs)) {
  410                 printf("%s: unable to create event thread for sock 0x%02x\n",
  411                     h->ph_parent->dv_xname, h->sock);
  412                 panic("pcic_create_event_thread");
  413         }
  414 }
  415 
  416 void
  417 pcic_event_thread(arg)
  418         void *arg;
  419 {
  420         struct pcic_handle *h = arg;
  421         struct pcic_event *pe;
  422         int s;
  423         struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
  424 
  425         while (h->shutdown == 0) {
  426                 s = splhigh();
  427                 if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) {
  428                         splx(s);
  429                         (void) tsleep(&h->events, PWAIT, "pcicev", 0);
  430                         continue;
  431                 } else {
  432                         splx(s);
  433                         /* sleep .25s to be enqueued chatterling interrupts */
  434                         (void) tsleep((caddr_t)pcic_event_thread, PWAIT,
  435                             "pcicss", hz/4);
  436                 }
  437                 pcic_event_process(h, pe);
  438         }
  439 
  440         h->event_thread = NULL;
  441 
  442         /* In case parent is waiting for us to exit. */
  443         wakeup(sc);
  444 
  445         kthread_exit(0);
  446 }
  447 
  448 void
  449 pcic_event_process(h, pe)
  450         struct pcic_handle *h;
  451         struct pcic_event *pe;
  452 {
  453         int s;
  454 
  455         s = splhigh();
  456         SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
  457         splx(s);
  458 
  459         switch (pe->pe_type) {
  460         case PCIC_EVENT_INSERTION:
  461                 s = splhigh();
  462                 while (1) {
  463                         struct pcic_event *pe1, *pe2;
  464 
  465                         if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
  466                                 break;
  467                         if (pe1->pe_type != PCIC_EVENT_REMOVAL)
  468                                 break;
  469                         if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
  470                                 break;
  471                         if (pe2->pe_type == PCIC_EVENT_INSERTION) {
  472                                 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
  473                                 free(pe1, M_TEMP);
  474                                 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
  475                                 free(pe2, M_TEMP);
  476                         }
  477                 }
  478                 splx(s);
  479                                 
  480                 DPRINTF(("%s: insertion event\n", h->ph_parent->dv_xname));
  481                 pcic_attach_card(h);
  482                 break;
  483 
  484         case PCIC_EVENT_REMOVAL:
  485                 s = splhigh();
  486                 while (1) {
  487                         struct pcic_event *pe1, *pe2;
  488 
  489                         if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
  490                                 break;
  491                         if (pe1->pe_type != PCIC_EVENT_INSERTION)
  492                                 break;
  493                         if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
  494                                 break;
  495                         if (pe2->pe_type == PCIC_EVENT_REMOVAL) {
  496                                 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
  497                                 free(pe1, M_TEMP);
  498                                 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
  499                                 free(pe2, M_TEMP);
  500                         }
  501                 }
  502                 splx(s);
  503 
  504                 DPRINTF(("%s: removal event\n", h->ph_parent->dv_xname));
  505                 pcic_detach_card(h, DETACH_FORCE);
  506                 break;
  507 
  508         default:
  509                 panic("pcic_event_thread: unknown event %d", pe->pe_type);
  510         }
  511         free(pe, M_TEMP);
  512 }
  513 
  514 void
  515 pcic_init_socket(h)
  516         struct pcic_handle *h;
  517 {
  518         int reg;
  519         struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
  520 
  521         /*
  522          * queue creation of a kernel thread to handle insert/removal events.
  523          */
  524 #ifdef DIAGNOSTIC
  525         if (h->event_thread != NULL)
  526                 panic("pcic_attach_socket: event thread");
  527 #endif
  528         kthread_create_deferred(pcic_create_event_thread, h);
  529 
  530         /* set up the card to interrupt on card detect */
  531 
  532         pcic_write(h, PCIC_CSC_INTR, (sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) |
  533             PCIC_CSC_INTR_CD_ENABLE);
  534         pcic_write(h, PCIC_INTR, 0);
  535         pcic_read(h, PCIC_CSC);
  536 
  537         /* unsleep the cirrus controller */
  538 
  539         if ((h->vendor == PCIC_VENDOR_CIRRUS_PD6710) ||
  540             (h->vendor == PCIC_VENDOR_CIRRUS_PD672X)) {
  541                 reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2);
  542                 if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) {
  543                         DPRINTF(("%s: socket %02x was suspended\n",
  544                             h->ph_parent->dv_xname, h->sock));
  545                         reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND;
  546                         pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg);
  547                 }
  548         }
  549         /* if there's a card there, then attach it. */
  550 
  551         reg = pcic_read(h, PCIC_IF_STATUS);
  552 
  553         if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
  554             PCIC_IF_STATUS_CARDDETECT_PRESENT) {
  555                 pcic_attach_card(h);
  556                 h->laststate = PCIC_LASTSTATE_PRESENT;
  557         } else
  558                 h->laststate = PCIC_LASTSTATE_EMPTY;
  559 }
  560 
  561 int
  562 pcic_submatch(parent, match, aux)
  563         struct device *parent;
  564         void *match, *aux;
  565 {
  566         struct cfdata *cf = match;
  567         struct pcmciabus_attach_args *paa = aux;
  568         struct pcic_handle *h = (struct pcic_handle *) paa->pch;
  569 
  570         switch (h->sock) {
  571         case C0SA:
  572                 if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
  573                     -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
  574                     cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 0)
  575                         return 0;
  576                 if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
  577                     -1 /* PCICCF_SOCKET_DEFAULT */ &&
  578                     cf->cf_loc[1 /* PCICCF_SOCKET */] != 0)
  579                         return 0;
  580 
  581                 break;
  582         case C0SB:
  583                 if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
  584                     -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
  585                     cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 0)
  586                         return 0;
  587                 if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
  588                     -1 /* PCICCF_SOCKET_DEFAULT */ &&
  589                     cf->cf_loc[1 /* PCICCF_SOCKET */] != 1)
  590                         return 0;
  591 
  592                 break;
  593         case C1SA:
  594                 if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
  595                     -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
  596                     cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 1)
  597                         return 0;
  598                 if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
  599                     -1 /* PCICCF_SOCKET_DEFAULT */ &&
  600                     cf->cf_loc[1 /* PCICCF_SOCKET */] != 0)
  601                         return 0;
  602 
  603                 break;
  604         case C1SB:
  605                 if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
  606                     -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
  607                     cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 1)
  608                         return 0;
  609                 if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
  610                     -1 /* PCICCF_SOCKET_DEFAULT */ &&
  611                     cf->cf_loc[1 /* PCICCF_SOCKET */] != 1)
  612                         return 0;
  613 
  614                 break;
  615         default:
  616                 panic("unknown pcic socket");
  617         }
  618 
  619         return ((*cf->cf_attach->ca_match)(parent, cf, aux));
  620 }
  621 
  622 int
  623 pcic_print(arg, pnp)
  624         void *arg;
  625         const char *pnp;
  626 {
  627         struct pcmciabus_attach_args *paa = arg;
  628         struct pcic_handle *h = (struct pcic_handle *) paa->pch;
  629 
  630         /* Only "pcmcia"s can attach to "pcic"s... easy. */
  631         if (pnp)
  632                 printf("pcmcia at %s", pnp);
  633 
  634         switch (h->sock) {
  635         case C0SA:
  636                 printf(" controller 0 socket 0");
  637                 break;
  638         case C0SB:
  639                 printf(" controller 0 socket 1");
  640                 break;
  641         case C1SA:
  642                 printf(" controller 1 socket 0");
  643                 break;
  644         case C1SB:
  645                 printf(" controller 1 socket 1");
  646                 break;
  647         default:
  648                 panic("unknown pcic socket");
  649         }
  650 
  651         return (UNCONF);
  652 }
  653 
  654 int
  655 pcic_intr(arg)
  656         void *arg;
  657 {
  658         struct pcic_softc *sc = arg;
  659         int i, ret = 0;
  660 
  661         DPRINTF(("%s: intr\n", sc->dev.dv_xname));
  662 
  663         for (i = 0; i < PCIC_NSLOTS; i++)
  664                 if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
  665                         ret += pcic_intr_socket(&sc->handle[i]);
  666 
  667         return (ret ? 1 : 0);
  668 }
  669 
  670 void
  671 pcic_poll_intr(arg)
  672         void *arg;
  673 {
  674         struct pcic_softc *sc = arg;
  675         int i, s;
  676 
  677         /*
  678          * Since we're polling, we aren't in interrupt context, so block any
  679          * actual interrupts coming from the pcic.
  680          */
  681         s = spltty();
  682 
  683         for (i = 0; i < PCIC_NSLOTS; i++)
  684                 if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
  685                         pcic_intr_socket(&sc->handle[i]);
  686 
  687         timeout_add(&sc->poll_timeout, hz / 2);
  688 
  689         splx(s);
  690 }
  691 
  692 int
  693 pcic_intr_socket(h)
  694         struct pcic_handle *h;
  695 {
  696         int cscreg;
  697 
  698         cscreg = pcic_read(h, PCIC_CSC);
  699 
  700         cscreg &= (PCIC_CSC_GPI |
  701                    PCIC_CSC_CD |
  702                    PCIC_CSC_READY |
  703                    PCIC_CSC_BATTWARN |
  704                    PCIC_CSC_BATTDEAD);
  705 
  706         if (cscreg & PCIC_CSC_GPI) {
  707                 DPRINTF(("%s: %02x GPI\n", h->ph_parent->dv_xname, h->sock));
  708         }
  709         if (cscreg & PCIC_CSC_CD) {
  710                 int statreg;
  711 
  712                 statreg = pcic_read(h, PCIC_IF_STATUS);
  713 
  714                 DPRINTF(("%s: %02x CD %x\n", h->ph_parent->dv_xname, h->sock,
  715                     statreg));
  716 
  717                 if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
  718                     PCIC_IF_STATUS_CARDDETECT_PRESENT) {
  719                         if (h->laststate != PCIC_LASTSTATE_PRESENT) {
  720                                 DPRINTF(("%s: enqueing INSERTION event\n",
  721                                     h->ph_parent->dv_xname));
  722                                 pcic_queue_event(h, PCIC_EVENT_INSERTION);
  723                         }
  724                         h->laststate = PCIC_LASTSTATE_PRESENT;
  725                 } else {
  726                         if (h->laststate == PCIC_LASTSTATE_PRESENT) {
  727                                 /* Deactivate the card now. */
  728                                 DPRINTF(("%s: deactivating card\n",
  729                                     h->ph_parent->dv_xname));
  730                                 pcic_deactivate_card(h);
  731 
  732                                 DPRINTF(("%s: enqueing REMOVAL event\n",
  733                                     h->ph_parent->dv_xname));
  734                                 pcic_queue_event(h, PCIC_EVENT_REMOVAL);
  735                         }
  736                         h->laststate =
  737                             ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == 0)
  738                             ? PCIC_LASTSTATE_EMPTY : PCIC_LASTSTATE_HALF;
  739                 }
  740         }
  741         if (cscreg & PCIC_CSC_READY) {
  742                 DPRINTF(("%s: %02x READY\n", h->ph_parent->dv_xname, h->sock));
  743                 /* shouldn't happen */
  744         }
  745         if (cscreg & PCIC_CSC_BATTWARN) {
  746                 DPRINTF(("%s: %02x BATTWARN\n", h->ph_parent->dv_xname,
  747                     h->sock));
  748         }
  749         if (cscreg & PCIC_CSC_BATTDEAD) {
  750                 DPRINTF(("%s: %02x BATTDEAD\n", h->ph_parent->dv_xname,
  751                     h->sock));
  752         }
  753         return (cscreg ? 1 : 0);
  754 }
  755 
  756 void
  757 pcic_queue_event(h, event)
  758         struct pcic_handle *h;
  759         int event;
  760 {
  761         struct pcic_event *pe;
  762         int s;
  763 
  764         pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
  765         if (pe == NULL)
  766                 panic("pcic_queue_event: can't allocate event");
  767 
  768         pe->pe_type = event;
  769         s = splhigh();
  770         SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q);
  771         splx(s);
  772         wakeup(&h->events);
  773 }
  774 
  775 void
  776 pcic_attach_card(h)
  777         struct pcic_handle *h;
  778 {
  779         if (h->flags & PCIC_FLAG_CARDP)
  780                 panic("pcic_attach_card: already attached");
  781 
  782         /* call the MI attach function */
  783         pcmcia_card_attach(h->pcmcia);
  784 
  785         h->flags |= PCIC_FLAG_CARDP;
  786 }
  787 
  788 void
  789 pcic_detach_card(h, flags)
  790         struct pcic_handle *h;
  791         int flags;              /* DETACH_* */
  792 {
  793 
  794         if (h->flags & PCIC_FLAG_CARDP) {
  795                 h->flags &= ~PCIC_FLAG_CARDP;
  796 
  797                 /* call the MI detach function */
  798                 pcmcia_card_detach(h->pcmcia, flags);
  799         } else {
  800                 DPRINTF(("pcic_detach_card: already detached"));
  801         }
  802 }
  803 
  804 void
  805 pcic_deactivate_card(h)
  806         struct pcic_handle *h;
  807 {
  808         struct device *dev = (struct device *)h->pcmcia;
  809 
  810         /*
  811          * At suspend, apm deactivates any connected cards. If we've woken up
  812          * to find a previously-connected device missing, and we're detaching
  813          * it, we don't want to deactivate it again.
  814          */
  815         if (dev->dv_flags & DVF_ACTIVE)
  816                 pcmcia_card_deactivate(h->pcmcia);
  817 
  818         /* power down the socket */
  819         pcic_write(h, PCIC_PWRCTL, 0);
  820 
  821         /* reset the socket */
  822         pcic_write(h, PCIC_INTR, 0);
  823 }
  824 
  825 /*
  826  * The pcic_power() function must execute BEFORE the pcmcia_power() hooks.
  827  * During suspend, a card may have been ejected. If so, we must detach it
  828  * completely before pcmcia_power() tries to activate it. Attempting to
  829  * activate a card that isn't there is bad news.
  830  */
  831 void
  832 pcic_power(why, arg)
  833         int why;
  834         void *arg;
  835 {
  836         struct pcic_handle *h = (struct pcic_handle *)arg;
  837         struct pcic_softc *sc = (struct pcic_softc *)h->ph_parent;
  838         struct pcic_event *pe;
  839 
  840         if (why != PWR_RESUME) {
  841                 if (timeout_pending(&sc->poll_timeout))
  842                         timeout_del(&sc->poll_timeout);
  843         }
  844         else {
  845                 pcic_intr_socket(h);
  846 
  847                 while ((pe = SIMPLEQ_FIRST(&h->events)))
  848                         pcic_event_process(h, pe);
  849 
  850                 timeout_add(&sc->poll_timeout, hz / 2);
  851         }
  852 }
  853 
  854 int 
  855 pcic_chip_mem_alloc(pch, size, pcmhp)
  856         pcmcia_chipset_handle_t pch;
  857         bus_size_t size;
  858         struct pcmcia_mem_handle *pcmhp;
  859 {
  860         struct pcic_handle *h = (struct pcic_handle *) pch;
  861         bus_space_handle_t memh;
  862         bus_addr_t addr;
  863         bus_size_t sizepg;
  864         int i, mask, mhandle;
  865         struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
  866 
  867         /* out of sc->memh, allocate as many pages as necessary */
  868 
  869         /* convert size to PCIC pages */
  870         sizepg = (size + (PCIC_MEM_ALIGN - 1)) / PCIC_MEM_ALIGN;
  871         if (sizepg > PCIC_MAX_MEM_PAGES)
  872                 return (1);
  873 
  874         mask = (1 << sizepg) - 1;
  875 
  876         addr = 0;               /* XXX gcc -Wuninitialized */
  877         mhandle = 0;            /* XXX gcc -Wuninitialized */
  878 
  879         for (i = 0; i <= PCIC_MAX_MEM_PAGES - sizepg; i++) {
  880                 if ((sc->subregionmask & (mask << i)) == (mask << i)) {
  881                         if (bus_space_subregion(sc->memt, sc->memh,
  882                             i * PCIC_MEM_PAGESIZE,
  883                             sizepg * PCIC_MEM_PAGESIZE, &memh))
  884                                 return (1);
  885                         mhandle = mask << i;
  886                         addr = sc->membase + (i * PCIC_MEM_PAGESIZE);
  887                         sc->subregionmask &= ~(mhandle);
  888                         pcmhp->memt = sc->memt;
  889                         pcmhp->memh = memh;
  890                         pcmhp->addr = addr;
  891                         pcmhp->size = size;
  892                         pcmhp->mhandle = mhandle;
  893                         pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE;
  894         
  895                         DPRINTF(("pcic_chip_mem_alloc bus addr 0x%lx+0x%lx\n",
  896                             (u_long) addr, (u_long) size));
  897 
  898                         return (0);
  899                 }
  900         }
  901 
  902         return (1);
  903 }
  904 
  905 void 
  906 pcic_chip_mem_free(pch, pcmhp)
  907         pcmcia_chipset_handle_t pch;
  908         struct pcmcia_mem_handle *pcmhp;
  909 {
  910         struct pcic_handle *h = (struct pcic_handle *) pch;
  911         struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
  912 
  913         sc->subregionmask |= pcmhp->mhandle;
  914 }
  915 
  916 static struct mem_map_index_st {
  917         int     sysmem_start_lsb;
  918         int     sysmem_start_msb;
  919         int     sysmem_stop_lsb;
  920         int     sysmem_stop_msb;
  921         int     cardmem_lsb;
  922         int     cardmem_msb;
  923         int     memenable;
  924 } mem_map_index[] = {
  925         {
  926                 PCIC_SYSMEM_ADDR0_START_LSB,
  927                 PCIC_SYSMEM_ADDR0_START_MSB,
  928                 PCIC_SYSMEM_ADDR0_STOP_LSB,
  929                 PCIC_SYSMEM_ADDR0_STOP_MSB,
  930                 PCIC_CARDMEM_ADDR0_LSB,
  931                 PCIC_CARDMEM_ADDR0_MSB,
  932                 PCIC_ADDRWIN_ENABLE_MEM0,
  933         },
  934         {
  935                 PCIC_SYSMEM_ADDR1_START_LSB,
  936                 PCIC_SYSMEM_ADDR1_START_MSB,
  937                 PCIC_SYSMEM_ADDR1_STOP_LSB,
  938                 PCIC_SYSMEM_ADDR1_STOP_MSB,
  939                 PCIC_CARDMEM_ADDR1_LSB,
  940                 PCIC_CARDMEM_ADDR1_MSB,
  941                 PCIC_ADDRWIN_ENABLE_MEM1,
  942         },
  943         {
  944                 PCIC_SYSMEM_ADDR2_START_LSB,
  945                 PCIC_SYSMEM_ADDR2_START_MSB,
  946                 PCIC_SYSMEM_ADDR2_STOP_LSB,
  947                 PCIC_SYSMEM_ADDR2_STOP_MSB,
  948                 PCIC_CARDMEM_ADDR2_LSB,
  949                 PCIC_CARDMEM_ADDR2_MSB,
  950                 PCIC_ADDRWIN_ENABLE_MEM2,
  951         },
  952         {
  953                 PCIC_SYSMEM_ADDR3_START_LSB,
  954                 PCIC_SYSMEM_ADDR3_START_MSB,
  955                 PCIC_SYSMEM_ADDR3_STOP_LSB,
  956                 PCIC_SYSMEM_ADDR3_STOP_MSB,
  957                 PCIC_CARDMEM_ADDR3_LSB,
  958                 PCIC_CARDMEM_ADDR3_MSB,
  959                 PCIC_ADDRWIN_ENABLE_MEM3,
  960         },
  961         {
  962                 PCIC_SYSMEM_ADDR4_START_LSB,
  963                 PCIC_SYSMEM_ADDR4_START_MSB,
  964                 PCIC_SYSMEM_ADDR4_STOP_LSB,
  965                 PCIC_SYSMEM_ADDR4_STOP_MSB,
  966                 PCIC_CARDMEM_ADDR4_LSB,
  967                 PCIC_CARDMEM_ADDR4_MSB,
  968                 PCIC_ADDRWIN_ENABLE_MEM4,
  969         },
  970 };
  971 
  972 void 
  973 pcic_chip_do_mem_map(h, win)
  974         struct pcic_handle *h;
  975         int win;
  976 {
  977         int reg;
  978         int kind = h->mem[win].kind & ~PCMCIA_WIDTH_MEM_MASK;
  979         int mem8 =
  980             (h->mem[win].kind & PCMCIA_WIDTH_MEM_MASK) == PCMCIA_WIDTH_MEM8
  981             || (kind == PCMCIA_MEM_ATTR);
  982 
  983         pcic_write(h, mem_map_index[win].sysmem_start_lsb,
  984             (h->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
  985         pcic_write(h, mem_map_index[win].sysmem_start_msb,
  986             ((h->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
  987             PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK) |
  988             (mem8 ? 0 : PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT));
  989 
  990         pcic_write(h, mem_map_index[win].sysmem_stop_lsb,
  991             ((h->mem[win].addr + h->mem[win].size) >>
  992             PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
  993         pcic_write(h, mem_map_index[win].sysmem_stop_msb,
  994             (((h->mem[win].addr + h->mem[win].size) >>
  995             (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
  996             PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) |
  997             PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2);
  998 
  999         pcic_write(h, mem_map_index[win].cardmem_lsb,
 1000             (h->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff);
 1001         pcic_write(h, mem_map_index[win].cardmem_msb,
 1002             ((h->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) &
 1003             PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) |
 1004             ((kind == PCMCIA_MEM_ATTR) ?
 1005             PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0));
 1006 
 1007         reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
 1008         reg |= (mem_map_index[win].memenable | PCIC_ADDRWIN_ENABLE_MEMCS16);
 1009         pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
 1010 
 1011 #ifdef PCICDEBUG
 1012         {
 1013                 int r1, r2, r3, r4, r5, r6;
 1014 
 1015                 r1 = pcic_read(h, mem_map_index[win].sysmem_start_msb);
 1016                 r2 = pcic_read(h, mem_map_index[win].sysmem_start_lsb);
 1017                 r3 = pcic_read(h, mem_map_index[win].sysmem_stop_msb);
 1018                 r4 = pcic_read(h, mem_map_index[win].sysmem_stop_lsb);
 1019                 r5 = pcic_read(h, mem_map_index[win].cardmem_msb);
 1020                 r6 = pcic_read(h, mem_map_index[win].cardmem_lsb);
 1021 
 1022                 DPRINTF(("pcic_chip_do_mem_map window %d: %02x%02x %02x%02x "
 1023                     "%02x%02x\n", win, r1, r2, r3, r4, r5, r6));
 1024         }
 1025 #endif
 1026 }
 1027 
 1028 int 
 1029 pcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
 1030         pcmcia_chipset_handle_t pch;
 1031         int kind;
 1032         bus_addr_t card_addr;
 1033         bus_size_t size;
 1034         struct pcmcia_mem_handle *pcmhp;
 1035         bus_size_t *offsetp;
 1036         int *windowp;
 1037 {
 1038         struct pcic_handle *h = (struct pcic_handle *) pch;
 1039         bus_addr_t busaddr;
 1040         long card_offset;
 1041         int i, win;
 1042         struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
 1043 
 1044         win = -1;
 1045         for (i = 0; i < (sizeof(mem_map_index) / sizeof(mem_map_index[0]));
 1046             i++) {
 1047                 if ((h->memalloc & (1 << i)) == 0) {
 1048                         win = i;
 1049                         h->memalloc |= (1 << i);
 1050                         break;
 1051                 }
 1052         }
 1053 
 1054         if (win == -1)
 1055                 return (1);
 1056 
 1057         *windowp = win;
 1058 
 1059         /* XXX this is pretty gross */
 1060 
 1061         if (sc->memt != pcmhp->memt)
 1062                 panic("pcic_chip_mem_map memt is bogus");
 1063 
 1064         busaddr = pcmhp->addr;
 1065 
 1066         /*
 1067          * Compute the address offset to the pcmcia address space for the
 1068          * pcic.  This is intentionally signed.  The masks and shifts below
 1069          * will cause TRT to happen in the pcic registers.  Deal with making
 1070          * sure the address is aligned, and return the alignment offset.
 1071          */
 1072 
 1073         *offsetp = card_addr % PCIC_MEM_ALIGN;
 1074         card_addr -= *offsetp;
 1075 
 1076         DPRINTF(("pcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr "
 1077             "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
 1078             (u_long) card_addr));
 1079 
 1080         /*
 1081          * include the offset in the size, and decrement size by one, since
 1082          * the hw wants start/stop
 1083          */
 1084         size += *offsetp - 1;
 1085 
 1086         card_offset = (((long) card_addr) - ((long) busaddr));
 1087 
 1088         h->mem[win].addr = busaddr;
 1089         h->mem[win].size = size;
 1090         h->mem[win].offset = card_offset;
 1091         h->mem[win].kind = kind;
 1092 
 1093         pcic_chip_do_mem_map(h, win);
 1094 
 1095         return (0);
 1096 }
 1097 
 1098 void 
 1099 pcic_chip_mem_unmap(pch, window)
 1100         pcmcia_chipset_handle_t pch;
 1101         int window;
 1102 {
 1103         struct pcic_handle *h = (struct pcic_handle *) pch;
 1104         int reg;
 1105 
 1106         if (window >= (sizeof(mem_map_index) / sizeof(mem_map_index[0])))
 1107                 panic("pcic_chip_mem_unmap: window out of range");
 1108 
 1109         reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
 1110         reg &= ~mem_map_index[window].memenable;
 1111         pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
 1112 
 1113         h->memalloc &= ~(1 << window);
 1114 }
 1115 
 1116 int 
 1117 pcic_chip_io_alloc(pch, start, size, align, pcihp)
 1118         pcmcia_chipset_handle_t pch;
 1119         bus_addr_t start;
 1120         bus_size_t size;
 1121         bus_size_t align;
 1122         struct pcmcia_io_handle *pcihp;
 1123 {
 1124         struct pcic_handle *h = (struct pcic_handle *) pch;
 1125         bus_space_tag_t iot;
 1126         bus_space_handle_t ioh;
 1127         bus_addr_t ioaddr, beg, fin;
 1128         int flags = 0;
 1129         struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
 1130         struct pcic_ranges *range;
 1131 
 1132         /*
 1133          * Allocate some arbitrary I/O space.
 1134          */
 1135 
 1136         iot = sc->iot;
 1137 
 1138         if (start) {
 1139                 ioaddr = start;
 1140                 if (bus_space_map(iot, start, size, 0, &ioh))
 1141                         return (1);
 1142                 DPRINTF(("pcic_chip_io_alloc map port %lx+%lx\n",
 1143                     (u_long)ioaddr, (u_long)size));
 1144         } else if (sc->ranges) {
 1145                 flags |= PCMCIA_IO_ALLOCATED;
 1146 
 1147                 /*
 1148                  * In this case, we know the "size" and "align" that
 1149                  * we want.  So we need to start walking down
 1150                  * sc->ranges, searching for a similar space that
 1151                  * is (1) large enough for the size and alignment
 1152                  * (2) then we need to try to allocate
 1153                  * (3) if it fails to allocate, we try next range.
 1154                  *
 1155                  * We must also check that the start/size of each
 1156                  * allocation we are about to do is within the bounds
 1157                  * of "sc->iobase" and "sc->iosize".
 1158                  * (Some pcmcia controllers handle a 12 bits of addressing,
 1159                  * but we want to use the same range structure)
 1160                  */
 1161                 for (range = sc->ranges; range->start; range++) {
 1162                         /* Potentially trim the range because of bounds. */
 1163                         beg = max(range->start, sc->iobase);
 1164                         fin = min(range->start + range->len,
 1165                             sc->iobase + sc->iosize);
 1166 
 1167                         /* Short-circuit easy cases. */
 1168                         if (fin < beg || fin - beg < size)
 1169                                 continue;
 1170 
 1171                         /*
 1172                          * This call magically fulfills our alignment
 1173                          * requirements.
 1174                          */
 1175                         DPRINTF(("pcic_chip_io_alloc beg-fin %lx-%lx\n",
 1176                             (u_long)beg, (u_long)fin));
 1177                         if (bus_space_alloc(iot, beg, fin, size, align, 0, 0,
 1178                             &ioaddr, &ioh) == 0)
 1179                                 break;
 1180                 }
 1181                 if (range->start == 0)
 1182                         return (1);
 1183                 DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n",
 1184                     (u_long)ioaddr, (u_long)size));
 1185 
 1186         } else {
 1187                 flags |= PCMCIA_IO_ALLOCATED;
 1188                 if (bus_space_alloc(iot, sc->iobase,
 1189                     sc->iobase + sc->iosize, size, align, 0, 0,
 1190                     &ioaddr, &ioh))
 1191                         return (1);
 1192                 DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n",
 1193                     (u_long)ioaddr, (u_long)size));
 1194         }
 1195 
 1196         pcihp->iot = iot;
 1197         pcihp->ioh = ioh;
 1198         pcihp->addr = ioaddr;
 1199         pcihp->size = size;
 1200         pcihp->flags = flags;
 1201 
 1202         return (0);
 1203 }
 1204 
 1205 void 
 1206 pcic_chip_io_free(pch, pcihp)
 1207         pcmcia_chipset_handle_t pch;
 1208         struct pcmcia_io_handle *pcihp;
 1209 {
 1210         bus_space_tag_t iot = pcihp->iot;
 1211         bus_space_handle_t ioh = pcihp->ioh;
 1212         bus_size_t size = pcihp->size;
 1213 
 1214         if (pcihp->flags & PCMCIA_IO_ALLOCATED)
 1215                 bus_space_free(iot, ioh, size);
 1216         else
 1217                 bus_space_unmap(iot, ioh, size);
 1218 }
 1219 
 1220 
 1221 static struct io_map_index_st {
 1222         int     start_lsb;
 1223         int     start_msb;
 1224         int     stop_lsb;
 1225         int     stop_msb;
 1226         int     ioenable;
 1227         int     ioctlmask;
 1228         int     ioctlbits[3];           /* indexed by PCMCIA_WIDTH_* */
 1229 }               io_map_index[] = {
 1230         {
 1231                 PCIC_IOADDR0_START_LSB,
 1232                 PCIC_IOADDR0_START_MSB,
 1233                 PCIC_IOADDR0_STOP_LSB,
 1234                 PCIC_IOADDR0_STOP_MSB,
 1235                 PCIC_ADDRWIN_ENABLE_IO0,
 1236                 PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT |
 1237                 PCIC_IOCTL_IO0_IOCS16SRC_MASK | PCIC_IOCTL_IO0_DATASIZE_MASK,
 1238                 {
 1239                         PCIC_IOCTL_IO0_IOCS16SRC_CARD,
 1240                         PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
 1241                             PCIC_IOCTL_IO0_DATASIZE_8BIT,
 1242                         PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
 1243                             PCIC_IOCTL_IO0_DATASIZE_16BIT,
 1244                 },
 1245         },
 1246         {
 1247                 PCIC_IOADDR1_START_LSB,
 1248                 PCIC_IOADDR1_START_MSB,
 1249                 PCIC_IOADDR1_STOP_LSB,
 1250                 PCIC_IOADDR1_STOP_MSB,
 1251                 PCIC_ADDRWIN_ENABLE_IO1,
 1252                 PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT |
 1253                 PCIC_IOCTL_IO1_IOCS16SRC_MASK | PCIC_IOCTL_IO1_DATASIZE_MASK,
 1254                 {
 1255                         PCIC_IOCTL_IO1_IOCS16SRC_CARD,
 1256                         PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE |
 1257                             PCIC_IOCTL_IO1_DATASIZE_8BIT,
 1258                         PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE |
 1259                             PCIC_IOCTL_IO1_DATASIZE_16BIT,
 1260                 },
 1261         },
 1262 };
 1263 
 1264 void 
 1265 pcic_chip_do_io_map(h, win)
 1266         struct pcic_handle *h;
 1267         int win;
 1268 {
 1269         int reg;
 1270 
 1271         DPRINTF(("pcic_chip_do_io_map win %d addr %lx size %lx width %d\n",
 1272             win, (long) h->io[win].addr, (long) h->io[win].size,
 1273             h->io[win].width * 8));
 1274 
 1275         pcic_write(h, io_map_index[win].start_lsb, h->io[win].addr & 0xff);
 1276         pcic_write(h, io_map_index[win].start_msb,
 1277             (h->io[win].addr >> 8) & 0xff);
 1278 
 1279         pcic_write(h, io_map_index[win].stop_lsb,
 1280             (h->io[win].addr + h->io[win].size - 1) & 0xff);
 1281         pcic_write(h, io_map_index[win].stop_msb,
 1282             ((h->io[win].addr + h->io[win].size - 1) >> 8) & 0xff);
 1283 
 1284         reg = pcic_read(h, PCIC_IOCTL);
 1285         reg &= ~io_map_index[win].ioctlmask;
 1286         reg |= io_map_index[win].ioctlbits[h->io[win].width];
 1287         pcic_write(h, PCIC_IOCTL, reg);
 1288 
 1289         reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
 1290         reg |= io_map_index[win].ioenable;
 1291         pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
 1292 }
 1293 
 1294 int 
 1295 pcic_chip_io_map(pch, width, offset, size, pcihp, windowp)
 1296         pcmcia_chipset_handle_t pch;
 1297         int width;
 1298         bus_addr_t offset;
 1299         bus_size_t size;
 1300         struct pcmcia_io_handle *pcihp;
 1301         int *windowp;
 1302 {
 1303         struct pcic_handle *h = (struct pcic_handle *) pch;
 1304         bus_addr_t ioaddr = pcihp->addr + offset;
 1305         int i, win;
 1306 #ifdef PCICDEBUG
 1307         static char *width_names[] = { "auto", "io8", "io16" };
 1308 #endif
 1309         struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
 1310 
 1311         /* XXX Sanity check offset/size. */
 1312 
 1313         win = -1;
 1314         for (i = 0; i < (sizeof(io_map_index) / sizeof(io_map_index[0])); i++) {
 1315                 if ((h->ioalloc & (1 << i)) == 0) {
 1316                         win = i;
 1317                         h->ioalloc |= (1 << i);
 1318                         break;
 1319                 }
 1320         }
 1321 
 1322         if (win == -1)
 1323                 return (1);
 1324 
 1325         *windowp = win;
 1326 
 1327         /* XXX this is pretty gross */
 1328 
 1329         if (sc->iot != pcihp->iot)
 1330                 panic("pcic_chip_io_map iot is bogus");
 1331 
 1332         DPRINTF(("pcic_chip_io_map window %d %s port %lx+%lx\n",
 1333                  win, width_names[width], (u_long) ioaddr, (u_long) size));
 1334 
 1335         h->io[win].addr = ioaddr;
 1336         h->io[win].size = size;
 1337         h->io[win].width = width;
 1338 
 1339         pcic_chip_do_io_map(h, win);
 1340 
 1341         return (0);
 1342 }
 1343 
 1344 void 
 1345 pcic_chip_io_unmap(pch, window)
 1346         pcmcia_chipset_handle_t pch;
 1347         int window;
 1348 {
 1349         struct pcic_handle *h = (struct pcic_handle *) pch;
 1350         int reg;
 1351 
 1352         if (window >= (sizeof(io_map_index) / sizeof(io_map_index[0])))
 1353                 panic("pcic_chip_io_unmap: window out of range");
 1354 
 1355         reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
 1356         reg &= ~io_map_index[window].ioenable;
 1357         pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
 1358 
 1359         h->ioalloc &= ~(1 << window);
 1360 }
 1361 
 1362 void
 1363 pcic_wait_ready(h)
 1364         struct pcic_handle *h;
 1365 {
 1366         int i;
 1367 
 1368         for (i = 0; i < 10000; i++) {
 1369                 if (pcic_read(h, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY)
 1370                         return;
 1371                 delay(500);
 1372 #ifdef PCICDEBUG
 1373                         if ((i>5000) && (i%100 == 99))
 1374                                 printf(".");
 1375 #endif
 1376         }
 1377 
 1378 #ifdef DIAGNOSTIC
 1379         printf("pcic_wait_ready: ready never happened, status = %02x\n",
 1380             pcic_read(h, PCIC_IF_STATUS));
 1381 #endif
 1382 }
 1383 
 1384 void
 1385 pcic_chip_socket_enable(pch)
 1386         pcmcia_chipset_handle_t pch;
 1387 {
 1388         struct pcic_handle *h = (struct pcic_handle *) pch;
 1389         int cardtype, reg, win;
 1390 
 1391         /* this bit is mostly stolen from pcic_attach_card */
 1392 
 1393         /* power down the socket to reset it, clear the card reset pin */
 1394 
 1395         pcic_write(h, PCIC_PWRCTL, 0);
 1396 
 1397         /* 
 1398          * wait 300ms until power fails (Tpf).  Then, wait 100ms since
 1399          * we are changing Vcc (Toff).
 1400          */
 1401         delay((300 + 100) * 1000);
 1402 
 1403         if (h->vendor == PCIC_VENDOR_VADEM_VG469) {
 1404                 reg = pcic_read(h, PCIC_VG469_VSELECT);
 1405                 reg &= ~PCIC_VG469_VSELECT_VCC;
 1406                 pcic_write(h, PCIC_VG469_VSELECT, reg);
 1407         }
 1408 
 1409         /* power up the socket */
 1410 
 1411         pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_DISABLE_RESETDRV
 1412                            | PCIC_PWRCTL_PWR_ENABLE);
 1413 
 1414         /*
 1415          * wait 100ms until power raise (Tpr) and 20ms to become
 1416          * stable (Tsu(Vcc)).
 1417          *
 1418          * some machines require some more time to be settled
 1419          * (another 200ms is added here).
 1420          */
 1421         delay((100 + 20 + 200) * 1000);
 1422 
 1423         pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_DISABLE_RESETDRV |
 1424             PCIC_PWRCTL_OE | PCIC_PWRCTL_PWR_ENABLE);
 1425         pcic_write(h, PCIC_INTR, 0);
 1426 
 1427         /*
 1428          * hold RESET at least 10us.
 1429          */
 1430         delay(10);
 1431 
 1432         /* clear the reset flag */
 1433 
 1434         pcic_write(h, PCIC_INTR, PCIC_INTR_RESET);
 1435 
 1436         /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
 1437 
 1438         delay(20000);
 1439 
 1440         /* wait for the chip to finish initializing */
 1441 
 1442 #ifdef DIAGNOSTIC
 1443         reg = pcic_read(h, PCIC_IF_STATUS);
 1444         if (!(reg & PCIC_IF_STATUS_POWERACTIVE)) {
 1445                 printf("pcic_chip_socket_enable: status %x\n", reg);
 1446         }
 1447 #endif
 1448 
 1449         pcic_wait_ready(h);
 1450 
 1451         /* zero out the address windows */
 1452 
 1453         pcic_write(h, PCIC_ADDRWIN_ENABLE, 0);
 1454 
 1455         /* set the card type */
 1456 
 1457         cardtype = pcmcia_card_gettype(h->pcmcia);
 1458 
 1459         reg = pcic_read(h, PCIC_INTR);
 1460         reg &= ~PCIC_INTR_CARDTYPE_MASK;
 1461         reg |= ((cardtype == PCMCIA_IFTYPE_IO) ?
 1462                 PCIC_INTR_CARDTYPE_IO :
 1463                 PCIC_INTR_CARDTYPE_MEM);
 1464         reg |= h->ih_irq;
 1465         pcic_write(h, PCIC_INTR, reg);
 1466 
 1467         DPRINTF(("%s: pcic_chip_socket_enable %02x cardtype %s %02x\n",
 1468             h->ph_parent->dv_xname, h->sock,
 1469             ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), reg));
 1470 
 1471         /* reinstall all the memory and io mappings */
 1472 
 1473         for (win = 0; win < PCIC_MEM_WINS; win++)
 1474                 if (h->memalloc & (1 << win))
 1475                         pcic_chip_do_mem_map(h, win);
 1476 
 1477         for (win = 0; win < PCIC_IO_WINS; win++)
 1478                 if (h->ioalloc & (1 << win))
 1479                         pcic_chip_do_io_map(h, win);
 1480 }
 1481 
 1482 void
 1483 pcic_chip_socket_disable(pch)
 1484         pcmcia_chipset_handle_t pch;
 1485 {
 1486         struct pcic_handle *h = (struct pcic_handle *) pch;
 1487 
 1488         DPRINTF(("pcic_chip_socket_disable\n"));
 1489 
 1490         /* power down the socket */
 1491 
 1492         pcic_write(h, PCIC_PWRCTL, 0);
 1493 
 1494         /*
 1495          * wait 300ms until power fails (Tpf).
 1496          */
 1497         delay(300 * 1000);
 1498 }
 1499 
 1500 u_int8_t
 1501 st_pcic_read(h, idx)
 1502         struct pcic_handle *h;
 1503         int idx;
 1504 {
 1505         if (idx != -1)
 1506                 bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_INDEX,
 1507                     h->sock + idx);
 1508         return bus_space_read_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_DATA);
 1509 }
 1510 
 1511 void
 1512 st_pcic_write(h, idx, data)
 1513         struct pcic_handle *h;
 1514         int idx;
 1515         int data;
 1516 {
 1517         if (idx != -1)
 1518                 bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_INDEX,
 1519                     h->sock + idx);
 1520         if (data != -1)
 1521                 bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_DATA,
 1522                     data);
 1523 }

/* [<][>][^][v][top][bottom][index][help] */