1*471aeecfSnaddy /* $OpenBSD: i82365_isapnp.c,v 1.11 2022/04/06 18:59:28 naddy Exp $ */
2ca7f5f62Saaron /* $NetBSD: i82365_isapnp.c,v 1.8 2000/02/23 17:22:11 soren Exp $ */
3ca7f5f62Saaron
4ca7f5f62Saaron /*
5ca7f5f62Saaron * Copyright (c) 1998 Bill Sommerfeld. All rights reserved.
6ca7f5f62Saaron * Copyright (c) 1997 Marc Horowitz. All rights reserved.
7ca7f5f62Saaron *
8ca7f5f62Saaron * Redistribution and use in source and binary forms, with or without
9ca7f5f62Saaron * modification, are permitted provided that the following conditions
10ca7f5f62Saaron * are met:
11ca7f5f62Saaron * 1. Redistributions of source code must retain the above copyright
12ca7f5f62Saaron * notice, this list of conditions and the following disclaimer.
13ca7f5f62Saaron * 2. Redistributions in binary form must reproduce the above copyright
14ca7f5f62Saaron * notice, this list of conditions and the following disclaimer in the
15ca7f5f62Saaron * documentation and/or other materials provided with the distribution.
16ca7f5f62Saaron * 3. All advertising materials mentioning features or use of this software
17ca7f5f62Saaron * must display the following acknowledgement:
18ca7f5f62Saaron * This product includes software developed by Marc Horowitz.
19ca7f5f62Saaron * 4. The name of the author may not be used to endorse or promote products
20ca7f5f62Saaron * derived from this software without specific prior written permission.
21ca7f5f62Saaron *
22ca7f5f62Saaron * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23ca7f5f62Saaron * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24ca7f5f62Saaron * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25ca7f5f62Saaron * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26ca7f5f62Saaron * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27ca7f5f62Saaron * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28ca7f5f62Saaron * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29ca7f5f62Saaron * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30ca7f5f62Saaron * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31ca7f5f62Saaron * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32ca7f5f62Saaron */
33ca7f5f62Saaron
34ca7f5f62Saaron
35ca7f5f62Saaron #include <sys/param.h>
36ca7f5f62Saaron #include <sys/systm.h>
37ca7f5f62Saaron #include <sys/kernel.h>
38ca7f5f62Saaron #include <sys/device.h>
39ca7f5f62Saaron #include <sys/extent.h>
40ca7f5f62Saaron #include <sys/malloc.h>
41ca7f5f62Saaron
42ca7f5f62Saaron #include <machine/bus.h>
43ca7f5f62Saaron #include <machine/intr.h>
44ca7f5f62Saaron
45ca7f5f62Saaron #include <dev/isa/isareg.h>
46ca7f5f62Saaron #include <dev/isa/isavar.h>
47ca7f5f62Saaron
48ca7f5f62Saaron #include <dev/isa/isapnpreg.h>
49ca7f5f62Saaron
50ca7f5f62Saaron #include <dev/pcmcia/pcmciareg.h>
51ca7f5f62Saaron #include <dev/pcmcia/pcmciavar.h>
52ca7f5f62Saaron #include <dev/pcmcia/pcmciachip.h>
53ca7f5f62Saaron
54ca7f5f62Saaron #include <dev/ic/i82365reg.h>
55ca7f5f62Saaron #include <dev/ic/i82365var.h>
56ca7f5f62Saaron #include <dev/isa/i82365_isavar.h>
57ca7f5f62Saaron
58ca7f5f62Saaron #undef DPRINTF
59ca7f5f62Saaron #ifdef PCICISADEBUG
60ca7f5f62Saaron int pcicisapnp_debug = 0 /* XXX */ ;
61ca7f5f62Saaron #define DPRINTF(arg) if (pcicisapnp_debug) printf arg;
62ca7f5f62Saaron #else
63ca7f5f62Saaron #define DPRINTF(arg)
64ca7f5f62Saaron #endif
65ca7f5f62Saaron
66c4071fd1Smillert int pcic_isapnp_match(struct device *, void *, void *);
67c4071fd1Smillert void pcic_isapnp_attach(struct device *, struct device *, void *);
68ca7f5f62Saaron
69*471aeecfSnaddy const struct cfattach pcic_isapnp_ca = {
70ca7f5f62Saaron sizeof(struct pcic_softc), pcic_isapnp_match, pcic_isapnp_attach
71ca7f5f62Saaron };
72ca7f5f62Saaron
73ca7f5f62Saaron static struct pcmcia_chip_functions pcic_isa_functions = {
74ca7f5f62Saaron pcic_chip_mem_alloc,
75ca7f5f62Saaron pcic_chip_mem_free,
76ca7f5f62Saaron pcic_chip_mem_map,
77ca7f5f62Saaron pcic_chip_mem_unmap,
78ca7f5f62Saaron
79ca7f5f62Saaron pcic_chip_io_alloc,
80ca7f5f62Saaron pcic_chip_io_free,
81ca7f5f62Saaron pcic_chip_io_map,
82ca7f5f62Saaron pcic_chip_io_unmap,
83ca7f5f62Saaron
84ca7f5f62Saaron pcic_isa_chip_intr_establish,
85ca7f5f62Saaron pcic_isa_chip_intr_disestablish,
8693704cdeSmillert pcic_isa_chip_intr_string,
87ca7f5f62Saaron
88ca7f5f62Saaron pcic_chip_socket_enable,
89ca7f5f62Saaron pcic_chip_socket_disable,
90ca7f5f62Saaron };
91ca7f5f62Saaron
92ca7f5f62Saaron int
pcic_isapnp_match(struct device * parent,void * match,void * aux)9314124d57Sjsg pcic_isapnp_match(struct device *parent, void *match, void *aux)
94ca7f5f62Saaron {
95ca7f5f62Saaron return (1);
96ca7f5f62Saaron }
97ca7f5f62Saaron
98ca7f5f62Saaron void
pcic_isapnp_attach(struct device * parent,struct device * self,void * aux)9914124d57Sjsg pcic_isapnp_attach(struct device *parent, struct device *self, void *aux)
100ca7f5f62Saaron {
101ca7f5f62Saaron struct pcic_softc *sc = (void *) self;
102ca7f5f62Saaron struct pcic_handle *h;
103ca7f5f62Saaron struct isa_attach_args *ipa = aux;
104ca7f5f62Saaron isa_chipset_tag_t ic = ipa->ia_ic;
105ca7f5f62Saaron bus_space_tag_t iot = ipa->ia_iot;
106ca7f5f62Saaron bus_space_tag_t memt = ipa->ia_memt;
107ca7f5f62Saaron bus_space_handle_t ioh;
108ca7f5f62Saaron bus_space_handle_t memh;
109ca7f5f62Saaron int tmp1, i;
110ca7f5f62Saaron
111ca7f5f62Saaron printf("\n");
112ca7f5f62Saaron
113ca7f5f62Saaron if (isapnp_config(iot, memt, ipa)) {
114ca7f5f62Saaron printf("%s: error in region allocation\n", sc->dev.dv_xname);
115ca7f5f62Saaron return;
116ca7f5f62Saaron }
117ca7f5f62Saaron
118ca7f5f62Saaron printf("%s: %s %s", sc->dev.dv_xname, ipa->ipa_devident,
119ca7f5f62Saaron ipa->ipa_devclass);
120ca7f5f62Saaron
121ca7f5f62Saaron /* sanity check that we get at least one hunk of IO space.. */
122ca7f5f62Saaron if (ipa->ipa_nio < 1) {
123ca7f5f62Saaron printf("%s: failed to get one chunk of i/o space\n",
124ca7f5f62Saaron sc->dev.dv_xname);
125ca7f5f62Saaron return;
126ca7f5f62Saaron }
127ca7f5f62Saaron
128ca7f5f62Saaron /* Find i/o space. */
129ca7f5f62Saaron ioh = ipa->ipa_io[0].h;
130ca7f5f62Saaron
131ca7f5f62Saaron /* sanity check to make sure we have a real PCIC there.. */
132ca7f5f62Saaron bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SA + PCIC_IDENT);
133ca7f5f62Saaron tmp1 = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
134ca7f5f62Saaron printf("(ident 0x%x", tmp1);
135ca7f5f62Saaron if (pcic_ident_ok(tmp1)) {
136ca7f5f62Saaron printf(" OK)");
137ca7f5f62Saaron } else {
138ca7f5f62Saaron printf(" Not OK)\n");
139ca7f5f62Saaron return;
140ca7f5f62Saaron }
141ca7f5f62Saaron
142ca7f5f62Saaron if (bus_space_map(memt, ipa->ia_maddr, ipa->ia_msize, 0, &memh)) {
143ca7f5f62Saaron printf(": can't map mem space\n");
144ca7f5f62Saaron return;
145ca7f5f62Saaron }
146ca7f5f62Saaron
147ca7f5f62Saaron sc->membase = ipa->ia_maddr;
148ca7f5f62Saaron sc->subregionmask = (1 << (ipa->ia_msize / PCIC_MEM_PAGESIZE)) - 1;
149ca7f5f62Saaron
150ca7f5f62Saaron sc->intr_est = ic;
151ca7f5f62Saaron sc->pct = (pcmcia_chipset_tag_t) & pcic_isa_functions;
152ca7f5f62Saaron
153ca7f5f62Saaron sc->iot = iot;
154ca7f5f62Saaron sc->ioh = ioh;
155ca7f5f62Saaron sc->memt = memt;
156ca7f5f62Saaron sc->memh = memh;
157ca7f5f62Saaron
158ca7f5f62Saaron printf("\n");
159ca7f5f62Saaron
160ca7f5f62Saaron pcic_attach(sc);
161ca7f5f62Saaron pcic_isa_bus_width_probe(sc, iot, ioh, ipa->ipa_io[0].base,
162ca7f5f62Saaron ipa->ipa_io[0].length);
163ca7f5f62Saaron pcic_attach_sockets(sc);
164ca7f5f62Saaron
165ca7f5f62Saaron /*
166ca7f5f62Saaron * allocate an irq. it will be used by both controllers. I could
167ca7f5f62Saaron * use two different interrupts, but interrupts are relatively
168ca7f5f62Saaron * scarce, shareable, and for PCIC controllers, very infrequent.
169ca7f5f62Saaron */
170ca7f5f62Saaron
171ca7f5f62Saaron if (ipa->ipa_nirq > 0)
172ca7f5f62Saaron sc->irq = ipa->ipa_irq[0].num;
173ca7f5f62Saaron else
174ca7f5f62Saaron sc->irq = IRQUNK;
175ca7f5f62Saaron
176ca7f5f62Saaron if (sc->irq == IRQUNK)
177ca7f5f62Saaron sc->irq = pcic_intr_find(sc, IST_EDGE);
178ca7f5f62Saaron
179ca7f5f62Saaron if (sc->irq) {
180ca7f5f62Saaron sc->ih = isa_intr_establish(ic, sc->irq, IST_EDGE, IPL_TTY,
181ca7f5f62Saaron pcic_intr, sc, sc->dev.dv_xname);
182ca7f5f62Saaron if (!sc->ih)
183ca7f5f62Saaron sc->irq = 0;
184ca7f5f62Saaron }
185ca7f5f62Saaron
186ca7f5f62Saaron if (sc->irq) {
187ca7f5f62Saaron printf("%s: irq %d, ", sc->dev.dv_xname, sc->irq);
188ca7f5f62Saaron
189ca7f5f62Saaron /* Set up the pcic to interrupt on card detect. */
190ca7f5f62Saaron for (i = 0; i < PCIC_NSLOTS; i++) {
191ca7f5f62Saaron h = &sc->handle[i];
192ca7f5f62Saaron if (h->flags & PCIC_FLAG_SOCKETP) {
193ca7f5f62Saaron pcic_write(h, PCIC_CSC_INTR,
194ca7f5f62Saaron (sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) |
195ca7f5f62Saaron PCIC_CSC_INTR_CD_ENABLE);
196ca7f5f62Saaron }
197ca7f5f62Saaron }
198ca7f5f62Saaron } else
199ca7f5f62Saaron printf("%s: no irq, ", sc->dev.dv_xname);
200ca7f5f62Saaron
201d556510fSmiod printf("polling enabled\n");
202ca7f5f62Saaron if (sc->poll_established == 0) {
203ca7f5f62Saaron timeout_set(&sc->poll_timeout, pcic_poll_intr, sc);
2046ed05477Sblambert timeout_add_msec(&sc->poll_timeout, 500);
205ca7f5f62Saaron sc->poll_established = 1;
206ca7f5f62Saaron }
207ca7f5f62Saaron }
208