1/* 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 *
| 1/* 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 *
|
26 * $Id: pcibus.c,v 1.40 1997/07/20 14:10:08 bde Exp $
| 26 * $Id: pcibus.c,v 1.41 1997/12/20 09:04:25 se Exp $
|
27 * 28 */ 29
| 27 * 28 */ 29
|
30#include <sys/types.h>
| 30#include <sys/param.h>
|
31#include <sys/systm.h>
| 31#include <sys/systm.h>
|
| 32#include <sys/bus.h> 33#include <sys/kernel.h>
|
32 33#include <pci/pcivar.h> 34#include <i386/isa/pcibus.h> 35 36#ifdef PCI_COMPAT 37/* XXX this is a terrible hack, which keeps the Tekram AMD SCSI driver happy */ 38#define cfgmech pci_mechanism 39int cfgmech; 40#else 41static int cfgmech; 42#endif /* PCI_COMPAT */ 43static int devmax; 44 45/* enable configuration space accesses and return data port address */ 46 47static int 48pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) 49{ 50 int dataport = 0; 51 52 if (bus <= PCI_BUSMAX 53 && slot < devmax 54 && func <= PCI_FUNCMAX 55 && reg <= PCI_REGMAX 56 && bytes != 3 57 && (unsigned) bytes <= 4 58 && (reg & (bytes -1)) == 0) { 59 switch (cfgmech) { 60 case 1: 61 outl(CONF1_ADDR_PORT, (1 << 31) 62 | (bus << 16) | (slot << 11) 63 | (func << 8) | (reg & ~0x03)); 64 dataport = CONF1_DATA_PORT + (reg & 0x03); 65 break; 66 case 2: 67 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); 68 outb(CONF2_FORWARD_PORT, bus); 69 dataport = 0xc000 | (slot << 8) | reg; 70 break; 71 } 72 } 73 return (dataport); 74} 75 76/* disable configuration space accesses */ 77 78static void 79pci_cfgdisable(void) 80{ 81 switch (cfgmech) { 82 case 1: 83 outl(CONF1_ADDR_PORT, 0); 84 break; 85 case 2: 86 outb(CONF2_ENABLE_PORT, 0); 87 outb(CONF2_FORWARD_PORT, 0); 88 break; 89 } 90} 91 92/* read configuration space register */ 93 94int 95pci_cfgread(pcicfgregs *cfg, int reg, int bytes) 96{ 97 int data = -1; 98 int port; 99 100 port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes); 101 102 if (port != 0) { 103 switch (bytes) { 104 case 1: 105 data = inb(port); 106 break; 107 case 2: 108 data = inw(port); 109 break; 110 case 4: 111 data = inl(port); 112 break; 113 } 114 pci_cfgdisable(); 115 } 116 return (data); 117} 118 119/* write configuration space register */ 120 121void 122pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes) 123{ 124 int port; 125 126 port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes); 127 if (port != 0) { 128 switch (bytes) { 129 case 1: 130 outb(port, data); 131 break; 132 case 2: 133 outw(port, data); 134 break; 135 case 4: 136 outl(port, data); 137 break; 138 } 139 pci_cfgdisable(); 140 } 141} 142 143/* check whether the configuration mechanism has been correct identified */ 144 145static int 146pci_cfgcheck(int maxdev) 147{ 148 u_char device; 149 150 if (bootverbose) 151 printf("pci_cfgcheck:\tdevice "); 152 153 for (device = 0; device < maxdev; device++) { 154 unsigned id, class, header; 155 if (bootverbose) 156 printf("%d ", device); 157 158 id = inl(pci_cfgenable(0, device, 0, 0, 4)); 159 if (id == 0 || id == -1) 160 continue; 161 162 class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8; 163 if (bootverbose) 164 printf("[class=%06x] ", class); 165 if (class == 0 || (class & 0xf870ff) != 0) 166 continue; 167 168 header = inb(pci_cfgenable(0, device, 0, 14, 1)); 169 if (bootverbose) 170 printf("[hdr=%02x] ", header); 171 if ((header & 0x7e) != 0) 172 continue; 173 174 if (bootverbose) 175 printf("is there (id=%08x)\n", id); 176 177 pci_cfgdisable(); 178 return (1); 179 } 180 if (bootverbose) 181 printf("-- nothing found\n"); 182 183 pci_cfgdisable(); 184 return (0); 185} 186
| 34 35#include <pci/pcivar.h> 36#include <i386/isa/pcibus.h> 37 38#ifdef PCI_COMPAT 39/* XXX this is a terrible hack, which keeps the Tekram AMD SCSI driver happy */ 40#define cfgmech pci_mechanism 41int cfgmech; 42#else 43static int cfgmech; 44#endif /* PCI_COMPAT */ 45static int devmax; 46 47/* enable configuration space accesses and return data port address */ 48 49static int 50pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) 51{ 52 int dataport = 0; 53 54 if (bus <= PCI_BUSMAX 55 && slot < devmax 56 && func <= PCI_FUNCMAX 57 && reg <= PCI_REGMAX 58 && bytes != 3 59 && (unsigned) bytes <= 4 60 && (reg & (bytes -1)) == 0) { 61 switch (cfgmech) { 62 case 1: 63 outl(CONF1_ADDR_PORT, (1 << 31) 64 | (bus << 16) | (slot << 11) 65 | (func << 8) | (reg & ~0x03)); 66 dataport = CONF1_DATA_PORT + (reg & 0x03); 67 break; 68 case 2: 69 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); 70 outb(CONF2_FORWARD_PORT, bus); 71 dataport = 0xc000 | (slot << 8) | reg; 72 break; 73 } 74 } 75 return (dataport); 76} 77 78/* disable configuration space accesses */ 79 80static void 81pci_cfgdisable(void) 82{ 83 switch (cfgmech) { 84 case 1: 85 outl(CONF1_ADDR_PORT, 0); 86 break; 87 case 2: 88 outb(CONF2_ENABLE_PORT, 0); 89 outb(CONF2_FORWARD_PORT, 0); 90 break; 91 } 92} 93 94/* read configuration space register */ 95 96int 97pci_cfgread(pcicfgregs *cfg, int reg, int bytes) 98{ 99 int data = -1; 100 int port; 101 102 port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes); 103 104 if (port != 0) { 105 switch (bytes) { 106 case 1: 107 data = inb(port); 108 break; 109 case 2: 110 data = inw(port); 111 break; 112 case 4: 113 data = inl(port); 114 break; 115 } 116 pci_cfgdisable(); 117 } 118 return (data); 119} 120 121/* write configuration space register */ 122 123void 124pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes) 125{ 126 int port; 127 128 port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes); 129 if (port != 0) { 130 switch (bytes) { 131 case 1: 132 outb(port, data); 133 break; 134 case 2: 135 outw(port, data); 136 break; 137 case 4: 138 outl(port, data); 139 break; 140 } 141 pci_cfgdisable(); 142 } 143} 144 145/* check whether the configuration mechanism has been correct identified */ 146 147static int 148pci_cfgcheck(int maxdev) 149{ 150 u_char device; 151 152 if (bootverbose) 153 printf("pci_cfgcheck:\tdevice "); 154 155 for (device = 0; device < maxdev; device++) { 156 unsigned id, class, header; 157 if (bootverbose) 158 printf("%d ", device); 159 160 id = inl(pci_cfgenable(0, device, 0, 0, 4)); 161 if (id == 0 || id == -1) 162 continue; 163 164 class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8; 165 if (bootverbose) 166 printf("[class=%06x] ", class); 167 if (class == 0 || (class & 0xf870ff) != 0) 168 continue; 169 170 header = inb(pci_cfgenable(0, device, 0, 14, 1)); 171 if (bootverbose) 172 printf("[hdr=%02x] ", header); 173 if ((header & 0x7e) != 0) 174 continue; 175 176 if (bootverbose) 177 printf("is there (id=%08x)\n", id); 178 179 pci_cfgdisable(); 180 return (1); 181 } 182 if (bootverbose) 183 printf("-- nothing found\n"); 184 185 pci_cfgdisable(); 186 return (0); 187} 188
|
187int
| 189static int
|
188pci_cfgopen(void) 189{ 190 unsigned long mode1res,oldval1; 191 unsigned char mode2res,oldval2; 192 193 oldval1 = inl(CONF1_ADDR_PORT); 194 195 if (bootverbose) { 196 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", 197 oldval1); 198 } 199 200 if ((oldval1 & CONF1_ENABLE_MSK) == 0) { 201 202 cfgmech = 1; 203 devmax = 32; 204 205 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 206 outb(CONF1_ADDR_PORT +3, 0); 207 mode1res = inl(CONF1_ADDR_PORT); 208 outl(CONF1_ADDR_PORT, oldval1); 209 210 if (bootverbose) 211 printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n", 212 mode1res, CONF1_ENABLE_CHK); 213 214 if (mode1res) { 215 if (pci_cfgcheck(32)) 216 return (cfgmech); 217 } 218 219 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 220 mode1res = inl(CONF1_ADDR_PORT); 221 outl(CONF1_ADDR_PORT, oldval1); 222 223 if (bootverbose) 224 printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n", 225 mode1res, CONF1_ENABLE_CHK1); 226 227 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 228 if (pci_cfgcheck(32)) 229 return (cfgmech); 230 } 231 } 232 233 oldval2 = inb(CONF2_ENABLE_PORT); 234 235 if (bootverbose) { 236 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", 237 oldval2); 238 } 239 240 if ((oldval2 & 0xf0) == 0) { 241 242 cfgmech = 2; 243 devmax = 16; 244 245 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 246 mode2res = inb(CONF2_ENABLE_PORT); 247 outb(CONF2_ENABLE_PORT, oldval2); 248 249 if (bootverbose) 250 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 251 mode2res, CONF2_ENABLE_CHK); 252 253 if (mode2res == CONF2_ENABLE_RES) { 254 if (bootverbose) 255 printf("pci_open(2a):\tnow trying mechanism 2\n"); 256 257 if (pci_cfgcheck(16)) 258 return (cfgmech); 259 } 260 } 261 262 cfgmech = 0; 263 devmax = 0; 264 return (cfgmech); 265}
| 190pci_cfgopen(void) 191{ 192 unsigned long mode1res,oldval1; 193 unsigned char mode2res,oldval2; 194 195 oldval1 = inl(CONF1_ADDR_PORT); 196 197 if (bootverbose) { 198 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", 199 oldval1); 200 } 201 202 if ((oldval1 & CONF1_ENABLE_MSK) == 0) { 203 204 cfgmech = 1; 205 devmax = 32; 206 207 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 208 outb(CONF1_ADDR_PORT +3, 0); 209 mode1res = inl(CONF1_ADDR_PORT); 210 outl(CONF1_ADDR_PORT, oldval1); 211 212 if (bootverbose) 213 printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n", 214 mode1res, CONF1_ENABLE_CHK); 215 216 if (mode1res) { 217 if (pci_cfgcheck(32)) 218 return (cfgmech); 219 } 220 221 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 222 mode1res = inl(CONF1_ADDR_PORT); 223 outl(CONF1_ADDR_PORT, oldval1); 224 225 if (bootverbose) 226 printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n", 227 mode1res, CONF1_ENABLE_CHK1); 228 229 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 230 if (pci_cfgcheck(32)) 231 return (cfgmech); 232 } 233 } 234 235 oldval2 = inb(CONF2_ENABLE_PORT); 236 237 if (bootverbose) { 238 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", 239 oldval2); 240 } 241 242 if ((oldval2 & 0xf0) == 0) { 243 244 cfgmech = 2; 245 devmax = 16; 246 247 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 248 mode2res = inb(CONF2_ENABLE_PORT); 249 outb(CONF2_ENABLE_PORT, oldval2); 250 251 if (bootverbose) 252 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 253 mode2res, CONF2_ENABLE_CHK); 254 255 if (mode2res == CONF2_ENABLE_RES) { 256 if (bootverbose) 257 printf("pci_open(2a):\tnow trying mechanism 2\n"); 258 259 if (pci_cfgcheck(16)) 260 return (cfgmech); 261 } 262 } 263 264 cfgmech = 0; 265 devmax = 0; 266 return (cfgmech); 267}
|
| 268 269static devclass_t pcib_devclass; 270 271static int 272nexus_pcib_probe(device_t dev) 273{ 274 if (pci_cfgopen() != 0) { 275 device_set_desc(dev, "PCI host bus adapter"); 276 277 device_add_child(dev, "pci", 0, 0); 278 return 0; 279 } 280 return ENXIO; 281} 282 283static device_method_t nexus_pcib_methods[] = { 284 /* Device interface */ 285 DEVMETHOD(device_probe, nexus_pcib_probe), 286 DEVMETHOD(device_attach, bus_generic_attach), 287 DEVMETHOD(device_shutdown, bus_generic_shutdown), 288 DEVMETHOD(device_suspend, bus_generic_suspend), 289 DEVMETHOD(device_resume, bus_generic_resume), 290 291 /* Bus interface */ 292 DEVMETHOD(bus_print_child, bus_generic_print_child), 293 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 294 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 295 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 296 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 297 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 298 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 299 300 { 0, 0 } 301}; 302 303static driver_t nexus_pcib_driver = { 304 "pcib", 305 nexus_pcib_methods, 306 1, 307}; 308 309DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0);
|
| |