kernel - remove INTR_FAST
[dragonfly.git] / sys / dev / pccard / pccbb / pccbb.c
1 /*-
2  * Copyright (c) 2002-2004 M. Warner Losh.
3  * Copyright (c) 2000-2001 Jonathan Chen.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: src/sys/dev/pccbb/pccbb.c,v 1.126 2005/07/17 19:40:05 imp Exp $
28  * $DragonFly: src/sys/dev/pccard/pccbb/pccbb.c,v 1.21 2007/07/05 12:08:54 sephe Exp $
29  */
30
31 /*-
32  * Copyright (c) 1998, 1999 and 2000
33  *      HAYAKAWA Koichi.  All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  * 3. All advertising materials mentioning features or use of this software
44  *    must display the following acknowledgement:
45  *      This product includes software developed by HAYAKAWA Koichi.
46  * 4. The name of the author may not be used to endorse or promote products
47  *    derived from this software without specific prior written permission.
48  *
49  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
50  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
51  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
52  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
53  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
54  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
55  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
56  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
58  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59  */
60
61 /*
62  * Driver for PCI to CardBus Bridge chips
63  * and PCI to PCMCIA Bridge chips
64  * and ISA to PCMCIA host adapters
65  * and C Bus to PCMCIA host adapters
66  *
67  * References:
68  *  TI Datasheets:
69  *   http://www-s.ti.com/cgi-bin/sc/generic2.cgi?family=PCI+CARDBUS+CONTROLLERS
70  *
71  * Written by Jonathan Chen <jon@freebsd.org>
72  * The author would like to acknowledge:
73  *  * HAYAKAWA Koichi: Author of the NetBSD code for the same thing
74  *  * Warner Losh: Newbus/newcard guru and author of the pccard side of things
75  *  * YAMAMOTO Shigeru: Author of another FreeBSD cardbus driver
76  *  * David Cross: Author of the initial ugly hack for a specific cardbus card
77  */
78
79 #include <sys/param.h>
80 #include <sys/bus.h>
81 #include <sys/errno.h>
82 #include <sys/interrupt.h>
83 #include <sys/kernel.h>
84 #include <sys/module.h>
85 #include <sys/kthread.h>
86 #include <sys/lock.h>
87 #include <sys/malloc.h>
88 #include <sys/proc.h>
89 #include <sys/rman.h>
90 #include <sys/sysctl.h>
91 #include <sys/systm.h>
92 #include <sys/thread2.h>
93
94 #include <bus/pci/pcireg.h>
95 #include <bus/pci/pcivar.h>
96 #include <machine/clock.h>
97
98 #include <bus/pccard/pccardreg.h>
99 #include <bus/pccard/pccardvar.h>
100
101 #include <dev/pccard/exca/excareg.h>
102 #include <dev/pccard/exca/excavar.h>
103
104 #include <dev/pccard/pccbb/pccbbreg.h>
105 #include <dev/pccard/pccbb/pccbbvar.h>
106
107 #include "power_if.h"
108 #include "card_if.h"
109 #include "pcib_if.h"
110
111 #define DPRINTF(x) do { if (cbb_debug) kprintf x; } while (0)
112 #define DEVPRINTF(x) do { if (cbb_debug) device_printf x; } while (0)
113
114 #define PCI_MASK_CONFIG(DEV,REG,MASK,SIZE)                              \
115         pci_write_config(DEV, REG, pci_read_config(DEV, REG, SIZE) MASK, SIZE)
116 #define PCI_MASK2_CONFIG(DEV,REG,MASK1,MASK2,SIZE)                      \
117         pci_write_config(DEV, REG, (                                    \
118                 pci_read_config(DEV, REG, SIZE) MASK1) MASK2, SIZE)
119
120 #define CBB_CARD_PRESENT(s) ((s & CBB_STATE_CD) == 0)
121
122 #define CBB_START_MEM   0x88000000
123 #define CBB_START_32_IO 0x1000
124 #define CBB_START_16_IO 0x100
125
126 devclass_t cbb_devclass;
127
128 /* sysctl vars */
129 SYSCTL_NODE(_hw, OID_AUTO, cbb, CTLFLAG_RD, 0, "CBB parameters");
130
131 /* There's no way to say TUNEABLE_LONG to get the right types */
132 u_long cbb_start_mem = CBB_START_MEM;
133 TUNABLE_INT("hw.cbb.start_memory", (int *)&cbb_start_mem);
134 SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_memory, CTLFLAG_RW,
135     &cbb_start_mem, CBB_START_MEM,
136     "Starting address for memory allocations");
137
138 u_long cbb_start_16_io = CBB_START_16_IO;
139 TUNABLE_INT("hw.cbb.start_16_io", (int *)&cbb_start_16_io);
140 SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_16_io, CTLFLAG_RW,
141     &cbb_start_16_io, CBB_START_16_IO,
142     "Starting ioport for 16-bit cards");
143
144 u_long cbb_start_32_io = CBB_START_32_IO;
145 TUNABLE_INT("hw.cbb.start_32_io", (int *)&cbb_start_32_io);
146 SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_32_io, CTLFLAG_RW,
147     &cbb_start_32_io, CBB_START_32_IO,
148     "Starting ioport for 32-bit cards");
149
150 int cbb_debug = 0;
151 TUNABLE_INT("hw.cbb.debug", &cbb_debug);
152 SYSCTL_ULONG(_hw_cbb, OID_AUTO, debug, CTLFLAG_RW, &cbb_debug, 0,
153     "Verbose cardbus bridge debugging");
154
155 static void     cbb_insert(struct cbb_softc *sc);
156 static void     cbb_removal(struct cbb_softc *sc);
157 static uint32_t cbb_detect_voltage(device_t brdev);
158 static void     cbb_cardbus_reset(device_t brdev);
159 static int      cbb_cardbus_io_open(device_t brdev, int win, uint32_t start,
160                     uint32_t end);
161 static int      cbb_cardbus_mem_open(device_t brdev, int win,
162                     uint32_t start, uint32_t end);
163 static void     cbb_cardbus_auto_open(struct cbb_softc *sc, int type);
164 static int      cbb_cardbus_activate_resource(device_t brdev, device_t child,
165                     int type, int rid, struct resource *res);
166 static int      cbb_cardbus_deactivate_resource(device_t brdev,
167                     device_t child, int type, int rid, struct resource *res);
168 static struct resource  *cbb_cardbus_alloc_resource(device_t brdev,
169                     device_t child, int type, int *rid, u_long start,
170                     u_long end, u_long count, u_int flags);
171 static int      cbb_cardbus_release_resource(device_t brdev, device_t child,
172                     int type, int rid, struct resource *res);
173 static int      cbb_cardbus_power_enable_socket(device_t brdev,
174                     device_t child);
175 static void     cbb_cardbus_power_disable_socket(device_t brdev,
176                     device_t child);
177 static void     cbb_func_intr(void *arg);
178
179 static void
180 cbb_remove_res(struct cbb_softc *sc, struct resource *res)
181 {
182         struct cbb_reslist *rle;
183
184         SLIST_FOREACH(rle, &sc->rl, link) {
185                 if (rle->res == res) {
186                         SLIST_REMOVE(&sc->rl, rle, cbb_reslist, link);
187                         kfree(rle, M_DEVBUF);
188                         return;
189                 }
190         }
191 }
192
193 static struct resource *
194 cbb_find_res(struct cbb_softc *sc, int type, int rid)
195 {
196         struct cbb_reslist *rle;
197         
198         SLIST_FOREACH(rle, &sc->rl, link)
199                 if (SYS_RES_MEMORY == rle->type && rid == rle->rid)
200                         return (rle->res);
201         return (NULL);
202 }
203
204 static void
205 cbb_insert_res(struct cbb_softc *sc, struct resource *res, int type,
206     int rid)
207 {
208         struct cbb_reslist *rle;
209
210         /*
211          * Need to record allocated resource so we can iterate through
212          * it later.
213          */
214         rle = kmalloc(sizeof(struct cbb_reslist), M_DEVBUF, M_NOWAIT);
215         if (rle == NULL)
216                 panic("cbb_cardbus_alloc_resource: can't record entry!");
217         rle->res = res;
218         rle->type = type;
219         rle->rid = rid;
220         SLIST_INSERT_HEAD(&sc->rl, rle, link);
221 }
222
223 static void
224 cbb_destroy_res(struct cbb_softc *sc)
225 {
226         struct cbb_reslist *rle;
227
228         while ((rle = SLIST_FIRST(&sc->rl)) != NULL) {
229                 device_printf(sc->dev, "Danger Will Robinson: Resource "
230                     "left allocated!  This is a bug... "
231                     "(rid=%x, type=%d, addr=%lx)\n", rle->rid, rle->type,
232                     rman_get_start(rle->res));
233                 SLIST_REMOVE_HEAD(&sc->rl, link);
234                 kfree(rle, M_DEVBUF);
235         }
236 }
237
238 /*
239  * Disable function interrupts by telling the bridge to generate IRQ1
240  * interrupts.  These interrupts aren't really generated by the chip, since
241  * IRQ1 is reserved.  Some chipsets assert INTA# inappropriately during
242  * initialization, so this helps to work around the problem.
243  *
244  * XXX We can't do this workaround for all chipsets, because this
245  * XXX causes interference with the keyboard because somechipsets will
246  * XXX actually signal IRQ1 over their serial interrupt connections to
247  * XXX the south bridge.  Disable it it for now.
248  */
249 void
250 cbb_disable_func_intr(struct cbb_softc *sc)
251 {
252 #if 0
253         uint8_t reg;
254         reg = (exca_getb(&sc->exca[0], EXCA_INTR) & ~EXCA_INTR_IRQ_MASK) | 
255             EXCA_INTR_IRQ_RESERVED1;
256         exca_putb(&sc->exca[0], EXCA_INTR, reg);
257 #endif
258 }
259
260 /*
261  * Enable function interrupts.  We turn on function interrupts when the card
262  * requests an interrupt.  The PCMCIA standard says that we should set
263  * the lower 4 bits to 0 to route via PCI.  Note: we call this for both
264  * CardBus and R2 (PC Card) cases, but it should have no effect on CardBus
265  * cards.
266  */
267 static void
268 cbb_enable_func_intr(struct cbb_softc *sc)
269 {
270         uint8_t reg;
271
272         reg = (exca_getb(&sc->exca[0], EXCA_INTR) & ~EXCA_INTR_IRQ_MASK) | 
273             EXCA_INTR_IRQ_NONE;
274         exca_putb(&sc->exca[0], EXCA_INTR, reg);
275 }
276
277 int
278 cbb_detach(device_t brdev)
279 {
280         struct cbb_softc *sc = device_get_softc(brdev);
281         int numdevs;
282         device_t *devlist;
283         int tmp;
284         int error;
285
286         device_get_children(brdev, &devlist, &numdevs);
287
288         error = 0;
289         for (tmp = 0; tmp < numdevs; tmp++) {
290                 if (device_detach(devlist[tmp]) == 0)
291                         device_delete_child(brdev, devlist[tmp]);
292                 else
293                         error++;
294         }
295         kfree(devlist, M_TEMP);
296         if (error > 0)
297                 return (ENXIO);
298
299         /* 
300          * XXX do we teardown all the ones still registered to guard against
301          * XXX buggy client drivers?
302          */
303         bus_teardown_intr(brdev, sc->irq_res, sc->intrhand);
304         sc->flags |= CBB_KTHREAD_DONE;
305         if (sc->flags & CBB_KTHREAD_RUNNING) {
306                 crit_enter();
307                 wakeup(&sc->generic_cv);
308                 tsleep(sc->event_thread, 0, "cbbun", 0);
309                 crit_exit();
310         }
311
312         bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->irq_res);
313         bus_release_resource(brdev, SYS_RES_MEMORY, CBBR_SOCKBASE,
314             sc->base_res);
315         return (0);
316 }
317
318 int
319 cbb_shutdown(device_t brdev)
320 {
321         struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(brdev);
322         /* properly reset everything at shutdown */
323
324         PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, |CBBM_BRIDGECTRL_RESET, 2);
325         exca_clrb(&sc->exca[0], EXCA_INTR, EXCA_INTR_RESET);
326
327         cbb_set(sc, CBB_SOCKET_MASK, 0);
328
329         cbb_power(brdev, CARD_OFF);
330
331         exca_putb(&sc->exca[0], EXCA_ADDRWIN_ENABLE, 0);
332         pci_write_config(brdev, CBBR_MEMBASE0, 0, 4);
333         pci_write_config(brdev, CBBR_MEMLIMIT0, 0, 4);
334         pci_write_config(brdev, CBBR_MEMBASE1, 0, 4);
335         pci_write_config(brdev, CBBR_MEMLIMIT1, 0, 4);
336         pci_write_config(brdev, CBBR_IOBASE0, 0, 4);
337         pci_write_config(brdev, CBBR_IOLIMIT0, 0, 4);
338         pci_write_config(brdev, CBBR_IOBASE1, 0, 4);
339         pci_write_config(brdev, CBBR_IOLIMIT1, 0, 4);
340         pci_write_config(brdev, PCIR_COMMAND, 0, 2);
341         return (0);
342 }
343
344 int
345 cbb_setup_intr(device_t dev, device_t child, struct resource *irq,
346                int flags, driver_intr_t *intr, void *arg,
347                void **cookiep, lwkt_serialize_t serializer)
348 {
349         struct cbb_intrhand *ih;
350         struct cbb_softc *sc = device_get_softc(dev);
351         int err;
352
353         ih = kmalloc(sizeof(struct cbb_intrhand), M_DEVBUF, M_NOWAIT);
354         if (ih == NULL)
355                 return (ENOMEM);
356         *cookiep = ih;
357         ih->intr = intr;
358         ih->arg = arg;
359         ih->sc = sc;
360         ih->serializer = serializer;
361         /*
362          * XXX need to turn on ISA interrupts, if we ever support them, but
363          * XXX for now that's all we need to do.
364          */
365         err = BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags,
366             cbb_func_intr, ih, &ih->cookie, NULL);
367         if (err != 0) {
368                 kfree(ih, M_DEVBUF);
369                 return (err);
370         }
371         cbb_enable_func_intr(sc);
372         sc->flags |= CBB_CARD_OK;
373         return 0;
374 }
375
376 int
377 cbb_teardown_intr(device_t dev, device_t child, struct resource *irq,
378     void *cookie)
379 {
380         struct cbb_intrhand *ih;
381         int err;
382
383         /* XXX Need to do different things for ISA interrupts. */
384         ih = (struct cbb_intrhand *) cookie;
385         err = BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq,
386             ih->cookie);
387         if (err != 0)
388                 return (err);
389         kfree(ih, M_DEVBUF);
390         return (0);
391 }
392
393
394 void
395 cbb_driver_added(device_t brdev, driver_t *driver)
396 {
397         struct cbb_softc *sc = device_get_softc(brdev);
398         device_t *devlist;
399         device_t dev;
400         int tmp;
401         int numdevs;
402         int wake = 0;
403
404         DEVICE_IDENTIFY(driver, brdev);
405         device_get_children(brdev, &devlist, &numdevs);
406         for (tmp = 0; tmp < numdevs; tmp++) {
407                 dev = devlist[tmp];
408                 if (device_get_state(dev) == DS_NOTPRESENT &&
409                     device_probe_and_attach(dev) == 0)
410                         wake++;
411         }
412         kfree(devlist, M_TEMP);
413
414         if (wake > 0)
415                 wakeup_one(&sc->generic_cv);
416 }
417
418 void
419 cbb_child_detached(device_t brdev, device_t child)
420 {
421         struct cbb_softc *sc = device_get_softc(brdev);
422
423         if (child != sc->cbdev && child != sc->exca[0].pccarddev)
424                 device_printf(brdev, "Unknown child detached: %s\n",
425                     device_get_nameunit(child));
426 }
427
428 /************************************************************************/
429 /* Kthreads                                                             */
430 /************************************************************************/
431
432 void
433 cbb_event_thread(void *arg)
434 {
435         struct cbb_softc *sc = arg;
436         uint32_t status;
437         int err;
438         int not_a_card = 0;
439
440         sc->flags |= CBB_KTHREAD_RUNNING;
441         while ((sc->flags & CBB_KTHREAD_DONE) == 0) {
442                 /*
443                  * We take out Giant here because we need it deep,
444                  * down in the bowels of the vm system for mapping the
445                  * memory we need to read the CIS.  In addition, since
446                  * we are adding/deleting devices from the dev tree,
447                  * and that code isn't MP safe, we have to hold Giant.
448                  */
449                 status = cbb_get(sc, CBB_SOCKET_STATE);
450                 DPRINTF(("Status is 0x%x\n", status));
451                 if (!CBB_CARD_PRESENT(status)) {
452                         not_a_card = 0;         /* We know card type */
453                         cbb_removal(sc);
454                 } else if (status & CBB_STATE_NOT_A_CARD) {
455                         /*
456                          * Up to 20 times, try to rescan the card when we
457                          * see NOT_A_CARD.
458                          */
459                         if (not_a_card++ < 20) {
460                                 DEVPRINTF((sc->dev,
461                                     "Not a card bit set, rescanning\n"));
462                                 cbb_setb(sc, CBB_SOCKET_FORCE, CBB_FORCE_CV_TEST);
463                         } else {
464                                 device_printf(sc->dev,
465                                     "Can't determine card type\n");
466                         }
467                 } else {
468                         not_a_card = 0;         /* We know card type */
469                         cbb_insert(sc);
470                 }
471
472                 /*
473                  * Wait until it has been 1s since the last time we
474                  * get an interrupt.  We handle the rest of the interrupt
475                  * at the top of the loop.  Although we clear the bit in the
476                  * ISR, we signal sc->generic_cv from the detach path after
477                  * we've set the CBB_KTHREAD_DONE bit, so we can't do a simple
478                  * 1s sleep here.
479                  *
480                  * In our ISR, we turn off the card changed interrupt.  Turn
481                  * them back on here before we wait for them to happen.  We
482                  * turn them on/off so that we can tolerate a large latency
483                  * between the time we signal cbb_event_thread and it gets
484                  * a chance to run.
485                  */
486                 crit_enter();
487                 cbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD);
488                 tsleep(&sc->generic_cv, 0, "cbbgcv", 0);
489                 err = 0;
490                 while (err != EWOULDBLOCK &&
491                     (sc->flags & CBB_KTHREAD_DONE) == 0)
492                         err = tsleep(&sc->generic_cv, 0, "cbbgcv", hz);
493                 crit_exit();
494         }
495         sc->flags &= ~CBB_KTHREAD_RUNNING;
496         wakeup(sc->event_thread);
497         kthread_exit();
498 }
499
500 /************************************************************************/
501 /* Insert/removal                                                       */
502 /************************************************************************/
503
504 static void
505 cbb_insert(struct cbb_softc *sc)
506 {
507         uint32_t sockevent, sockstate;
508
509         sockevent = cbb_get(sc, CBB_SOCKET_EVENT);
510         sockstate = cbb_get(sc, CBB_SOCKET_STATE);
511
512         DEVPRINTF((sc->dev, "card inserted: event=0x%08x, state=%08x\n",
513             sockevent, sockstate));
514
515         if (sockstate & CBB_STATE_R2_CARD) {
516                 if (sc->exca[0].pccarddev) {
517                         sc->flags |= CBB_16BIT_CARD;
518                         exca_insert(&sc->exca[0]);
519                 } else {
520                         device_printf(sc->dev,
521                             "16-bit card inserted, but no pccard bus.\n");
522                 }
523         } else if (sockstate & CBB_STATE_CB_CARD) {
524                 if (sc->cbdev != NULL) {
525                         sc->flags &= ~CBB_16BIT_CARD;
526                         CARD_ATTACH_CARD(sc->cbdev);
527                 } else {
528                         device_printf(sc->dev,
529                             "CardBus card inserted, but no cardbus bus.\n");
530                 }
531         } else {
532                 /*
533                  * We should power the card down, and try again a couple of
534                  * times if this happens. XXX
535                  */
536                 device_printf(sc->dev, "Unsupported card type detected\n");
537         }
538 }
539
540 static void
541 cbb_removal(struct cbb_softc *sc)
542 {
543         sc->flags &= ~CBB_CARD_OK;
544         if (sc->flags & CBB_16BIT_CARD) {
545                 exca_removal(&sc->exca[0]);
546         } else {
547                 if (sc->cbdev != NULL)
548                         CARD_DETACH_CARD(sc->cbdev);
549         }
550         cbb_destroy_res(sc);
551 }
552
553 /************************************************************************/
554 /* Interrupt Handler                                                    */
555 /************************************************************************/
556
557 /*
558  * Since we touch hardware in the worst case, we don't need to use atomic
559  * ops on the CARD_OK tests.  They would save us a trip to the hardware
560  * if CARD_OK was recently cleared and the caches haven't updated yet.
561  * However, an atomic op costs between 100-200 CPU cycles.  On a 3GHz
562  * machine, this is about 33-66ns, whereas a trip the the hardware
563  * is about that.  On slower machines, the cost is even higher, so the
564  * trip to the hardware is cheaper and achieves the same ends that
565  * a fully locked operation would give us.
566  *
567  * This is a separate routine because we'd have to use locking and/or
568  * other synchronization in cbb_intr to do this there.  That would be
569  * even more expensive.
570  *
571  * I need to investigate what this means for a SMP machine with multiple
572  * CPUs servicing the ISR when an eject happens.  In the case of a dirty
573  * eject, CD glitches and we might read 'card present' from the hardware
574  * due to this jitter.  If we assumed that cbb_intr() ran before
575  * cbb_func_intr(), we could just check the SOCKET_MASK register and if
576  * CD changes were clear there, then we'd know the card was gone.
577  */
578 static void
579 cbb_func_intr(void *arg)
580 {
581         struct cbb_intrhand *ih = arg;
582         struct cbb_softc *sc = ih->sc;
583
584         /*
585          * Make sure that the card is really there.
586          */
587         if ((sc->flags & CBB_CARD_OK) == 0)
588                 return;
589         if (!CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE))) {
590                 sc->flags &= ~CBB_CARD_OK;
591                 return;
592         }
593
594         /*
595          * nb: don't have to check for giant or not, since that's done
596          * in the ISR dispatch
597          */
598         if (ih->serializer) {
599                 lwkt_serialize_handler_call(ih->serializer,
600                         (inthand2_t *)ih->intr, ih->arg, NULL);
601         } else {
602                 (*ih->intr)(ih->arg);
603         }
604 }
605
606 void
607 cbb_intr(void *arg)
608 {
609         struct cbb_softc *sc = arg;
610         uint32_t sockevent;
611
612         sockevent = cbb_get(sc, CBB_SOCKET_EVENT);
613         if (sockevent != 0) {
614                 /* ack the interrupt */
615                 cbb_set(sc, CBB_SOCKET_EVENT, sockevent);
616
617                 /*
618                  * If anything has happened to the socket, we assume that
619                  * the card is no longer OK, and we shouldn't call its
620                  * ISR.  We set CARD_OK as soon as we've attached the
621                  * card.  This helps in a noisy eject, which happens
622                  * all too often when users are ejecting their PC Cards.
623                  *
624                  * We use this method in preference to checking to see if
625                  * the card is still there because the check suffers from
626                  * a race condition in the bouncing case.  Prior versions
627                  * of the pccard software used a similar trick and achieved
628                  * excellent results.
629                  */
630                 if (sockevent & CBB_SOCKET_EVENT_CD) {
631                         crit_enter();
632                         cbb_clrb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD);
633                         sc->flags &= ~CBB_CARD_OK;
634                         cbb_disable_func_intr(sc);
635                         wakeup_one(&sc->generic_cv);
636                         crit_exit();
637                 }
638                 /*
639                  * If we get a power interrupt, wakeup anybody that might
640                  * be waiting for one.
641                  */
642                 if (sockevent & CBB_SOCKET_EVENT_POWER) {
643                         crit_enter();
644                         sc->powerintr++;
645                         wakeup(&sc->power_cv);
646                         crit_exit();
647                 }
648         }
649         /*
650          * Some chips also require us to read the old ExCA registe for
651          * card status change when we route CSC vis PCI.  This isn't supposed
652          * to be required, but it clears the interrupt state on some chipsets.
653          * Maybe there's a setting that would obviate its need.  Maybe we
654          * should test the status bits and deal with them, but so far we've
655          * not found any machines that don't also give us the socket status
656          * indication above.
657          *
658          * We have to call this unconditionally because some bridges deliver
659          * the even independent of the CBB_SOCKET_EVENT_CD above.
660          */
661         exca_getb(&sc->exca[0], EXCA_CSC);
662 }
663
664 /************************************************************************/
665 /* Generic Power functions                                              */
666 /************************************************************************/
667
668 static uint32_t
669 cbb_detect_voltage(device_t brdev)
670 {
671         struct cbb_softc *sc = device_get_softc(brdev);
672         uint32_t psr;
673         uint32_t vol = CARD_UKN_CARD;
674
675         psr = cbb_get(sc, CBB_SOCKET_STATE);
676
677         if (psr & CBB_STATE_5VCARD)
678                 vol |= CARD_5V_CARD;
679         if (psr & CBB_STATE_3VCARD)
680                 vol |= CARD_3V_CARD;
681         if (psr & CBB_STATE_XVCARD)
682                 vol |= CARD_XV_CARD;
683         if (psr & CBB_STATE_YVCARD)
684                 vol |= CARD_YV_CARD;
685
686         return (vol);
687 }
688
689 static uint8_t
690 cbb_o2micro_power_hack(struct cbb_softc *sc)
691 {
692         uint8_t reg;
693
694         /*
695          * Issue #2: INT# not qualified with IRQ Routing Bit.  An
696          * unexpected PCI INT# may be generated during PC-Card
697          * initialization even with the IRQ Routing Bit Set with some
698          * PC-Cards.
699          *
700          * This is a two part issue.  The first part is that some of
701          * our older controllers have an issue in which the slot's PCI
702          * INT# is NOT qualified by the IRQ routing bit (PCI reg. 3Eh
703          * bit 7).  Regardless of the IRQ routing bit, if NO ISA IRQ
704          * is selected (ExCA register 03h bits 3:0, of the slot, are
705          * cleared) we will generate INT# if IREQ# is asserted.  The
706          * second part is because some PC-Cards prematurally assert
707          * IREQ# before the ExCA registers are fully programmed.  This
708          * in turn asserts INT# because ExCA register 03h bits 3:0
709          * (ISA IRQ Select) are not yet programmed.
710          *
711          * The fix for this issue, which will work for any controller
712          * (old or new), is to set ExCA register 03h bits 3:0 = 0001b
713          * (select IRQ1), of the slot, before turning on slot power.
714          * Selecting IRQ1 will result in INT# NOT being asserted
715          * (because IRQ1 is selected), and IRQ1 won't be asserted
716          * because our controllers don't generate IRQ1.
717          *
718          * Other, non O2Micro controllers will generate irq 1 in some
719          * situations, so we can't do this hack for everybody.  Reports of
720          * keyboard controller's interrupts being suppressed occurred when
721          * we did this.
722          */
723         reg = exca_getb(&sc->exca[0], EXCA_INTR);
724         exca_putb(&sc->exca[0], EXCA_INTR, (reg & 0xf0) | 1);
725         return (reg);
726 }
727
728 /*
729  * Restore the damage that cbb_o2micro_power_hack does to EXCA_INTR so
730  * we don't have an interrupt storm on power on.  This has the efect of
731  * disabling card status change interrupts for the duration of poweron.
732  */
733 static void
734 cbb_o2micro_power_hack2(struct cbb_softc *sc, uint8_t reg)
735 {
736         exca_putb(&sc->exca[0], EXCA_INTR, reg);
737 }
738
739 int
740 cbb_power(device_t brdev, int volts)
741 {
742         uint32_t status, sock_ctrl, mask;
743         struct cbb_softc *sc = device_get_softc(brdev);
744         int cnt, sane;
745         int retval = 0;
746         int on = 0;
747         uint8_t reg = 0;
748
749         sock_ctrl = cbb_get(sc, CBB_SOCKET_CONTROL);
750
751         sock_ctrl &= ~CBB_SOCKET_CTRL_VCCMASK;
752         switch (volts & CARD_VCCMASK) {
753         case 5:
754                 sock_ctrl |= CBB_SOCKET_CTRL_VCC_5V;
755                 on++;
756                 break;
757         case 3:
758                 sock_ctrl |= CBB_SOCKET_CTRL_VCC_3V;
759                 on++;
760                 break;
761         case XV:
762                 sock_ctrl |= CBB_SOCKET_CTRL_VCC_XV;
763                 on++;
764                 break;
765         case YV:
766                 sock_ctrl |= CBB_SOCKET_CTRL_VCC_YV;
767                 on++;
768                 break;
769         case 0:
770                 break;
771         default:
772                 return (0);                     /* power NEVER changed */
773         }
774
775         /* VPP == VCC */
776         sock_ctrl &= ~CBB_SOCKET_CTRL_VPPMASK;
777         sock_ctrl |= ((sock_ctrl >> 4) & 0x07);
778
779         if (cbb_get(sc, CBB_SOCKET_CONTROL) == sock_ctrl)
780                 return (1); /* no change necessary */
781         DEVPRINTF((sc->dev, "cbb_power: %dV\n", volts));
782         if (volts != 0 && sc->chipset == CB_O2MICRO)
783                 reg = cbb_o2micro_power_hack(sc);
784
785         /*
786          * We have to mask the card change detect interrupt while we're
787          * messing with the power.  It is allowed to bounce while we're
788          * messing with power as things settle down.  In addition, we mask off
789          * the card's function interrupt by routing it via the ISA bus.  This
790          * bit generally only affects 16bit cards.  Some bridges allow one to
791          * set another bit to have it also affect 32bit cards.  Since 32bit
792          * cards are required to be better behaved, we don't bother to get
793          * into those bridge specific features.
794          */
795         mask = cbb_get(sc, CBB_SOCKET_MASK);
796         mask |= CBB_SOCKET_MASK_POWER;
797         mask &= ~CBB_SOCKET_MASK_CD;
798         cbb_set(sc, CBB_SOCKET_MASK, mask);
799         PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL,
800             |CBBM_BRIDGECTRL_INTR_IREQ_ISA_EN, 2);
801         cbb_set(sc, CBB_SOCKET_CONTROL, sock_ctrl);
802         if (on) {
803                 crit_enter();
804                 cnt = sc->powerintr;
805                 sane = 200;
806                 while (!(cbb_get(sc, CBB_SOCKET_STATE) & CBB_STATE_POWER_CYCLE) &&
807                     cnt == sc->powerintr && sane-- > 0)
808                         tsleep(&sc->power_cv, 0, "cbbpcv", hz / 10);
809                 crit_exit();
810                 if (sane <= 0)
811                         device_printf(sc->dev, "power timeout, doom?\n");
812         }
813
814         /*
815          * After the power is good, we can turn off the power interrupt.
816          * However, the PC Card standard says that we must delay turning the
817          * CD bit back on for a bit to allow for bouncyness on power down
818          * (recall that we don't wait above for a power down, since we don't
819          * get an interrupt for that).  We're called either from the suspend
820          * code in which case we don't want to turn card change on again, or
821          * we're called from the card insertion code, in which case the cbb
822          * thread will turn it on for us before it waits to be woken by a
823          * change event.
824          */
825         cbb_clrb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_POWER);
826         status = cbb_get(sc, CBB_SOCKET_STATE);
827         if (on) {
828                 if ((status & CBB_STATE_POWER_CYCLE) == 0)
829                         device_printf(sc->dev, "Power not on?\n");
830         }
831         if (status & CBB_STATE_BAD_VCC_REQ) {
832                 device_printf(sc->dev, "Bad Vcc requested\n");  
833                 /* XXX Do we want to do something to mitigate things here? */
834                 goto done;
835         }
836         PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL,
837             & ~CBBM_BRIDGECTRL_INTR_IREQ_ISA_EN, 2);
838         retval = 1;
839 done:;
840         if (volts != 0 && sc->chipset == CB_O2MICRO)
841                 cbb_o2micro_power_hack2(sc, reg);
842         return (retval);
843 }
844
845 static int
846 cbb_current_voltage(device_t brdev)
847 {
848         struct cbb_softc *sc = device_get_softc(brdev);
849         uint32_t ctrl;
850         
851         ctrl = cbb_get(sc, CBB_SOCKET_CONTROL);
852         switch (ctrl & CBB_SOCKET_CTRL_VCCMASK) {
853         case CBB_SOCKET_CTRL_VCC_5V:
854                 return CARD_5V_CARD;
855         case CBB_SOCKET_CTRL_VCC_3V:
856                 return CARD_3V_CARD;
857         case CBB_SOCKET_CTRL_VCC_XV:
858                 return CARD_XV_CARD;
859         case CBB_SOCKET_CTRL_VCC_YV:
860                 return CARD_YV_CARD;
861         }
862         return 0;
863 }
864
865 /*
866  * detect the voltage for the card, and set it.  Since the power
867  * used is the square of the voltage, lower voltages is a big win
868  * and what Windows does (and what Microsoft prefers).  The MS paper
869  * also talks about preferring the CIS entry as well, but that has
870  * to be done elsewhere.  We also optimize power sequencing here
871  * and don't change things if we're already powered up at a supported
872  * voltage.
873  *
874  * In addition, we power up with OE disabled.  We'll set it later
875  * in the power up sequence.
876  */
877 static int
878 cbb_do_power(device_t brdev)
879 {
880         struct cbb_softc *sc = device_get_softc(brdev);
881         uint32_t voltage, curpwr;
882         uint32_t status;
883
884         /* Don't enable OE (output enable) until power stable */
885         exca_clrb(&sc->exca[0], EXCA_PWRCTL, EXCA_PWRCTL_OE);
886
887         voltage = cbb_detect_voltage(brdev);
888         curpwr = cbb_current_voltage(brdev);
889         status = cbb_get(sc, CBB_SOCKET_STATE);
890         if ((status & CBB_STATE_POWER_CYCLE) && (voltage & curpwr))
891                 return 0;
892         /* Prefer lowest voltage supported */
893         cbb_power(brdev, CARD_OFF);
894         if (voltage & CARD_YV_CARD)
895                 cbb_power(brdev, CARD_VCC(YV));
896         else if (voltage & CARD_XV_CARD)
897                 cbb_power(brdev, CARD_VCC(XV));
898         else if (voltage & CARD_3V_CARD)
899                 cbb_power(brdev, CARD_VCC(3));
900         else if (voltage & CARD_5V_CARD)
901                 cbb_power(brdev, CARD_VCC(5));
902         else {
903                 device_printf(brdev, "Unknown card voltage\n");
904                 return (ENXIO);
905         }
906         return (0);
907 }
908
909 /************************************************************************/
910 /* CardBus power functions                                              */
911 /************************************************************************/
912
913 static void
914 cbb_cardbus_reset(device_t brdev)
915 {
916         struct cbb_softc *sc = device_get_softc(brdev);
917         int delay;
918
919         /*
920          * 20ms is necessary for most bridges.  For some reason, the Ricoh
921          * RF5C47x bridges need 400ms.
922          */
923         delay = sc->chipset == CB_RF5C47X ? 400 : 20;
924
925         PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, |CBBM_BRIDGECTRL_RESET, 2);
926
927         tsleep(sc, 0, "cbbP3", hz * delay / 1000);
928
929         /* If a card exists, unreset it! */
930         if (CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE))) {
931                 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL,
932                     &~CBBM_BRIDGECTRL_RESET, 2);
933                 tsleep(sc, 0, "cbbP3", hz * delay / 1000);
934         }
935 }
936
937 static int
938 cbb_cardbus_power_enable_socket(device_t brdev, device_t child)
939 {
940         struct cbb_softc *sc = device_get_softc(brdev);
941         int err;
942
943         if (!CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE)))
944                 return (ENODEV);
945
946         err = cbb_do_power(brdev);
947         if (err)
948                 return (err);
949         cbb_cardbus_reset(brdev);
950         return (0);
951 }
952
953 static void
954 cbb_cardbus_power_disable_socket(device_t brdev, device_t child)
955 {
956         cbb_power(brdev, CARD_OFF);
957         cbb_cardbus_reset(brdev);
958 }
959
960 /************************************************************************/
961 /* CardBus Resource                                                     */
962 /************************************************************************/
963
964 static int
965 cbb_cardbus_io_open(device_t brdev, int win, uint32_t start, uint32_t end)
966 {
967         int basereg;
968         int limitreg;
969
970         if ((win < 0) || (win > 1)) {
971                 DEVPRINTF((brdev,
972                     "cbb_cardbus_io_open: window out of range %d\n", win));
973                 return (EINVAL);
974         }
975
976         basereg = win * 8 + CBBR_IOBASE0;
977         limitreg = win * 8 + CBBR_IOLIMIT0;
978
979         pci_write_config(brdev, basereg, start, 4);
980         pci_write_config(brdev, limitreg, end, 4);
981         return (0);
982 }
983
984 static int
985 cbb_cardbus_mem_open(device_t brdev, int win, uint32_t start, uint32_t end)
986 {
987         int basereg;
988         int limitreg;
989
990         if ((win < 0) || (win > 1)) {
991                 DEVPRINTF((brdev,
992                     "cbb_cardbus_mem_open: window out of range %d\n", win));
993                 return (EINVAL);
994         }
995
996         basereg = win*8 + CBBR_MEMBASE0;
997         limitreg = win*8 + CBBR_MEMLIMIT0;
998
999         pci_write_config(brdev, basereg, start, 4);
1000         pci_write_config(brdev, limitreg, end, 4);
1001         return (0);
1002 }
1003
1004 /*
1005  * XXX The following function belongs in the pci bus layer.
1006  */
1007 static void
1008 cbb_cardbus_auto_open(struct cbb_softc *sc, int type)
1009 {
1010         uint32_t starts[2];
1011         uint32_t ends[2];
1012         struct cbb_reslist *rle;
1013         int align;
1014         int prefetchable[2];
1015         uint32_t reg;
1016
1017         starts[0] = starts[1] = 0xffffffff;
1018         ends[0] = ends[1] = 0;
1019
1020         if (type == SYS_RES_MEMORY)
1021                 align = CBB_MEMALIGN;
1022         else if (type == SYS_RES_IOPORT)
1023                 align = CBB_IOALIGN;
1024         else
1025                 align = 1;
1026
1027         /*
1028          * This looks somewhat bogus, and doesn't seem to really respect
1029          * alignment.  The alignment stuff is happening too late (it
1030          * should happen at allocation time, not activation time) and
1031          * this code looks generally to be too complex for the purpose
1032          * it surves.
1033          */
1034         SLIST_FOREACH(rle, &sc->rl, link) {
1035                 if (rle->type != type)
1036                         ;
1037                 else if (rle->res == NULL) {
1038                         device_printf(sc->dev, "WARNING: Resource not reserved?  "
1039                             "(type=%d, addr=%lx)\n",
1040                             rle->type, rman_get_start(rle->res));
1041                 } else if (!(rman_get_flags(rle->res) & RF_ACTIVE)) {
1042                         /* XXX */
1043                 } else if (starts[0] == 0xffffffff) {
1044                         starts[0] = rman_get_start(rle->res);
1045                         ends[0] = rman_get_end(rle->res);
1046                         prefetchable[0] =
1047                             rman_get_flags(rle->res) & RF_PREFETCHABLE;
1048                 } else if (rman_get_end(rle->res) > ends[0] &&
1049                     rman_get_start(rle->res) - ends[0] <
1050                     CBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] ==
1051                     (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1052                         ends[0] = rman_get_end(rle->res);
1053                 } else if (rman_get_start(rle->res) < starts[0] &&
1054                     starts[0] - rman_get_end(rle->res) <
1055                     CBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] ==
1056                     (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1057                         starts[0] = rman_get_start(rle->res);
1058                 } else if (starts[1] == 0xffffffff) {
1059                         starts[1] = rman_get_start(rle->res);
1060                         ends[1] = rman_get_end(rle->res);
1061                         prefetchable[1] =
1062                             rman_get_flags(rle->res) & RF_PREFETCHABLE;
1063                 } else if (rman_get_end(rle->res) > ends[1] &&
1064                     rman_get_start(rle->res) - ends[1] <
1065                     CBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] ==
1066                     (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1067                         ends[1] = rman_get_end(rle->res);
1068                 } else if (rman_get_start(rle->res) < starts[1] &&
1069                     starts[1] - rman_get_end(rle->res) <
1070                     CBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] ==
1071                     (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1072                         starts[1] = rman_get_start(rle->res);
1073                 } else {
1074                         uint32_t diffs[2];
1075                         int win;
1076
1077                         diffs[0] = diffs[1] = 0xffffffff;
1078                         if (rman_get_start(rle->res) > ends[0])
1079                                 diffs[0] = rman_get_start(rle->res) - ends[0];
1080                         else if (rman_get_end(rle->res) < starts[0])
1081                                 diffs[0] = starts[0] - rman_get_end(rle->res);
1082                         if (rman_get_start(rle->res) > ends[1])
1083                                 diffs[1] = rman_get_start(rle->res) - ends[1];
1084                         else if (rman_get_end(rle->res) < starts[1])
1085                                 diffs[1] = starts[1] - rman_get_end(rle->res);
1086
1087                         win = (diffs[0] <= diffs[1])?0:1;
1088                         if (rman_get_start(rle->res) > ends[win])
1089                                 ends[win] = rman_get_end(rle->res);
1090                         else if (rman_get_end(rle->res) < starts[win])
1091                                 starts[win] = rman_get_start(rle->res);
1092                         if (!(rman_get_flags(rle->res) & RF_PREFETCHABLE))
1093                                 prefetchable[win] = 0;
1094                 }
1095
1096                 if (starts[0] != 0xffffffff)
1097                         starts[0] -= starts[0] % align;
1098                 if (starts[1] != 0xffffffff)
1099                         starts[1] -= starts[1] % align;
1100                 if (ends[0] % align != 0)
1101                         ends[0] += align - ends[0] % align - 1;
1102                 if (ends[1] % align != 0)
1103                         ends[1] += align - ends[1] % align - 1;
1104         }
1105
1106         if (type == SYS_RES_MEMORY) {
1107                 cbb_cardbus_mem_open(sc->dev, 0, starts[0], ends[0]);
1108                 cbb_cardbus_mem_open(sc->dev, 1, starts[1], ends[1]);
1109                 reg = pci_read_config(sc->dev, CBBR_BRIDGECTRL, 2);
1110                 reg &= ~(CBBM_BRIDGECTRL_PREFETCH_0|
1111                     CBBM_BRIDGECTRL_PREFETCH_1);
1112                 reg |= (prefetchable[0]?CBBM_BRIDGECTRL_PREFETCH_0:0)|
1113                     (prefetchable[1]?CBBM_BRIDGECTRL_PREFETCH_1:0);
1114                 pci_write_config(sc->dev, CBBR_BRIDGECTRL, reg, 2);
1115         } else if (type == SYS_RES_IOPORT) {
1116                 cbb_cardbus_io_open(sc->dev, 0, starts[0], ends[0]);
1117                 cbb_cardbus_io_open(sc->dev, 1, starts[1], ends[1]);
1118         }
1119 }
1120
1121 static int
1122 cbb_cardbus_activate_resource(device_t brdev, device_t child, int type,
1123     int rid, struct resource *res)
1124 {
1125         int ret;
1126
1127         ret = BUS_ACTIVATE_RESOURCE(device_get_parent(brdev), child,
1128             type, rid, res);
1129         if (ret != 0)
1130                 return (ret);
1131         cbb_cardbus_auto_open(device_get_softc(brdev), type);
1132         return (0);
1133 }
1134
1135 static int
1136 cbb_cardbus_deactivate_resource(device_t brdev, device_t child, int type,
1137     int rid, struct resource *res)
1138 {
1139         int ret;
1140
1141         ret = BUS_DEACTIVATE_RESOURCE(device_get_parent(brdev), child,
1142             type, rid, res);
1143         if (ret != 0)
1144                 return (ret);
1145         cbb_cardbus_auto_open(device_get_softc(brdev), type);
1146         return (0);
1147 }
1148
1149 static struct resource *
1150 cbb_cardbus_alloc_resource(device_t brdev, device_t child, int type,
1151     int *rid, u_long start, u_long end, u_long count, u_int flags)
1152 {
1153         struct cbb_softc *sc = device_get_softc(brdev);
1154         int tmp;
1155         struct resource *res;
1156         u_long align;
1157
1158         switch (type) {
1159         case SYS_RES_IRQ:
1160                 tmp = rman_get_start(sc->irq_res);
1161                 if (start > tmp || end < tmp || count != 1) {
1162                         device_printf(child, "requested interrupt %ld-%ld,"
1163                             "count = %ld not supported by cbb\n",
1164                             start, end, count);
1165                         return (NULL);
1166                 }
1167                 start = end = tmp;
1168                 flags |= RF_SHAREABLE;
1169                 break;
1170         case SYS_RES_IOPORT:
1171                 if (start <= cbb_start_32_io)
1172                         start = cbb_start_32_io;
1173                 if (end < start)
1174                         end = start;
1175                 break;
1176         case SYS_RES_MEMORY:
1177                 if (start <= cbb_start_mem)
1178                         start = cbb_start_mem;
1179                 if (end < start)
1180                         end = start;
1181                 if (count < CBB_MEMALIGN)
1182                         align = CBB_MEMALIGN;
1183                 else
1184                         align = count;
1185                 if (align > (1 << RF_ALIGNMENT(flags)))
1186                         flags = (flags & ~RF_ALIGNMENT_MASK) | 
1187                             rman_make_alignment_flags(align);
1188                 break;
1189         }
1190
1191         res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid,
1192             start, end, count, flags & ~RF_ACTIVE);
1193         if (res == NULL) {
1194                 kprintf("cbb alloc res fail\n");
1195                 return (NULL);
1196         }
1197         cbb_insert_res(sc, res, type, *rid);
1198         if (flags & RF_ACTIVE)
1199                 if (bus_activate_resource(child, type, *rid, res) != 0) {
1200                         bus_release_resource(child, type, *rid, res);
1201                         return (NULL);
1202                 }
1203
1204         return (res);
1205 }
1206
1207 static int
1208 cbb_cardbus_release_resource(device_t brdev, device_t child, int type,
1209     int rid, struct resource *res)
1210 {
1211         struct cbb_softc *sc = device_get_softc(brdev);
1212         int error;
1213
1214         if (rman_get_flags(res) & RF_ACTIVE) {
1215                 error = bus_deactivate_resource(child, type, rid, res);
1216                 if (error != 0)
1217                         return (error);
1218         }
1219         cbb_remove_res(sc, res);
1220         return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child,
1221             type, rid, res));
1222 }
1223
1224 /************************************************************************/
1225 /* PC Card Power Functions                                              */
1226 /************************************************************************/
1227
1228 static int
1229 cbb_pcic_power_enable_socket(device_t brdev, device_t child)
1230 {
1231         struct cbb_softc *sc = device_get_softc(brdev);
1232         int err;
1233
1234         DPRINTF(("cbb_pcic_socket_enable:\n"));
1235
1236         /* power down/up the socket to reset */
1237         err = cbb_do_power(brdev);
1238         if (err)
1239                 return (err);
1240         exca_reset(&sc->exca[0], child);
1241
1242         return (0);
1243 }
1244
1245 static void
1246 cbb_pcic_power_disable_socket(device_t brdev, device_t child)
1247 {
1248         struct cbb_softc *sc = device_get_softc(brdev);
1249
1250         DPRINTF(("cbb_pcic_socket_disable\n"));
1251
1252         /* reset signal asserting... */
1253         exca_clrb(&sc->exca[0], EXCA_INTR, EXCA_INTR_RESET);
1254         tsleep(sc, 0, "cbbP1", hz / 100);
1255
1256         /* power down the socket */
1257         exca_clrb(&sc->exca[0], EXCA_PWRCTL, EXCA_PWRCTL_OE);
1258         cbb_power(brdev, CARD_OFF);
1259
1260         /* wait 300ms until power fails (Tpf). */
1261         tsleep(sc, 0, "cbbP1", hz * 300 / 1000);
1262 }
1263
1264 /************************************************************************/
1265 /* POWER methods                                                        */
1266 /************************************************************************/
1267
1268 int
1269 cbb_power_enable_socket(device_t brdev, device_t child)
1270 {
1271         struct cbb_softc *sc = device_get_softc(brdev);
1272
1273         if (sc->flags & CBB_16BIT_CARD)
1274                 return (cbb_pcic_power_enable_socket(brdev, child));
1275         else
1276                 return (cbb_cardbus_power_enable_socket(brdev, child));
1277 }
1278
1279 void
1280 cbb_power_disable_socket(device_t brdev, device_t child)
1281 {
1282         struct cbb_softc *sc = device_get_softc(brdev);
1283         if (sc->flags & CBB_16BIT_CARD)
1284                 cbb_pcic_power_disable_socket(brdev, child);
1285         else
1286                 cbb_cardbus_power_disable_socket(brdev, child);
1287 }
1288
1289 static int
1290 cbb_pcic_activate_resource(device_t brdev, device_t child, int type, int rid,
1291     struct resource *res)
1292 {
1293         struct cbb_softc *sc = device_get_softc(brdev);
1294         return (exca_activate_resource(&sc->exca[0], child, type, rid, res));
1295 }
1296
1297 static int
1298 cbb_pcic_deactivate_resource(device_t brdev, device_t child, int type,
1299     int rid, struct resource *res)
1300 {
1301         struct cbb_softc *sc = device_get_softc(brdev);
1302         return (exca_deactivate_resource(&sc->exca[0], child, type, rid, res));
1303 }
1304
1305 static struct resource *
1306 cbb_pcic_alloc_resource(device_t brdev, device_t child, int type, int *rid,
1307     u_long start, u_long end, u_long count, u_int flags)
1308 {
1309         struct resource *res = NULL;
1310         struct cbb_softc *sc = device_get_softc(brdev);
1311         int align;
1312         int tmp;
1313
1314         switch (type) {
1315         case SYS_RES_MEMORY:
1316                 if (start < cbb_start_mem)
1317                         start = cbb_start_mem;
1318                 if (end < start)
1319                         end = start;
1320                 if (count < CBB_MEMALIGN)
1321                         align = CBB_MEMALIGN;
1322                 else
1323                         align = count;
1324                 if (align > (1 << RF_ALIGNMENT(flags)))
1325                         flags = (flags & ~RF_ALIGNMENT_MASK) | 
1326                             rman_make_alignment_flags(align);
1327                 break;
1328         case SYS_RES_IOPORT:
1329                 if (start < cbb_start_16_io)
1330                         start = cbb_start_16_io;
1331                 if (end < start)
1332                         end = start;
1333                 break;
1334         case SYS_RES_IRQ:
1335                 tmp = rman_get_start(sc->irq_res);
1336                 if (start > tmp || end < tmp || count != 1) {
1337                         device_printf(child, "requested interrupt %ld-%ld,"
1338                             "count = %ld not supported by cbb\n",
1339                             start, end, count);
1340                         return (NULL);
1341                 }
1342                 flags |= RF_SHAREABLE;
1343                 start = end = rman_get_start(sc->irq_res);
1344                 break;
1345         }
1346         res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid,
1347             start, end, count, flags & ~RF_ACTIVE);
1348         if (res == NULL)
1349                 return (NULL);
1350         cbb_insert_res(sc, res, type, *rid);
1351         if (flags & RF_ACTIVE) {
1352                 if (bus_activate_resource(child, type, *rid, res) != 0) {
1353                         bus_release_resource(child, type, *rid, res);
1354                         return (NULL);
1355                 }
1356         }
1357
1358         return (res);
1359 }
1360
1361 static int
1362 cbb_pcic_release_resource(device_t brdev, device_t child, int type,
1363     int rid, struct resource *res)
1364 {
1365         struct cbb_softc *sc = device_get_softc(brdev);
1366         int error;
1367
1368         if (rman_get_flags(res) & RF_ACTIVE) {
1369                 error = bus_deactivate_resource(child, type, rid, res);
1370                 if (error != 0)
1371                         return (error);
1372         }
1373         cbb_remove_res(sc, res);
1374         return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child,
1375             type, rid, res));
1376 }
1377
1378 /************************************************************************/
1379 /* PC Card methods                                                      */
1380 /************************************************************************/
1381
1382 int
1383 cbb_pcic_set_res_flags(device_t brdev, device_t child, int type, int rid,
1384     uint32_t flags)
1385 {
1386         struct cbb_softc *sc = device_get_softc(brdev);
1387         struct resource *res;
1388
1389         if (type != SYS_RES_MEMORY)
1390                 return (EINVAL);
1391         res = cbb_find_res(sc, type, rid);
1392         if (res == NULL) {
1393                 device_printf(brdev,
1394                     "set_res_flags: specified rid not found\n");
1395                 return (ENOENT);
1396         }
1397         return (exca_mem_set_flags(&sc->exca[0], res, flags));
1398 }
1399
1400 int
1401 cbb_pcic_set_memory_offset(device_t brdev, device_t child, int rid,
1402     uint32_t cardaddr, uint32_t *deltap)
1403 {
1404         struct cbb_softc *sc = device_get_softc(brdev);
1405         struct resource *res;
1406
1407         res = cbb_find_res(sc, SYS_RES_MEMORY, rid);
1408         if (res == NULL) {
1409                 device_printf(brdev,
1410                     "set_memory_offset: specified rid not found\n");
1411                 return (ENOENT);
1412         }
1413         return (exca_mem_set_offset(&sc->exca[0], res, cardaddr, deltap));
1414 }
1415
1416 /************************************************************************/
1417 /* BUS Methods                                                          */
1418 /************************************************************************/
1419
1420
1421 int
1422 cbb_activate_resource(device_t brdev, device_t child, int type, int rid,
1423     struct resource *r)
1424 {
1425         struct cbb_softc *sc = device_get_softc(brdev);
1426
1427         if (sc->flags & CBB_16BIT_CARD)
1428                 return (cbb_pcic_activate_resource(brdev, child, type, rid, r));
1429         else
1430                 return (cbb_cardbus_activate_resource(brdev, child, type, rid,
1431                     r));
1432 }
1433
1434 int
1435 cbb_deactivate_resource(device_t brdev, device_t child, int type,
1436     int rid, struct resource *r)
1437 {
1438         struct cbb_softc *sc = device_get_softc(brdev);
1439
1440         if (sc->flags & CBB_16BIT_CARD)
1441                 return (cbb_pcic_deactivate_resource(brdev, child, type,
1442                     rid, r));
1443         else
1444                 return (cbb_cardbus_deactivate_resource(brdev, child, type,
1445                     rid, r));
1446 }
1447
1448 struct resource *
1449 cbb_alloc_resource(device_t brdev, device_t child, int type, int *rid,
1450     u_long start, u_long end, u_long count, u_int flags)
1451 {
1452         struct cbb_softc *sc = device_get_softc(brdev);
1453
1454         if (sc->flags & CBB_16BIT_CARD)
1455                 return (cbb_pcic_alloc_resource(brdev, child, type, rid,
1456                     start, end, count, flags));
1457         else
1458                 return (cbb_cardbus_alloc_resource(brdev, child, type, rid,
1459                     start, end, count, flags));
1460 }
1461
1462 int
1463 cbb_release_resource(device_t brdev, device_t child, int type, int rid,
1464     struct resource *r)
1465 {
1466         struct cbb_softc *sc = device_get_softc(brdev);
1467
1468         if (sc->flags & CBB_16BIT_CARD)
1469                 return (cbb_pcic_release_resource(brdev, child, type,
1470                     rid, r));
1471         else
1472                 return (cbb_cardbus_release_resource(brdev, child, type,
1473                     rid, r));
1474 }
1475
1476 int
1477 cbb_read_ivar(device_t brdev, device_t child, int which, uintptr_t *result)
1478 {
1479         struct cbb_softc *sc = device_get_softc(brdev);
1480
1481         switch (which) {
1482         case PCIB_IVAR_DOMAIN:
1483                 *result = sc->domain;
1484                 return (0);
1485         case PCIB_IVAR_BUS:
1486                 *result = sc->secbus;
1487                 return (0);
1488         }
1489         return (ENOENT);
1490 }
1491
1492 int
1493 cbb_write_ivar(device_t brdev, device_t child, int which, uintptr_t value)
1494 {
1495         struct cbb_softc *sc = device_get_softc(brdev);
1496
1497         switch (which) {
1498         case PCIB_IVAR_DOMAIN:
1499                 return (EINVAL);
1500         case PCIB_IVAR_BUS:
1501                 sc->secbus = value;
1502                 break;
1503         }
1504         return (ENOENT);
1505 }
1506
1507 /************************************************************************/
1508 /* PCI compat methods                                                   */
1509 /************************************************************************/
1510
1511 int
1512 cbb_maxslots(device_t brdev)
1513 {
1514         return (0);
1515 }
1516
1517 uint32_t
1518 cbb_read_config(device_t brdev, int b, int s, int f, int reg, int width)
1519 {
1520         uint32_t rv;
1521
1522         /*
1523          * Pass through to the next ppb up the chain (i.e. our grandparent).
1524          */
1525         rv = PCIB_READ_CONFIG(device_get_parent(device_get_parent(brdev)),
1526             b, s, f, reg, width);
1527         return (rv);
1528 }
1529
1530 void
1531 cbb_write_config(device_t brdev, int b, int s, int f, int reg, uint32_t val,
1532     int width)
1533 {
1534         /*
1535          * Pass through to the next ppb up the chain (i.e. our grandparent).
1536          */
1537         PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(brdev)),
1538             b, s, f, reg, val, width);
1539 }
1540
1541 int
1542 cbb_suspend(device_t self)
1543 {
1544         int                     error = 0;
1545         struct cbb_softc        *sc = device_get_softc(self);
1546
1547         cbb_set(sc, CBB_SOCKET_MASK, 0);        /* Quiet hardware */
1548         bus_teardown_intr(self, sc->irq_res, sc->intrhand);
1549         sc->flags &= ~CBB_CARD_OK;              /* Card is bogus now */
1550         error = bus_generic_suspend(self);
1551         return (error);
1552 }
1553
1554 int
1555 cbb_resume(device_t self)
1556 {
1557         int     error = 0;
1558         struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(self);
1559         uint32_t tmp;
1560
1561         /*
1562          * Some BIOSes will not save the BARs for the pci chips, so we
1563          * must do it ourselves.  If the BAR is reset to 0 for an I/O
1564          * device, it will read back as 0x1, so no explicit test for
1565          * memory devices are needed.
1566          *
1567          * Note: The PCI bus code should do this automatically for us on
1568          * suspend/resume, but until it does, we have to cope.
1569          */
1570         pci_write_config(self, CBBR_SOCKBASE, rman_get_start(sc->base_res), 4);
1571         DEVPRINTF((self, "PCI Memory allocated: %08lx\n",
1572             rman_get_start(sc->base_res)));
1573
1574         sc->chipinit(sc);
1575
1576         /* reset interrupt -- Do we really need to do this? */
1577         tmp = cbb_get(sc, CBB_SOCKET_EVENT);
1578         cbb_set(sc, CBB_SOCKET_EVENT, tmp);
1579
1580         /* re-establish the interrupt. */
1581         if (bus_setup_intr(self, sc->irq_res, INTR_MPSAFE, cbb_intr, sc,
1582                            &sc->intrhand, NULL)) {
1583                 device_printf(self, "couldn't re-establish interrupt");
1584                 bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res);
1585                 bus_release_resource(self, SYS_RES_MEMORY, CBBR_SOCKBASE,
1586                     sc->base_res);
1587                 sc->irq_res = NULL;
1588                 sc->base_res = NULL;
1589                 return (ENOMEM);
1590         }
1591
1592         /* CSC Interrupt: Card detect interrupt on */
1593         cbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD);
1594
1595         /* Signal the thread to wakeup. */
1596         wakeup_one(&sc->generic_cv);
1597
1598         error = bus_generic_resume(self);
1599
1600         return (error);
1601 }
1602
1603 int
1604 cbb_child_present(device_t self)
1605 {
1606         struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(self);
1607         uint32_t sockstate;
1608
1609         sockstate = cbb_get(sc, CBB_SOCKET_STATE);
1610         return (CBB_CARD_PRESENT(sockstate) &&
1611           (sc->flags & CBB_CARD_OK) == CBB_CARD_OK);
1612 }