This source file includes following definitions.
- com_cardbus_find_csdev
- com_cardbus_match
- com_cardbus_gofigure
- com_cardbus_attach
- com_cardbus_setup
- com_cardbus_enable
- com_cardbus_disable
- com_cardbus_detach
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/tty.h>
52 #include <sys/device.h>
53
54 #include <dev/cardbus/cardbusvar.h>
55 #include <dev/pci/pcidevs.h>
56
57 #include <dev/pcmcia/pcmciareg.h>
58
59 #include "com.h"
60 #ifdef i386
61 #include "pccom.h"
62 #endif
63
64 #include <dev/ic/comreg.h>
65 #if NPCCOM > 0
66 #include <i386/isa/pccomvar.h>
67 #endif
68 #if NCOM > 0
69 #include <dev/ic/comvar.h>
70 #endif
71 #include <dev/ic/ns16550reg.h>
72
73 #define com_lcr com_cfcr
74
75 struct com_cardbus_softc {
76 struct com_softc cc_com;
77 void *cc_ih;
78 cardbus_devfunc_t cc_ct;
79 bus_addr_t cc_addr;
80 cardbusreg_t cc_base;
81 bus_size_t cc_size;
82 cardbusreg_t cc_csr;
83 int cc_cben;
84 cardbustag_t cc_tag;
85 cardbusreg_t cc_reg;
86 int cc_type;
87 u_char cc_bug;
88 };
89
90 #define DEVNAME(CSC) ((CSC)->cc_com.sc_dev.dv_xname)
91
92 int com_cardbus_match(struct device *, void *, void *);
93 void com_cardbus_attach(struct device *, struct device *, void *);
94 int com_cardbus_detach(struct device *, int);
95
96 void com_cardbus_setup(struct com_cardbus_softc *);
97 int com_cardbus_enable(struct com_softc *);
98 void com_cardbus_disable(struct com_softc *);
99 struct csdev *com_cardbus_find_csdev(struct cardbus_attach_args *);
100 int com_cardbus_gofigure(struct cardbus_attach_args *,
101 struct com_cardbus_softc *);
102
103 #if NCOM_CARDBUS
104 struct cfattach com_cardbus_ca = {
105 sizeof(struct com_cardbus_softc), com_cardbus_match,
106 com_cardbus_attach, com_cardbus_detach, com_activate
107 };
108 #elif NPCCOM_CARDBUS
109 struct cfattach pccom_cardbus_ca = {
110 sizeof(struct com_cardbus_softc), com_cardbus_match,
111 com_cardbus_attach, com_cardbus_detach, com_activate
112 };
113 #endif
114
115 #define BUG_BROADCOM 0x01
116
117 static struct csdev {
118 u_short vendor;
119 u_short product;
120 cardbusreg_t reg;
121 u_char type;
122 u_char bug;
123 } csdevs[] = {
124 { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_GLOBALMODEM56,
125 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
126 { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_MODEM56,
127 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
128 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4322,
129 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO, BUG_BROADCOM },
130 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_SERIAL,
131 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO, BUG_BROADCOM },
132 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_SERIAL_GC,
133 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
134 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MODEM56,
135 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
136 { PCI_VENDOR_OXFORD2, PCI_PRODUCT_OXFORD2_OXCB950,
137 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
138 { PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_CBEM56G,
139 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
140 { PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_MODEM56,
141 CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO }
142 };
143
144 static const int ncsdevs = sizeof(csdevs) / sizeof(csdevs[0]);
145
146 struct csdev*
147 com_cardbus_find_csdev(struct cardbus_attach_args *ca)
148 {
149 struct csdev *cp;
150
151 for (cp = csdevs; cp < csdevs + ncsdevs; cp++)
152 if (cp->vendor == CARDBUS_VENDOR(ca->ca_id) &&
153 cp->product == CARDBUS_PRODUCT(ca->ca_id))
154 return (cp);
155 return (NULL);
156 }
157
158 int
159 com_cardbus_match(struct device *parent, void *match, void *aux)
160 {
161 struct cardbus_attach_args *ca = aux;
162
163
164 if (com_cardbus_find_csdev(ca) != NULL)
165 return (10);
166
167
168 if (ca->ca_cis.funcid == PCMCIA_FUNCTION_SERIAL &&
169 ca->ca_cis.funce.serial.uart_present != 0 &&
170 (ca->ca_cis.funce.serial.uart_type == 0 ||
171 ca->ca_cis.funce.serial.uart_type == 1 ||
172 ca->ca_cis.funce.serial.uart_type == 2))
173 return (1);
174
175 return (0);
176 }
177
178 int
179 com_cardbus_gofigure(struct cardbus_attach_args *ca,
180 struct com_cardbus_softc *csc)
181 {
182 int i, index = -1;
183 cardbusreg_t cis_ptr;
184 struct csdev *cp;
185
186
187 cp = com_cardbus_find_csdev(ca);
188 if (cp != NULL) {
189 csc->cc_reg = cp->reg;
190 csc->cc_type = cp->type;
191 csc->cc_bug = cp->bug;
192 return (0);
193 }
194
195 cis_ptr = Cardbus_conf_read(csc->cc_ct, csc->cc_tag, CARDBUS_CIS_REG);
196
197
198
199
200 for (i = 0; i < 7; i++) {
201
202 if (ca->ca_cis.bar[i].size == 0)
203 continue;
204
205 if (CARDBUS_CIS_ASI_BAR(cis_ptr) ==
206 CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags))
207 continue;
208 if (index != -1)
209 goto multi_bar;
210 index = i;
211 }
212 if (index == -1) {
213 printf(": couldn't find any base address tuple\n");
214 return (1);
215 }
216 csc->cc_reg = CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[index].flags);
217 if ((ca->ca_cis.bar[index].flags & 0x10) == 0)
218 csc->cc_type = CARDBUS_MAPREG_TYPE_MEM;
219 else
220 csc->cc_type = CARDBUS_MAPREG_TYPE_IO;
221 return (0);
222
223 multi_bar:
224 printf(": there are more than one possible base\n");
225
226 printf("%s: address for this device, "
227 "please report the following information\n",
228 DEVNAME(csc));
229 printf("%s: vendor 0x%x product 0x%x\n", DEVNAME(csc),
230 CARDBUS_VENDOR(ca->ca_id), CARDBUS_PRODUCT(ca->ca_id));
231 for (i = 0; i < 7; i++) {
232
233 if (ca->ca_cis.bar[i].size == 0)
234 continue;
235
236 if (CARDBUS_CIS_ASI_BAR(cis_ptr) ==
237 CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags))
238 continue;
239 printf("%s: base address %x type %s size %x\n",
240 DEVNAME(csc), CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags),
241 (ca->ca_cis.bar[i].flags & 0x10) ? "i/o" : "mem",
242 ca->ca_cis.bar[i].size);
243 }
244 return (1);
245 }
246
247 void
248 com_cardbus_attach(struct device *parent, struct device *self, void *aux)
249 {
250 struct com_softc *sc = (struct com_softc*)self;
251 struct com_cardbus_softc *csc = (struct com_cardbus_softc*)self;
252 struct cardbus_attach_args *ca = aux;
253
254 csc->cc_ct = ca->ca_ct;
255 csc->cc_tag = Cardbus_make_tag(csc->cc_ct);
256
257 if (com_cardbus_gofigure(ca, csc) != 0)
258 return;
259
260 if (Cardbus_mapreg_map(ca->ca_ct, csc->cc_reg, csc->cc_type, 0,
261 &sc->sc_iot, &sc->sc_ioh, &csc->cc_addr, &csc->cc_size) != 0) {
262 printf("failed to map memory");
263 return;
264 }
265
266 csc->cc_base = csc->cc_addr;
267 csc->cc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
268 if (csc->cc_type == CARDBUS_MAPREG_TYPE_IO) {
269 csc->cc_base |= CARDBUS_MAPREG_TYPE_IO;
270 csc->cc_csr |= CARDBUS_COMMAND_IO_ENABLE;
271 csc->cc_cben = CARDBUS_IO_ENABLE;
272 } else {
273 csc->cc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
274 csc->cc_cben = CARDBUS_MEM_ENABLE;
275 }
276
277 sc->sc_iobase = csc->cc_addr;
278 sc->sc_frequency = COM_FREQ;
279
280 sc->enable = com_cardbus_enable;
281 sc->disable = com_cardbus_disable;
282 sc->enabled = 0;
283
284 if (ca->ca_cis.cis1_info[0] && ca->ca_cis.cis1_info[1]) {
285 printf(": %s %s\n", ca->ca_cis.cis1_info[0],
286 ca->ca_cis.cis1_info[1]);
287 printf("%s", DEVNAME(csc));
288 }
289
290 if (com_cardbus_enable(sc))
291 printf(": function enable failed\n");
292 sc->enabled = 1;
293
294 sc->sc_hwflags = 0;
295 sc->sc_swflags = 0;
296
297 if (csc->cc_bug & BUG_BROADCOM)
298 sc->sc_fifolen = 15;
299
300 com_attach_subr(sc);
301 }
302
303 void
304 com_cardbus_setup(struct com_cardbus_softc *csc)
305 {
306 cardbus_devfunc_t ct = csc->cc_ct;
307 cardbus_chipset_tag_t cc = ct->ct_cc;
308 cardbus_function_tag_t cf = ct->ct_cf;
309 cardbusreg_t reg;
310
311 cardbus_conf_write(cc, cf, csc->cc_tag, csc->cc_reg, csc->cc_base);
312
313
314 cf->cardbus_ctrl(cc, csc->cc_cben);
315 cf->cardbus_ctrl(cc, CARDBUS_BM_ENABLE);
316
317
318 reg = cardbus_conf_read(cc, cf, csc->cc_tag, CARDBUS_COMMAND_STATUS_REG);
319 reg &= ~(CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE);
320 reg |= csc->cc_csr;
321 cardbus_conf_write(cc, cf, csc->cc_tag, CARDBUS_COMMAND_STATUS_REG, reg);
322
323
324
325
326
327 reg = cardbus_conf_read(cc, cf, csc->cc_tag, CARDBUS_BHLC_REG);
328 if (CARDBUS_LATTIMER(reg) < 0x20) {
329 reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
330 reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
331 cardbus_conf_write(cc, cf, csc->cc_tag, CARDBUS_BHLC_REG, reg);
332 }
333 }
334
335 int
336 com_cardbus_enable(struct com_softc *sc)
337 {
338 struct com_cardbus_softc *csc = (struct com_cardbus_softc*)sc;
339 struct cardbus_softc *psc =
340 (struct cardbus_softc *)sc->sc_dev.dv_parent;
341 cardbus_chipset_tag_t cc = psc->sc_cc;
342 cardbus_function_tag_t cf = psc->sc_cf;
343
344 Cardbus_function_enable(csc->cc_ct);
345
346 com_cardbus_setup(csc);
347
348
349 csc->cc_ih = cardbus_intr_establish(cc, cf, psc->sc_intrline,
350 IPL_TTY, comintr, sc, DEVNAME(csc));
351 if (csc->cc_ih == NULL) {
352 printf("%s: couldn't establish interrupt\n", DEVNAME(csc));
353 return (1);
354 }
355
356 printf(": irq %d", psc->sc_intrline);
357
358 return (0);
359 }
360
361 void
362 com_cardbus_disable(struct com_softc *sc)
363 {
364 struct com_cardbus_softc *csc = (struct com_cardbus_softc*)sc;
365 struct cardbus_softc *psc =
366 (struct cardbus_softc *)sc->sc_dev.dv_parent;
367 cardbus_chipset_tag_t cc = psc->sc_cc;
368 cardbus_function_tag_t cf = psc->sc_cf;
369
370 cardbus_intr_disestablish(cc, cf, csc->cc_ih);
371 Cardbus_function_disable(csc->cc_ct);
372 }
373
374 int
375 com_cardbus_detach(struct device *self, int flags)
376 {
377 struct com_cardbus_softc *csc = (struct com_cardbus_softc *) self;
378 struct com_softc *sc = (struct com_softc *) self;
379 struct cardbus_softc *psc = (struct cardbus_softc *)self->dv_parent;
380 int error;
381
382 if ((error = com_detach(self, flags)) != 0)
383 return (error);
384
385 cardbus_intr_disestablish(psc->sc_cc, psc->sc_cf, csc->cc_ih);
386
387 Cardbus_mapreg_unmap(csc->cc_ct, csc->cc_reg, sc->sc_iot, sc->sc_ioh,
388 csc->cc_size);
389
390 return (0);
391 }