i82365_isa.c revision 1.1.2.1 1 1.1.2.1 marc #include <sys/types.h>
2 1.1.2.1 marc #include <sys/param.h>
3 1.1.2.1 marc #include <sys/systm.h>
4 1.1.2.1 marc #include <sys/device.h>
5 1.1.2.1 marc #include <sys/extent.h>
6 1.1.2.1 marc #include <sys/malloc.h>
7 1.1.2.1 marc
8 1.1.2.1 marc #include <vm/vm.h>
9 1.1.2.1 marc
10 1.1.2.1 marc #include <machine/bus.h>
11 1.1.2.1 marc #include <machine/intr.h>
12 1.1.2.1 marc
13 1.1.2.1 marc #include <dev/isa/isareg.h>
14 1.1.2.1 marc #include <dev/isa/isavar.h>
15 1.1.2.1 marc
16 1.1.2.1 marc #include <dev/pcmcia/pcmciareg.h>
17 1.1.2.1 marc #include <dev/pcmcia/pcmciavar.h>
18 1.1.2.1 marc #include <dev/pcmcia/pcmciachip.h>
19 1.1.2.1 marc
20 1.1.2.1 marc #include <dev/ic/i82365reg.h>
21 1.1.2.1 marc #include <dev/ic/i82365var.h>
22 1.1.2.1 marc
23 1.1.2.1 marc int pcic_isa_probe __P((struct device *, void *, void *));
24 1.1.2.1 marc void pcic_isa_attach __P((struct device *, struct device *, void *));
25 1.1.2.1 marc
26 1.1.2.1 marc void *pcic_isa_chip_intr_establish __P((pcmcia_chipset_handle_t,
27 1.1.2.1 marc struct pcmcia_function *, int,
28 1.1.2.1 marc int (*)(void *), void *));
29 1.1.2.1 marc void pcic_isa_chip_intr_disestablish __P((pcmcia_chipset_handle_t, void *));
30 1.1.2.1 marc
31 1.1.2.1 marc struct cfattach pcic_isa_ca = {
32 1.1.2.1 marc sizeof(struct pcic_softc), pcic_isa_probe, pcic_isa_attach
33 1.1.2.1 marc };
34 1.1.2.1 marc
35 1.1.2.1 marc static struct pcmcia_chip_functions pcic_isa_functions = {
36 1.1.2.1 marc pcic_chip_mem_alloc,
37 1.1.2.1 marc pcic_chip_mem_free,
38 1.1.2.1 marc pcic_chip_mem_map,
39 1.1.2.1 marc pcic_chip_mem_unmap,
40 1.1.2.1 marc
41 1.1.2.1 marc pcic_chip_io_alloc,
42 1.1.2.1 marc pcic_chip_io_free,
43 1.1.2.1 marc pcic_chip_io_map,
44 1.1.2.1 marc pcic_chip_io_unmap,
45 1.1.2.1 marc
46 1.1.2.1 marc pcic_isa_chip_intr_establish,
47 1.1.2.1 marc pcic_isa_chip_intr_disestablish,
48 1.1.2.1 marc
49 1.1.2.1 marc pcic_chip_socket_enable,
50 1.1.2.1 marc pcic_chip_socket_disable,
51 1.1.2.1 marc };
52 1.1.2.1 marc
53 1.1.2.1 marc int
54 1.1.2.1 marc pcic_isa_probe(parent, match, aux)
55 1.1.2.1 marc struct device *parent;
56 1.1.2.1 marc void *match, *aux;
57 1.1.2.1 marc {
58 1.1.2.1 marc struct isa_attach_args *ia = aux;
59 1.1.2.1 marc bus_space_tag_t iot = ia->ia_iot;
60 1.1.2.1 marc bus_space_handle_t ioh, memh;
61 1.1.2.1 marc int val, found;
62 1.1.2.1 marc
63 1.1.2.1 marc if (bus_space_map(iot, ia->ia_iobase, PCIC_IOSIZE, 0, &ioh))
64 1.1.2.1 marc return (0);
65 1.1.2.1 marc
66 1.1.2.1 marc if (ia->ia_msize == -1)
67 1.1.2.1 marc ia->ia_msize = PCIC_MEMSIZE;
68 1.1.2.1 marc
69 1.1.2.1 marc if (bus_space_map(ia->ia_memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
70 1.1.2.1 marc return (0);
71 1.1.2.1 marc
72 1.1.2.1 marc found = 0;
73 1.1.2.1 marc
74 1.1.2.1 marc /* this could be done with a loop, but it would violate the
75 1.1.2.1 marc abstraction */
76 1.1.2.1 marc
77 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SA+PCIC_IDENT);
78 1.1.2.1 marc
79 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
80 1.1.2.1 marc
81 1.1.2.1 marc if (pcic_ident_ok(val))
82 1.1.2.1 marc found++;
83 1.1.2.1 marc
84 1.1.2.1 marc
85 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SB+PCIC_IDENT);
86 1.1.2.1 marc
87 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
88 1.1.2.1 marc
89 1.1.2.1 marc if (pcic_ident_ok(val))
90 1.1.2.1 marc found++;
91 1.1.2.1 marc
92 1.1.2.1 marc
93 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SA+PCIC_IDENT);
94 1.1.2.1 marc
95 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
96 1.1.2.1 marc
97 1.1.2.1 marc if (pcic_ident_ok(val))
98 1.1.2.1 marc found++;
99 1.1.2.1 marc
100 1.1.2.1 marc
101 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SB+PCIC_IDENT);
102 1.1.2.1 marc
103 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
104 1.1.2.1 marc
105 1.1.2.1 marc if (pcic_ident_ok(val))
106 1.1.2.1 marc found++;
107 1.1.2.1 marc
108 1.1.2.1 marc
109 1.1.2.1 marc bus_space_unmap(iot, ioh, PCIC_IOSIZE);
110 1.1.2.1 marc bus_space_unmap(ia->ia_memt, memh, ia->ia_msize);
111 1.1.2.1 marc
112 1.1.2.1 marc if (!found)
113 1.1.2.1 marc return(0);
114 1.1.2.1 marc
115 1.1.2.1 marc ia->ia_iosize = PCIC_IOSIZE;
116 1.1.2.1 marc
117 1.1.2.1 marc return(1);
118 1.1.2.1 marc }
119 1.1.2.1 marc
120 1.1.2.1 marc void
121 1.1.2.1 marc pcic_isa_attach(parent, self, aux)
122 1.1.2.1 marc struct device *parent, *self;
123 1.1.2.1 marc void *aux;
124 1.1.2.1 marc {
125 1.1.2.1 marc struct pcic_softc *sc = (void *)self;
126 1.1.2.1 marc struct isa_attach_args *ia = aux;
127 1.1.2.1 marc isa_chipset_tag_t ic = ia->ia_ic;
128 1.1.2.1 marc bus_space_tag_t iot = ia->ia_iot;
129 1.1.2.1 marc bus_space_tag_t memt = ia->ia_memt;
130 1.1.2.1 marc bus_space_handle_t ioh;
131 1.1.2.1 marc bus_space_handle_t memh;
132 1.1.2.1 marc
133 1.1.2.1 marc /* Map i/o space. */
134 1.1.2.1 marc if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
135 1.1.2.1 marc panic("pcic_isa_attach: can't map i/o space");
136 1.1.2.1 marc
137 1.1.2.1 marc /* Map mem space. */
138 1.1.2.1 marc if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
139 1.1.2.1 marc panic("pcic_isa_attach: can't map i/o space");
140 1.1.2.1 marc
141 1.1.2.1 marc sc->membase = ia->ia_maddr;
142 1.1.2.1 marc sc->subregionmask = (1<<(ia->ia_msize/PCIC_MEM_PAGESIZE))-1;
143 1.1.2.1 marc
144 1.1.2.1 marc sc->intr_est = ic;
145 1.1.2.1 marc sc->pct = (pcmcia_chipset_tag_t) &pcic_isa_functions;
146 1.1.2.1 marc
147 1.1.2.1 marc sc->iot = iot;
148 1.1.2.1 marc sc->ioh = ioh;
149 1.1.2.1 marc sc->memt = memt;
150 1.1.2.1 marc sc->memh = memh;
151 1.1.2.1 marc
152 1.1.2.1 marc /* allocate an irq. it will be used by both controllers. I could
153 1.1.2.1 marc use two different interrupts, but interrupts are relatively
154 1.1.2.1 marc scarce, shareable, and for PCIC controllers, very infrequent. */
155 1.1.2.1 marc
156 1.1.2.1 marc if ((sc->irq = ia->ia_irq) == IRQUNK) {
157 1.1.2.1 marc /* XXX CHECK RETURN VALUE */
158 1.1.2.1 marc (void) isa_intr_alloc(ic,
159 1.1.2.1 marc PCIC_CSC_INTR_IRQ_VALIDMASK,
160 1.1.2.1 marc IST_EDGE, &sc->irq);
161 1.1.2.1 marc printf(": using irq %d", sc->irq);
162 1.1.2.1 marc }
163 1.1.2.1 marc
164 1.1.2.1 marc printf("\n");
165 1.1.2.1 marc
166 1.1.2.1 marc pcic_attach(sc);
167 1.1.2.1 marc
168 1.1.2.1 marc sc->ih = isa_intr_establish(ic, sc->irq, IST_EDGE, IPL_TTY, pcic_intr, sc);
169 1.1.2.1 marc
170 1.1.2.1 marc pcic_attach_sockets(sc);
171 1.1.2.1 marc }
172 1.1.2.1 marc
173 1.1.2.1 marc /* allow patching or kernel option file override of available IRQs.
174 1.1.2.1 marc Useful if order of probing would screw up other devices, or if PCIC
175 1.1.2.1 marc hardware/cards have trouble with certain interrupt lines. */
176 1.1.2.1 marc
177 1.1.2.1 marc #ifndef PCIC_INTR_ALLOC_MASK
178 1.1.2.1 marc #define PCIC_INTR_ALLOC_MASK 0xffff
179 1.1.2.1 marc #endif
180 1.1.2.1 marc
181 1.1.2.1 marc int pcic_intr_alloc_mask = PCIC_INTR_ALLOC_MASK;
182 1.1.2.1 marc
183 1.1.2.1 marc void *
184 1.1.2.1 marc pcic_isa_chip_intr_establish(pch, pf, ipl, fct, arg)
185 1.1.2.1 marc pcmcia_chipset_handle_t pch;
186 1.1.2.1 marc struct pcmcia_function *pf;
187 1.1.2.1 marc int ipl;
188 1.1.2.1 marc int (*fct)(void *);
189 1.1.2.1 marc void *arg;
190 1.1.2.1 marc {
191 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
192 1.1.2.1 marc int irq, ist;
193 1.1.2.1 marc void *ih;
194 1.1.2.1 marc int reg;
195 1.1.2.1 marc
196 1.1.2.1 marc if (pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)
197 1.1.2.1 marc ist = IST_LEVEL;
198 1.1.2.1 marc else if (pf->cfe->flags & PCMCIA_CFE_IRQPULSE)
199 1.1.2.1 marc ist = IST_PULSE;
200 1.1.2.1 marc else
201 1.1.2.1 marc ist = IST_LEVEL;
202 1.1.2.1 marc
203 1.1.2.1 marc if (isa_intr_alloc(h->sc->intr_est,
204 1.1.2.1 marc PCIC_INTR_IRQ_VALIDMASK & pcic_intr_alloc_mask,
205 1.1.2.1 marc ist, &irq))
206 1.1.2.1 marc return(NULL);
207 1.1.2.1 marc if (!(ih = isa_intr_establish(h->sc->intr_est, irq, ist, ipl, fct, arg)))
208 1.1.2.1 marc return(NULL);
209 1.1.2.1 marc
210 1.1.2.1 marc reg = pcic_read(h, PCIC_INTR);
211 1.1.2.1 marc reg &= ~PCIC_INTR_IRQ_MASK;
212 1.1.2.1 marc reg |= PCIC_INTR_ENABLE;
213 1.1.2.1 marc reg |= irq;
214 1.1.2.1 marc pcic_write(h, PCIC_INTR, reg);
215 1.1.2.1 marc
216 1.1.2.1 marc printf("%s: card irq %d\n", h->pcmcia->dv_xname, irq);
217 1.1.2.1 marc
218 1.1.2.1 marc return(ih);
219 1.1.2.1 marc }
220 1.1.2.1 marc
221 1.1.2.1 marc void pcic_isa_chip_intr_disestablish(pch, ih)
222 1.1.2.1 marc pcmcia_chipset_handle_t pch;
223 1.1.2.1 marc void *ih;
224 1.1.2.1 marc {
225 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
226 1.1.2.1 marc int reg;
227 1.1.2.1 marc
228 1.1.2.1 marc reg = pcic_read(h, PCIC_INTR);
229 1.1.2.1 marc reg &= ~(PCIC_INTR_IRQ_MASK|PCIC_INTR_ENABLE);
230 1.1.2.1 marc pcic_write(h, PCIC_INTR, reg);
231 1.1.2.1 marc
232 1.1.2.1 marc isa_intr_disestablish(h->sc->intr_est, ih);
233 1.1.2.1 marc }
234