1 /* 2 * Copyright 2006 Kyma Systems LLC. 3 * All rights reserved. 4 * 5 * Written by Sanjay Lal <sanjayl@kymasys.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the NetBSD Project by 18 * Kyma Systems LLC. 19 * 4. The name of Kyma Systems LLC may not be used to endorse 20 * or promote products derived from this software without specific prior 21 * written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY KYMA SYSTEMS LLC ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KYMA SYSTEMS LLC 27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 38 #include <sys/param.h> 39 #include <sys/device.h> 40 #include <sys/systm.h> 41 42 #include <dev/pci/pcivar.h> 43 #include <dev/ofw/openfirm.h> 44 #include <dev/ofw/ofw_pci.h> 45 46 #include <machine/autoconf.h> 47 48 struct ibmcpc_softc 49 { 50 struct device sc_dev; 51 struct pci_bridge sc_pc[8]; 52 }; 53 54 void ibmcpc_attach __P((struct device *, struct device *, void *)); 55 int ibmcpc_match __P((struct device *, struct cfdata *, void *)); 56 57 pcireg_t ibmcpc_conf_read __P((pci_chipset_tag_t, pcitag_t, int)); 58 void ibmcpc_conf_write __P((pci_chipset_tag_t, pcitag_t, int, pcireg_t)); 59 60 CFATTACH_DECL(ibmcpc, sizeof(struct ibmcpc_softc), 61 ibmcpc_match, ibmcpc_attach, NULL, NULL); 62 63 #define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) 64 65 int 66 ibmcpc_match(parent, cf, aux) 67 struct device *parent; 68 struct cfdata *cf; 69 void *aux; 70 { 71 struct confargs *ca = aux; 72 char compat[32]; 73 74 if (strcmp(ca->ca_name, "ht") != 0) 75 return 0; 76 77 memset(compat, 0, sizeof(compat)); 78 OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat)); 79 80 if (strcmp(compat, "u3-ht") != 0) 81 return 0; 82 83 return 1; 84 } 85 86 void 87 ibmcpc_attach(parent, self, aux) 88 struct device *parent, *self; 89 void *aux; 90 { 91 struct ibmcpc_softc *sc = (void *) self; 92 pci_chipset_tag_t pc = sc->sc_pc; 93 struct confargs *ca = aux; 94 struct pcibus_attach_args pba; 95 int node = ca->ca_node, child; 96 u_int32_t reg[6], i; 97 void *pc_data; 98 char name[32]; 99 u_int32_t busrange[2]; 100 101 printf("\n"); 102 103 /* u3 address */ 104 if (OF_getprop(node, "reg", reg, sizeof(reg)) < 24) { 105 return; 106 } 107 printf("Mapping in config space @ pa 0x%08x, size: 0x%08x\n", reg[1], 108 reg[2]); 109 pc_data = mapiodev(reg[1], reg[2]); 110 111 for (child = OF_child(OF_finddevice("/ht")), i = 1; child; 112 child = OF_peer(child), i++) { 113 memset(name, 0, sizeof(name)); 114 115 if (OF_getprop(child, "name", name, sizeof(name)) == -1) 116 continue; 117 118 if (strcmp(name, "pci") != 0) 119 continue; 120 121 pc->node = child; 122 123 if (OF_getprop(child, "bus-range", busrange, 8) < 8) 124 continue; 125 126 pc->bus = busrange[0]; 127 pc->addr = 0x0; 128 pc->data = pc_data; 129 pc->conf_read = ibmcpc_conf_read; 130 pc->conf_write = ibmcpc_conf_write; 131 pc->memt = (bus_space_tag_t) 0; 132 pc->iot = (bus_space_tag_t) 0; 133 134 memset(&pba, 0, sizeof(pba)); 135 pba.pba_memt = pc->memt; 136 pba.pba_iot = pc->iot; 137 pba.pba_dmat = &pci_bus_dma_tag; 138 pba.pba_dmat64 = NULL; 139 pba.pba_bridgetag = NULL; 140 pba.pba_pc = pc; 141 pba.pba_bus = pc->bus; 142 pba.pba_flags = PCI_FLAGS_MEM_ENABLED | PCI_FLAGS_IO_ENABLED; 143 config_found_ia(self, "pcibus", &pba, pcibusprint); 144 145 pc++; 146 } 147 } 148 149 pcireg_t 150 ibmcpc_conf_read(pc, tag, reg) 151 pci_chipset_tag_t pc; 152 pcitag_t tag; 153 int reg; 154 { 155 u_int32_t daddr = (u_int32_t) pc->data; 156 pcireg_t data; 157 u_int32_t bus, dev, func, x, devfn; 158 159 pci_decompose_tag(pc, tag, &bus, &dev, &func); 160 161 devfn = PCI_DEVFN(dev, func); 162 163 if (bus == 0) { 164 165 if (devfn == 0x0) { 166 data = 0xffffffff; 167 goto done; 168 } 169 170 x = daddr + ((devfn << 8) | reg); 171 } 172 else 173 x = daddr + ((devfn << 8) | reg) + (bus << 16) + 0x01000000UL; 174 175 data = in32rb(x); 176 177 done: 178 return data; 179 } 180 181 void 182 ibmcpc_conf_write(pc, tag, reg, data) 183 pci_chipset_tag_t pc; 184 pcitag_t tag; 185 int reg; 186 pcireg_t data; 187 { 188 int32_t *daddr = pc->data; 189 u_int32_t bus, dev, func; 190 u_int32_t x, devfn; 191 192 pci_decompose_tag(pc, tag, &bus, &dev, &func); 193 194 devfn = PCI_DEVFN(dev, func); 195 196 if (bus == 0) { 197 if (devfn == 0x0) { 198 goto done; 199 } 200 x = (u_int32_t) daddr + ((devfn << 8) | reg); 201 } 202 else 203 x = (u_int32_t) daddr + ((devfn << 8) | reg) + (bus << 16) + 204 0x01000000UL; 205 206 out32rb(x, data); 207 208 done: 209 return; 210 } 211