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