1 /* $NetBSD: cy_pci.c,v 1.6 1997/04/13 20:14:23 cgd Exp $ */ 2 3 /* 4 * cy_pci.c 5 * 6 * Driver for Cyclades Cyclom-8/16/32 multiport serial cards 7 * (currently not tested with Cyclom-32 cards) 8 * 9 * Timo Rossi, 1996 10 * 11 */ 12 #include <sys/param.h> 13 #include <sys/systm.h> 14 #include <sys/device.h> 15 16 #include <machine/bus.h> 17 #include <machine/intr.h> 18 19 #include <dev/pci/pcivar.h> 20 #include <dev/pci/pcireg.h> 21 #include <dev/pci/pcidevs.h> 22 23 #include <dev/ic/cd1400reg.h> 24 #include <dev/ic/cyreg.h> 25 #include <dev/ic/cyvar.h> 26 27 #ifdef __BROKEN_INDIRECT_CONFIG 28 static int cy_match_pci __P((struct device *, void *, void *)); 29 #else 30 static int cy_match_pci __P((struct device *, struct cfdata *, void *)); 31 #endif 32 static void cy_attach_pci __P((struct device *, struct device *, void *)); 33 static int cy_map_pci __P((struct pci_attach_args *, bus_space_tag_t *, 34 bus_space_handle_t *, bus_size_t *, bus_space_tag_t *, 35 bus_space_handle_t *, bus_size_t *)); 36 static void cy_unmap_pci __P((bus_space_tag_t, bus_space_handle_t, 37 bus_size_t, bus_space_tag_t, bus_space_handle_t, bus_size_t)); 38 39 struct cfattach cy_pci_ca = { 40 sizeof(struct cy_softc), cy_match_pci, cy_attach_pci 41 }; 42 43 static int 44 cy_map_pci(pap, iotp, iohp, iosizep, memtp, memhp, memsizep) 45 struct pci_attach_args *pap; 46 bus_space_tag_t *iotp, *memtp; 47 bus_space_handle_t *iohp, *memhp; 48 bus_size_t *iosizep, *memsizep; 49 { 50 int ioh_valid, memh_valid; 51 52 ioh_valid = (pci_mapreg_map(pap, 0x14, 53 PCI_MAPREG_TYPE_IO, 0, 54 iotp, iohp, NULL, iosizep) == 0); 55 memh_valid = (pci_mapreg_map(pap, 0x18, 56 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, 57 memtp, memhp, NULL, memsizep) == 0); 58 59 if (ioh_valid && memh_valid) 60 return (1); 61 62 if (ioh_valid) 63 bus_space_unmap(*iotp, *iohp, *iosizep); 64 if (memh_valid) 65 bus_space_unmap(*memtp, *memhp, *memsizep); 66 return (0); 67 } 68 69 static void 70 cy_unmap_pci(iot, ioh, iosize, memt, memh, memsize) 71 bus_space_tag_t iot, memt; 72 bus_space_handle_t ioh, memh; 73 bus_size_t iosize, memsize; 74 75 { 76 bus_space_unmap(iot, ioh, iosize); 77 bus_space_unmap(memt, memh, memsize); 78 } 79 80 static int 81 cy_match_pci(parent, match, aux) 82 struct device *parent; 83 #ifdef __BROKEN_INDIRECT_CONFIG 84 void *match; 85 #else 86 struct cfdata *match; 87 #endif 88 void *aux; 89 { 90 struct pci_attach_args *pap = aux; 91 bus_space_tag_t iot, memt; 92 bus_space_handle_t ioh, memh; 93 bus_size_t iosize, memsize; 94 95 if (PCI_VENDOR(pap->pa_id) != PCI_VENDOR_CYCLADES) 96 return 0; 97 98 switch (PCI_PRODUCT(pap->pa_id)) { 99 case PCI_PRODUCT_CYCLADES_CYCLOMY_1: 100 break; 101 case PCI_PRODUCT_CYCLADES_CYCLOMY_2: 102 break; 103 default: 104 return 0; 105 } 106 107 #ifdef CY_DEBUG 108 printf("cy: Found Cyclades PCI device, id = 0x%x\n", pap->pa_id); 109 #endif 110 111 if (cy_map_pci(pap, &iot, &ioh, &iosize, &memt, &memh, &memsize) == 0) 112 return (0); 113 114 #if 0 115 XXX probably should do something like this, but this code is just 116 XXX too broken. 117 118 #ifdef CY_DEBUG 119 printf("%s: pci mapped mem 0x%lx (size %d), io 0x%x (size %d)\n", 120 sc.sc_dev.dv_xname, memaddr, memsize, iobase, iosize); 121 #endif 122 123 if ((rv = cy_find(&sc)) == 0) 124 printf("%s: PCI Cyclom card with no CD1400s!?\n", 125 sc.sc_dev.dv_xname); 126 #endif /* 0 */ 127 128 cy_unmap_pci(iot, ioh, iosize, memt, memh, memsize); 129 return (1); 130 } 131 132 133 static void 134 cy_attach_pci(parent, self, aux) 135 struct device *parent, *self; 136 void *aux; 137 { 138 struct cy_softc *sc = (void *) self; 139 struct pci_attach_args *pap = aux; 140 pci_intr_handle_t intrhandle; 141 bus_space_tag_t iot, memt; 142 bus_space_handle_t ioh, memh; 143 bus_size_t iosize, memsize; 144 const char *intrstr; 145 146 sc->sc_bustype = CY_BUSTYPE_PCI; 147 148 if (cy_map_pci(pap, &iot, &ioh, &iosize, &memt, &memh, 149 &memsize) == 0) { 150 printf(": unable to map device registers\n"); 151 return; 152 } 153 154 sc->sc_memt = memt; 155 sc->sc_bsh = memh; 156 157 if (cy_find(sc) == 0) { 158 printf(": cannot find CD1400s\n"); 159 return; 160 } 161 162 /* Set up interrupt handler. */ 163 if (pci_intr_map(pap->pa_pc, pap->pa_intrtag, pap->pa_intrpin, 164 pap->pa_intrline, &intrhandle) != 0) { 165 printf(": couldn't map PCI interrupt\n"); 166 return; 167 } 168 intrstr = pci_intr_string(pap->pa_pc, intrhandle); 169 sc->sc_ih = pci_intr_establish(pap->pa_pc, intrhandle, IPL_TTY, 170 cy_intr, sc); 171 if (sc->sc_ih == NULL) { 172 printf(": couldn't establish interrupt", sc->sc_dev.dv_xname); 173 if (intrstr != NULL) 174 printf(" at %s", intrstr); 175 printf("\n"); 176 return; 177 } 178 if (intrstr != NULL) 179 printf(": interrupting at %s\n%s", intrstr, self->dv_xname); 180 181 /* attach the hardware */ 182 cy_attach(parent, self, aux); 183 184 /* Enable PCI card interrupts */ 185 bus_space_write_2(iot, ioh, CY_PCI_INTENA, 186 bus_space_read_2(iot, ioh, CY_PCI_INTENA) | 0x900); 187 } 188