Deleted Added
full compact
puc.c (102717) puc.c (102734)
1/* $NetBSD: puc.c,v 1.7 2000/07/29 17:43:38 jlam Exp $ */
2
3/*-
4 * Copyright (c) 2002 JF Hay. All rights reserved.
5 * Copyright (c) 2000 M. Warner Losh. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 44 unchanged lines hidden (view full) ---

53 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
54 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
57 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 */
59
60#include <sys/cdefs.h>
1/* $NetBSD: puc.c,v 1.7 2000/07/29 17:43:38 jlam Exp $ */
2
3/*-
4 * Copyright (c) 2002 JF Hay. All rights reserved.
5 * Copyright (c) 2000 M. Warner Losh. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 44 unchanged lines hidden (view full) ---

53 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
54 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
57 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 */
59
60#include <sys/cdefs.h>
61__FBSDID("$FreeBSD: head/sys/dev/puc/puc.c 102717 2002-08-31 18:42:31Z phk $");
61__FBSDID("$FreeBSD: head/sys/dev/puc/puc.c 102734 2002-08-31 20:29:46Z phk $");
62
63/*
64 * PCI "universal" communication card device driver, glues com, lpt,
65 * and similar ports to PCI via bridge chip often much larger than
66 * the devices being glued.
67 *
68 * Author: Christopher G. Demetriou, May 14, 1998 (derived from NetBSD
69 * sys/dev/pci/pciide.c, revision 1.6).

--- 33 unchanged lines hidden (view full) ---

103
104struct puc_device {
105 struct resource_list resources;
106 u_int serialfreq;
107};
108
109static void puc_intr(void *arg);
110
62
63/*
64 * PCI "universal" communication card device driver, glues com, lpt,
65 * and similar ports to PCI via bridge chip often much larger than
66 * the devices being glued.
67 *
68 * Author: Christopher G. Demetriou, May 14, 1998 (derived from NetBSD
69 * sys/dev/pci/pciide.c, revision 1.6).

--- 33 unchanged lines hidden (view full) ---

103
104struct puc_device {
105 struct resource_list resources;
106 u_int serialfreq;
107};
108
109static void puc_intr(void *arg);
110
111static void puc_config_superio(device_t);
112static void puc_config_win877(struct resource *);
113static int puc_find_free_unit(char *);
114#ifdef PUC_DEBUG
111static int puc_find_free_unit(char *);
112#ifdef PUC_DEBUG
115static void puc_print_win877(bus_space_tag_t, bus_space_handle_t, u_int,
116 u_int);
117static void puc_print_resource_list(struct resource_list *);
118#endif
119
113static void puc_print_resource_list(struct resource_list *);
114#endif
115
116static int
117puc_port_bar_index(struct puc_softc *sc, int bar)
118{
119 int i;
120
121 for (i = 0; i < PUC_MAX_BAR; i += 1) {
122 if (!sc->sc_bar_mappings[i].used)
123 break;
124 if (sc->sc_bar_mappings[i].bar == bar)
125 return (i);
126 }
127 sc->sc_bar_mappings[i].bar = bar;
128 sc->sc_bar_mappings[i].used = 1;
129 return (i);
130}
131
120int
121puc_attach(device_t dev, const struct puc_device_description *desc)
122{
123 char *typestr;
124 int bidx, childunit, i, irq_setup, rid;
125 struct puc_softc *sc;
126 struct puc_device *pdev;
127 struct resource *res;
128 struct resource_list_entry *rle;
129
130 sc = (struct puc_softc *)device_get_softc(dev);
131 bzero(sc, sizeof(*sc));
132 sc->sc_desc = desc;
132int
133puc_attach(device_t dev, const struct puc_device_description *desc)
134{
135 char *typestr;
136 int bidx, childunit, i, irq_setup, rid;
137 struct puc_softc *sc;
138 struct puc_device *pdev;
139 struct resource *res;
140 struct resource_list_entry *rle;
141
142 sc = (struct puc_softc *)device_get_softc(dev);
143 bzero(sc, sizeof(*sc));
144 sc->sc_desc = desc;
133
134 if (sc->sc_desc == NULL)
135 return (ENXIO);
136
137#ifdef PUC_DEBUG
138 bootverbose = 1;
139
140 printf("puc: name: %s\n", sc->sc_desc->name);
141#endif

--- 14 unchanged lines hidden (view full) ---

156 if (irq_setup != 0)
157 irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res,
158 INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie);
159 if (irq_setup != 0)
160 return (ENXIO);
161
162 rid = 0;
163 for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) {
145 if (sc->sc_desc == NULL)
146 return (ENXIO);
147
148#ifdef PUC_DEBUG
149 bootverbose = 1;
150
151 printf("puc: name: %s\n", sc->sc_desc->name);
152#endif

--- 14 unchanged lines hidden (view full) ---

167 if (irq_setup != 0)
168 irq_setup = BUS_SETUP_INTR(device_get_parent(dev), dev, res,
169 INTR_TYPE_TTY, puc_intr, sc, &sc->intr_cookie);
170 if (irq_setup != 0)
171 return (ENXIO);
172
173 rid = 0;
174 for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) {
164 if (rid == sc->sc_desc->ports[i].bar)
175 if (i > 0 && rid == sc->sc_desc->ports[i].bar)
165 sc->barmuxed = 1;
166 rid = sc->sc_desc->ports[i].bar;
176 sc->barmuxed = 1;
177 rid = sc->sc_desc->ports[i].bar;
167 bidx = PUC_PORT_BAR_INDEX(rid);
178 bidx = puc_port_bar_index(sc, rid);
168
169 if (sc->sc_bar_mappings[bidx].res != NULL)
170 continue;
171 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
172 0ul, ~0ul, 1, RF_ACTIVE);
173 if (res == NULL) {
174 printf("could not get resource\n");
175 continue;
176 }
177 sc->sc_bar_mappings[bidx].res = res;
178#ifdef PUC_DEBUG
179
180 if (sc->sc_bar_mappings[bidx].res != NULL)
181 continue;
182 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
183 0ul, ~0ul, 1, RF_ACTIVE);
184 if (res == NULL) {
185 printf("could not get resource\n");
186 continue;
187 }
188 sc->sc_bar_mappings[bidx].res = res;
189#ifdef PUC_DEBUG
179 printf("port bst %x, start %x, end %x\n",
190 printf("port rid %d bst %x, start %x, end %x\n", rid,
180 (u_int)rman_get_bustag(res), (u_int)rman_get_start(res),
181 (u_int)rman_get_end(res));
182#endif
183 }
184
191 (u_int)rman_get_bustag(res), (u_int)rman_get_start(res),
192 (u_int)rman_get_end(res));
193#endif
194 }
195
185 puc_config_superio(dev);
196 if (desc->init != NULL) {
197 i = desc->init(sc);
198 if (i != 0)
199 return (i);
200 }
186
187 for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) {
188 rid = sc->sc_desc->ports[i].bar;
201
202 for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) {
203 rid = sc->sc_desc->ports[i].bar;
189 bidx = PUC_PORT_BAR_INDEX(rid);
204 bidx = puc_port_bar_index(sc, rid);
190 if (sc->sc_bar_mappings[bidx].res == NULL)
191 continue;
192
193 switch (sc->sc_desc->ports[i].type) {
194 case PUC_PORT_TYPE_COM:
195 typestr = "sio";
196 break;
197 default:

--- 11 unchanged lines hidden (view full) ---

209 rman_get_end(sc->irqres) - rman_get_start(sc->irqres) + 1);
210 rle = resource_list_find(&pdev->resources, SYS_RES_IRQ, 0);
211 rle->res = sc->irqres;
212
213 /* Now fake an IOPORT resource */
214 res = sc->sc_bar_mappings[bidx].res;
215 resource_list_add(&pdev->resources, SYS_RES_IOPORT, 0,
216 rman_get_start(res) + sc->sc_desc->ports[i].offset,
205 if (sc->sc_bar_mappings[bidx].res == NULL)
206 continue;
207
208 switch (sc->sc_desc->ports[i].type) {
209 case PUC_PORT_TYPE_COM:
210 typestr = "sio";
211 break;
212 default:

--- 11 unchanged lines hidden (view full) ---

224 rman_get_end(sc->irqres) - rman_get_start(sc->irqres) + 1);
225 rle = resource_list_find(&pdev->resources, SYS_RES_IRQ, 0);
226 rle->res = sc->irqres;
227
228 /* Now fake an IOPORT resource */
229 res = sc->sc_bar_mappings[bidx].res;
230 resource_list_add(&pdev->resources, SYS_RES_IOPORT, 0,
231 rman_get_start(res) + sc->sc_desc->ports[i].offset,
217 rman_get_end(res) + sc->sc_desc->ports[i].offset + 8 - 1,
232 rman_get_start(res) + sc->sc_desc->ports[i].offset + 8 - 1,
218 8);
219 rle = resource_list_find(&pdev->resources, SYS_RES_IOPORT, 0);
220
221 if (sc->barmuxed == 0) {
222 rle->res = sc->sc_bar_mappings[bidx].res;
223 } else {
224 rle->res = malloc(sizeof(struct resource), M_DEVBUF,
225 M_WAITOK | M_ZERO);

--- 62 unchanged lines hidden (view full) ---

288 * tell us which device generated the interrupt.
289 */
290static void
291puc_intr(void *arg)
292{
293 int i;
294 struct puc_softc *sc;
295
233 8);
234 rle = resource_list_find(&pdev->resources, SYS_RES_IOPORT, 0);
235
236 if (sc->barmuxed == 0) {
237 rle->res = sc->sc_bar_mappings[bidx].res;
238 } else {
239 rle->res = malloc(sizeof(struct resource), M_DEVBUF,
240 M_WAITOK | M_ZERO);

--- 62 unchanged lines hidden (view full) ---

303 * tell us which device generated the interrupt.
304 */
305static void
306puc_intr(void *arg)
307{
308 int i;
309 struct puc_softc *sc;
310
311printf("puc_intr\n");
296 sc = (struct puc_softc *)arg;
297 for (i = 0; i < PUC_MAX_PORTS; i++)
298 if (sc->sc_ports[i].ihand != NULL)
299 (sc->sc_ports[i].ihand)(sc->sc_ports[i].ihandarg);
300}
301
302const struct puc_device_description *
303puc_find_description(uint32_t vend, uint32_t prod, uint32_t svend,

--- 11 unchanged lines hidden (view full) ---

315 checkreg(sprod, PUC_REG_SPROD))
316 return (&puc_devices[i]);
317 }
318
319#undef checkreg
320
321 return (NULL);
322}
312 sc = (struct puc_softc *)arg;
313 for (i = 0; i < PUC_MAX_PORTS; i++)
314 if (sc->sc_ports[i].ihand != NULL)
315 (sc->sc_ports[i].ihand)(sc->sc_ports[i].ihandarg);
316}
317
318const struct puc_device_description *
319puc_find_description(uint32_t vend, uint32_t prod, uint32_t svend,

--- 11 unchanged lines hidden (view full) ---

331 checkreg(sprod, PUC_REG_SPROD))
332 return (&puc_devices[i]);
333 }
334
335#undef checkreg
336
337 return (NULL);
338}
323
324/*
325 * It might be possible to make these more generic if we can detect patterns.
326 * For instance maybe if the size of a bar is 0x400 (the old isa space) it
327 * might contain one or more superio chips.
328 */
329static void
330puc_config_superio(device_t dev)
331{
332 struct puc_softc *sc = (struct puc_softc *)device_get_softc(dev);
333
334 if (sc->sc_desc->rval[PUC_REG_VEND] == 0x1592 &&
335 sc->sc_desc->rval[PUC_REG_PROD] == 0x0781)
336 puc_config_win877(sc->sc_bar_mappings[0].res);
337}
338
339#define rdspio(indx) (bus_space_write_1(bst, bsh, efir, indx), \
340 bus_space_read_1(bst, bsh, efdr))
341#define wrspio(indx,data) (bus_space_write_1(bst, bsh, efir, indx), \
342 bus_space_write_1(bst, bsh, efdr, data))
343
344#ifdef PUC_DEBUG
345static void
346puc_print_win877(bus_space_tag_t bst, bus_space_handle_t bsh, u_int efir,
347 u_int efdr)
348{
349 u_char cr00, cr01, cr04, cr09, cr0d, cr14, cr15, cr16, cr17;
350 u_char cr18, cr19, cr24, cr25, cr28, cr2c, cr31, cr32;
351
352 cr00 = rdspio(0x00);
353 cr01 = rdspio(0x01);
354 cr04 = rdspio(0x04);
355 cr09 = rdspio(0x09);
356 cr0d = rdspio(0x0d);
357 cr14 = rdspio(0x14);
358 cr15 = rdspio(0x15);
359 cr16 = rdspio(0x16);
360 cr17 = rdspio(0x17);
361 cr18 = rdspio(0x18);
362 cr19 = rdspio(0x19);
363 cr24 = rdspio(0x24);
364 cr25 = rdspio(0x25);
365 cr28 = rdspio(0x28);
366 cr2c = rdspio(0x2c);
367 cr31 = rdspio(0x31);
368 cr32 = rdspio(0x32);
369 printf("877T: cr00 %x, cr01 %x, cr04 %x, cr09 %x, cr0d %x, cr14 %x, "
370 "cr15 %x, cr16 %x, cr17 %x, cr18 %x, cr19 %x, cr24 %x, cr25 %x, "
371 "cr28 %x, cr2c %x, cr31 %x, cr32 %x\n", cr00, cr01, cr04, cr09,
372 cr0d, cr14, cr15, cr16, cr17,
373 cr18, cr19, cr24, cr25, cr28, cr2c, cr31, cr32);
374}
375#endif
376
377static void
378puc_config_win877(struct resource *res)
379{
380 u_char val;
381 u_int efir, efdr;
382 bus_space_tag_t bst;
383 bus_space_handle_t bsh;
384
385 bst = rman_get_bustag(res);
386 bsh = rman_get_bushandle(res);
387
388 /* configure the first W83877TF */
389 bus_space_write_1(bst, bsh, 0x250, 0x89);
390 efir = 0x251;
391 efdr = 0x252;
392 val = rdspio(0x09) & 0x0f;
393 if (val != 0x0c) {
394 printf("conf_win877: Oops not a W83877TF\n");
395 return;
396 }
397
398#ifdef PUC_DEBUG
399 printf("before: ");
400 puc_print_win877(bst, bsh, efir, efdr);
401#endif
402
403 val = rdspio(0x16);
404 val |= 0x04;
405 wrspio(0x16, val);
406 val &= ~0x04;
407 wrspio(0x16, val);
408
409 wrspio(0x24, 0x2e8 >> 2);
410 wrspio(0x25, 0x2f8 >> 2);
411 wrspio(0x17, 0x03);
412 wrspio(0x28, 0x43);
413
414#ifdef PUC_DEBUG
415 printf("after: ");
416 puc_print_win877(bst, bsh, efir, efdr);
417#endif
418
419 bus_space_write_1(bst, bsh, 0x250, 0xaa);
420
421 /* configure the second W83877TF */
422 bus_space_write_1(bst, bsh, 0x3f0, 0x87);
423 bus_space_write_1(bst, bsh, 0x3f0, 0x87);
424 efir = 0x3f0;
425 efdr = 0x3f1;
426 val = rdspio(0x09) & 0x0f;
427 if (val != 0x0c) {
428 printf("conf_win877: Oops not a W83877TF\n");
429 return;
430 }
431
432#ifdef PUC_DEBUG
433 printf("before: ");
434 puc_print_win877(bst, bsh, efir, efdr);
435#endif
436
437 val = rdspio(0x16);
438 val |= 0x04;
439 wrspio(0x16, val);
440 val &= ~0x04;
441 wrspio(0x16, val);
442
443 wrspio(0x24, 0x3e8 >> 2);
444 wrspio(0x25, 0x3f8 >> 2);
445 wrspio(0x17, 0x03);
446 wrspio(0x28, 0x43);
447
448#ifdef PUC_DEBUG
449 printf("after: ");
450 puc_print_win877(bst, bsh, efir, efdr);
451#endif
452
453 bus_space_write_1(bst, bsh, 0x3f0, 0xaa);
454}
455
456#undef rdspio
457#undef wrspio
458
459static int puc_find_free_unit(char *name)
460{
461 devclass_t dc;
462 int start;
463 int unit;
464
465 unit = 0;
466 start = 0;

--- 10 unchanged lines hidden (view full) ---

477#endif
478 return (unit);
479}
480
481#ifdef PUC_DEBUG
482static void
483puc_print_resource_list(struct resource_list *rl)
484{
339static int puc_find_free_unit(char *name)
340{
341 devclass_t dc;
342 int start;
343 int unit;
344
345 unit = 0;
346 start = 0;

--- 10 unchanged lines hidden (view full) ---

357#endif
358 return (unit);
359}
360
361#ifdef PUC_DEBUG
362static void
363puc_print_resource_list(struct resource_list *rl)
364{
365#if 0
485 struct resource_list_entry *rle;
486
487 printf("print_resource_list: rl %p\n", rl);
488 SLIST_FOREACH(rle, rl, link)
366 struct resource_list_entry *rle;
367
368 printf("print_resource_list: rl %p\n", rl);
369 SLIST_FOREACH(rle, rl, link)
489 printf("type %x, rid %x\n", rle->type, rle->rid);
370 printf(" type %x, rid %x start %x end %x count %x\n",
371 rle->type, rle->rid, rle->start, rle->end, rle->count);
490 printf("print_resource_list: end.\n");
372 printf("print_resource_list: end.\n");
373#endif
491}
492#endif
493
494struct resource *
495puc_alloc_resource(device_t dev, device_t child, int type, int *rid,
496 u_long start, u_long end, u_long count, u_int flags)
497{
498 struct puc_device *pdev;

--- 68 unchanged lines hidden (view full) ---

567
568int
569puc_setup_intr(device_t dev, device_t child, struct resource *r, int flags,
570 void (*ihand)(void *), void *arg, void **cookiep)
571{
572 int i;
573 struct puc_softc *sc;
574
374}
375#endif
376
377struct resource *
378puc_alloc_resource(device_t dev, device_t child, int type, int *rid,
379 u_long start, u_long end, u_long count, u_int flags)
380{
381 struct puc_device *pdev;

--- 68 unchanged lines hidden (view full) ---

450
451int
452puc_setup_intr(device_t dev, device_t child, struct resource *r, int flags,
453 void (*ihand)(void *), void *arg, void **cookiep)
454{
455 int i;
456 struct puc_softc *sc;
457
458printf("puc_setup_intr()\n");
575 sc = (struct puc_softc *)device_get_softc(dev);
576 for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) {
577 if (sc->sc_ports[i].dev == child) {
578 if (sc->sc_ports[i].ihand != 0)
579 return (ENXIO);
580 sc->sc_ports[i].ihand = ihand;
581 sc->sc_ports[i].ihandarg = arg;
582 *cookiep = arg;

--- 5 unchanged lines hidden (view full) ---

588
589int
590puc_teardown_intr(device_t dev, device_t child, struct resource *r,
591 void *cookie)
592{
593 int i;
594 struct puc_softc *sc;
595
459 sc = (struct puc_softc *)device_get_softc(dev);
460 for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) {
461 if (sc->sc_ports[i].dev == child) {
462 if (sc->sc_ports[i].ihand != 0)
463 return (ENXIO);
464 sc->sc_ports[i].ihand = ihand;
465 sc->sc_ports[i].ihandarg = arg;
466 *cookiep = arg;

--- 5 unchanged lines hidden (view full) ---

472
473int
474puc_teardown_intr(device_t dev, device_t child, struct resource *r,
475 void *cookie)
476{
477 int i;
478 struct puc_softc *sc;
479
480printf("puc_teardown_intr()\n");
596 sc = (struct puc_softc *)device_get_softc(dev);
597 for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) {
598 if (sc->sc_ports[i].dev == child) {
599 sc->sc_ports[i].ihand = NULL;
600 sc->sc_ports[i].ihandarg = NULL;
601 return (0);
602 }
603 }

--- 24 unchanged lines hidden ---
481 sc = (struct puc_softc *)device_get_softc(dev);
482 for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) {
483 if (sc->sc_ports[i].dev == child) {
484 sc->sc_ports[i].ihand = NULL;
485 sc->sc_ports[i].ihandarg = NULL;
486 return (0);
487 }
488 }

--- 24 unchanged lines hidden ---