1/************************************************************************** 2**
| 1/************************************************************************** 2**
|
3** $Id: pcibus.c,v 1.10 1995/06/30 16:11:42 se Exp $
| 3** $Id: pcibus.c,v 1.11 1995/09/13 17:03:47 se Exp $
|
4** 5** pci bus subroutines for i386 architecture. 6** 7** FreeBSD 8** 9**------------------------------------------------------------------------- 10** 11** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. 12** 13** Redistribution and use in source and binary forms, with or without 14** modification, are permitted provided that the following conditions 15** are met: 16** 1. Redistributions of source code must retain the above copyright 17** notice, this list of conditions and the following disclaimer. 18** 2. Redistributions in binary form must reproduce the above copyright 19** notice, this list of conditions and the following disclaimer in the 20** documentation and/or other materials provided with the distribution. 21** 3. The name of the author may not be used to endorse or promote products 22** derived from this software without specific prior written permission. 23** 24** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34** 35*************************************************************************** 36*/ 37 38#define __PCIBUS_C___ "pl4 95/03/21" 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/kernel.h> 43 44#include <i386/isa/icu.h> 45#include <i386/isa/isa.h> 46#include <i386/isa/isa_device.h> 47 48#include <pci/pcivar.h> 49#include <pci/pcireg.h> 50#include <pci/pcibus.h> 51 52/*----------------------------------------------------------------- 53** 54** The following functions are provided by the pci bios. 55** They are used only by the pci configuration. 56** 57** pcibus_setup(): 58** Probes for a pci system. 59** Sets pci_maxdevice and pci_mechanism. 60** 61** pcibus_tag(): 62** Creates a handle for pci configuration space access. 63** This handle is given to the read/write functions. 64** 65** pcibus_ftag(): 66** Creates a modified handle. 67** 68** pcibus_read(): 69** Read a long word from the pci configuration space. 70** Requires a tag (from pcitag) and the register 71** number (should be a long word alligned one). 72** 73** pcibus_write(): 74** Writes a long word to the pci configuration space. 75** Requires a tag (from pcitag), the register number 76** (should be a long word alligned one), and a value. 77** 78** pcibus_regirq(): 79** Register an interupt handler for a pci device. 80** Requires a tag (from pcitag), the register number 81** (should be a long word alligned one), and a value. 82** 83**----------------------------------------------------------------- 84*/ 85
| 4** 5** pci bus subroutines for i386 architecture. 6** 7** FreeBSD 8** 9**------------------------------------------------------------------------- 10** 11** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. 12** 13** Redistribution and use in source and binary forms, with or without 14** modification, are permitted provided that the following conditions 15** are met: 16** 1. Redistributions of source code must retain the above copyright 17** notice, this list of conditions and the following disclaimer. 18** 2. Redistributions in binary form must reproduce the above copyright 19** notice, this list of conditions and the following disclaimer in the 20** documentation and/or other materials provided with the distribution. 21** 3. The name of the author may not be used to endorse or promote products 22** derived from this software without specific prior written permission. 23** 24** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34** 35*************************************************************************** 36*/ 37 38#define __PCIBUS_C___ "pl4 95/03/21" 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/kernel.h> 43 44#include <i386/isa/icu.h> 45#include <i386/isa/isa.h> 46#include <i386/isa/isa_device.h> 47 48#include <pci/pcivar.h> 49#include <pci/pcireg.h> 50#include <pci/pcibus.h> 51 52/*----------------------------------------------------------------- 53** 54** The following functions are provided by the pci bios. 55** They are used only by the pci configuration. 56** 57** pcibus_setup(): 58** Probes for a pci system. 59** Sets pci_maxdevice and pci_mechanism. 60** 61** pcibus_tag(): 62** Creates a handle for pci configuration space access. 63** This handle is given to the read/write functions. 64** 65** pcibus_ftag(): 66** Creates a modified handle. 67** 68** pcibus_read(): 69** Read a long word from the pci configuration space. 70** Requires a tag (from pcitag) and the register 71** number (should be a long word alligned one). 72** 73** pcibus_write(): 74** Writes a long word to the pci configuration space. 75** Requires a tag (from pcitag), the register number 76** (should be a long word alligned one), and a value. 77** 78** pcibus_regirq(): 79** Register an interupt handler for a pci device. 80** Requires a tag (from pcitag), the register number 81** (should be a long word alligned one), and a value. 82** 83**----------------------------------------------------------------- 84*/ 85
|
| 86static int 87pcibus_check (void); 88
|
86static void 87pcibus_setup (void); 88 89static pcici_t 90pcibus_tag (u_char bus, u_char device, u_char func); 91 92static pcici_t 93pcibus_ftag (pcici_t tag, u_char func); 94 95static u_long 96pcibus_read (pcici_t tag, u_long reg); 97 98static void 99pcibus_write (pcici_t tag, u_long reg, u_long data); 100 101static int 102pcibus_ihandler_attach (int irq, void(*ihandler)(), int arg, unsigned* maskp); 103 104static int 105pcibus_ihandler_detach (int irq, void(*handler)()); 106 107static int 108pcibus_imask_include (int irq, unsigned* maskptr); 109 110static int 111pcibus_imask_exclude (int irq, unsigned* maskptr); 112 113struct pcibus i386pci = { 114 "pci", 115 pcibus_setup, 116 pcibus_tag, 117 pcibus_ftag, 118 pcibus_read, 119 pcibus_write, 120 ICU_LEN, 121 pcibus_ihandler_attach, 122 pcibus_ihandler_detach, 123 pcibus_imask_include, 124 pcibus_imask_exclude, 125}; 126 127/* 128** Announce structure to generic driver 129*/ 130 131DATA_SET (pcibus_set, i386pci); 132 133/*-------------------------------------------------------------------- 134** 135** Determine configuration mode 136** 137**-------------------------------------------------------------------- 138*/ 139 140 141#define CONF1_ENABLE 0x80000000ul 142#define CONF1_ENABLE_CHK1 0xF0000000ul 143#define CONF1_ENABLE_CHK2 0xfffffffful 144#define CONF1_ENABLE_RES2 0x80fffffcul 145#define CONF1_ADDR_PORT 0x0cf8 146#define CONF1_DATA_PORT 0x0cfc 147 148 149#define CONF2_ENABLE_PORT 0x0cf8 150#define CONF2_FORWARD_PORT 0x0cfa 151 152
| 89static void 90pcibus_setup (void); 91 92static pcici_t 93pcibus_tag (u_char bus, u_char device, u_char func); 94 95static pcici_t 96pcibus_ftag (pcici_t tag, u_char func); 97 98static u_long 99pcibus_read (pcici_t tag, u_long reg); 100 101static void 102pcibus_write (pcici_t tag, u_long reg, u_long data); 103 104static int 105pcibus_ihandler_attach (int irq, void(*ihandler)(), int arg, unsigned* maskp); 106 107static int 108pcibus_ihandler_detach (int irq, void(*handler)()); 109 110static int 111pcibus_imask_include (int irq, unsigned* maskptr); 112 113static int 114pcibus_imask_exclude (int irq, unsigned* maskptr); 115 116struct pcibus i386pci = { 117 "pci", 118 pcibus_setup, 119 pcibus_tag, 120 pcibus_ftag, 121 pcibus_read, 122 pcibus_write, 123 ICU_LEN, 124 pcibus_ihandler_attach, 125 pcibus_ihandler_detach, 126 pcibus_imask_include, 127 pcibus_imask_exclude, 128}; 129 130/* 131** Announce structure to generic driver 132*/ 133 134DATA_SET (pcibus_set, i386pci); 135 136/*-------------------------------------------------------------------- 137** 138** Determine configuration mode 139** 140**-------------------------------------------------------------------- 141*/ 142 143 144#define CONF1_ENABLE 0x80000000ul 145#define CONF1_ENABLE_CHK1 0xF0000000ul 146#define CONF1_ENABLE_CHK2 0xfffffffful 147#define CONF1_ENABLE_RES2 0x80fffffcul 148#define CONF1_ADDR_PORT 0x0cf8 149#define CONF1_DATA_PORT 0x0cfc 150 151 152#define CONF2_ENABLE_PORT 0x0cf8 153#define CONF2_FORWARD_PORT 0x0cfa 154 155
|
| 156static int 157pcibus_check (void) 158{ 159 u_char device; 160 161 for (device = 0; device < pci_maxdevice; device++) { 162 if (pcibus_read (pcibus_tag (0,device,0), 0) != 0xfffffffful) 163 return 1; 164 } 165 return 0; 166} 167
|
153static void 154pcibus_setup (void) 155{ 156 u_long result, oldval; 157 158 /*--------------------------------------- 159 ** Configuration mode 1 ? 160 **--------------------------------------- 161 */ 162 163 oldval = inl (CONF1_ADDR_PORT); 164 outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 165 outb (CONF1_ADDR_PORT +3, 0); 166 result = inl (CONF1_ADDR_PORT); 167 outl (CONF1_ADDR_PORT, oldval); 168 169 if (result & CONF1_ENABLE) { 170 pci_mechanism = 1; 171 pci_maxdevice = 32;
| 168static void 169pcibus_setup (void) 170{ 171 u_long result, oldval; 172 173 /*--------------------------------------- 174 ** Configuration mode 1 ? 175 **--------------------------------------- 176 */ 177 178 oldval = inl (CONF1_ADDR_PORT); 179 outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 180 outb (CONF1_ADDR_PORT +3, 0); 181 result = inl (CONF1_ADDR_PORT); 182 outl (CONF1_ADDR_PORT, oldval); 183 184 if (result & CONF1_ENABLE) { 185 pci_mechanism = 1; 186 pci_maxdevice = 32;
|
172 if (pcibus_read (pcibus_tag (0,0,0), 0) != 0xfffffffful)
| 187 if (pcibus_check())
|
173 return; 174 }; 175 176 /*--------------------------------------- 177 ** Configuration mode 2 ? 178 **--------------------------------------- 179 */ 180 181 outb (CONF2_ENABLE_PORT, 0); 182 outb (CONF2_FORWARD_PORT, 0); 183 if (!inb (CONF2_ENABLE_PORT) && !inb (CONF2_FORWARD_PORT)) { 184 pci_mechanism = 2; 185 pci_maxdevice = 16;
| 188 return; 189 }; 190 191 /*--------------------------------------- 192 ** Configuration mode 2 ? 193 **--------------------------------------- 194 */ 195 196 outb (CONF2_ENABLE_PORT, 0); 197 outb (CONF2_FORWARD_PORT, 0); 198 if (!inb (CONF2_ENABLE_PORT) && !inb (CONF2_FORWARD_PORT)) { 199 pci_mechanism = 2; 200 pci_maxdevice = 16;
|
186 if (pcibus_read (pcibus_tag (0,0,0), 0) != 0xfffffffful)
| 201 if (pcibus_check())
|
187 return; 188 }; 189 190 191 /*----------------------------------------------------- 192 ** Well, is it Configuration mode 1, after all ? 193 **----------------------------------------------------- 194 */ 195 196 oldval = inl (CONF1_ADDR_PORT); 197 outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK2); 198 result = inl (CONF1_ADDR_PORT); 199 outl (CONF1_ADDR_PORT, oldval); 200 201 if (result == CONF1_ENABLE_RES2) { 202 pci_mechanism = 1; 203 pci_maxdevice = 32;
| 202 return; 203 }; 204 205 206 /*----------------------------------------------------- 207 ** Well, is it Configuration mode 1, after all ? 208 **----------------------------------------------------- 209 */ 210 211 oldval = inl (CONF1_ADDR_PORT); 212 outl (CONF1_ADDR_PORT, CONF1_ENABLE_CHK2); 213 result = inl (CONF1_ADDR_PORT); 214 outl (CONF1_ADDR_PORT, oldval); 215 216 if (result == CONF1_ENABLE_RES2) { 217 pci_mechanism = 1; 218 pci_maxdevice = 32;
|
204 if (pcibus_read (pcibus_tag (0,0,0), 0) != 0xfffffffful)
| 219 if (pcibus_check())
|
205 return; 206 } 207 if (result != 0xfffffffful) 208 printf ("pcibus_setup: " 209 "wrote 0x%08x, read back 0x%08x, expected 0x%08x\n", 210 CONF1_ENABLE_CHK2, result, CONF1_ENABLE_RES2); 211 212 /*--------------------------------------- 213 ** No PCI bus host bridge found 214 **--------------------------------------- 215 */ 216 217 pci_mechanism = 0; 218 pci_maxdevice = 0; 219} 220 221/*-------------------------------------------------------------------- 222** 223** Build a pcitag from bus, device and function number 224** 225**-------------------------------------------------------------------- 226*/ 227 228static pcici_t 229pcibus_tag (unsigned char bus, unsigned char device, unsigned char func) 230{ 231 pcici_t tag; 232 233 tag.cfg1 = 0; 234 if (device >= 32) return tag; 235 if (func >= 8) return tag; 236 237 switch (pci_mechanism) { 238 239 case 1: 240 tag.cfg1 = CONF1_ENABLE 241 | (((u_long) bus ) << 16ul) 242 | (((u_long) device) << 11ul) 243 | (((u_long) func ) << 8ul); 244 break; 245 case 2: 246 if (device >= 16) break; 247 tag.cfg2.port = 0xc000 | (device << 8ul); 248 tag.cfg2.enable = 0xf1 | (func << 1ul); 249 tag.cfg2.forward = bus; 250 break; 251 }; 252 return tag; 253} 254 255static pcici_t 256pcibus_ftag (pcici_t tag, u_char func) 257{ 258 switch (pci_mechanism) { 259 260 case 1: 261 tag.cfg1 &= ~0x700ul; 262 tag.cfg1 |= (((u_long) func) << 8ul); 263 break; 264 case 2: 265 tag.cfg2.enable = 0xf1 | (func << 1ul); 266 break; 267 }; 268 return tag; 269} 270 271/*-------------------------------------------------------------------- 272** 273** Read register from configuration space. 274** 275**-------------------------------------------------------------------- 276*/ 277 278static u_long 279pcibus_read (pcici_t tag, u_long reg) 280{ 281 u_long addr, data = 0; 282 283 if (!tag.cfg1) return (0xfffffffful); 284 285 switch (pci_mechanism) { 286 287 case 1: 288 addr = tag.cfg1 | (reg & 0xfc); 289#ifdef PCI_DEBUG 290 printf ("pci_conf_read(1): addr=%x ", addr); 291#endif 292 outl (CONF1_ADDR_PORT, addr); 293 data = inl (CONF1_DATA_PORT); 294 outl (CONF1_ADDR_PORT, 0 ); 295 break; 296 297 case 2: 298 addr = tag.cfg2.port | (reg & 0xfc); 299#ifdef PCI_DEBUG 300 printf ("pci_conf_read(2): addr=%x ", addr); 301#endif 302 outb (CONF2_ENABLE_PORT , tag.cfg2.enable ); 303 outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 304 305 data = inl ((u_short) addr); 306 307 outb (CONF2_ENABLE_PORT, 0); 308 outb (CONF2_FORWARD_PORT, 0); 309 break; 310 }; 311 312#ifdef PCI_DEBUG 313 printf ("data=%x\n", data); 314#endif 315 316 return (data); 317} 318 319/*-------------------------------------------------------------------- 320** 321** Write register into configuration space. 322** 323**-------------------------------------------------------------------- 324*/ 325 326static void 327pcibus_write (pcici_t tag, u_long reg, u_long data) 328{ 329 u_long addr; 330 331 if (!tag.cfg1) return; 332 333 switch (pci_mechanism) { 334 335 case 1: 336 addr = tag.cfg1 | (reg & 0xfc); 337#ifdef PCI_DEBUG 338 printf ("pci_conf_write(1): addr=%x data=%x\n", 339 addr, data); 340#endif 341 outl (CONF1_ADDR_PORT, addr); 342 outl (CONF1_DATA_PORT, data); 343 outl (CONF1_ADDR_PORT, 0 ); 344 break; 345 346 case 2: 347 addr = tag.cfg2.port | (reg & 0xfc); 348#ifdef PCI_DEBUG 349 printf ("pci_conf_write(2): addr=%x data=%x\n", 350 addr, data); 351#endif 352 outb (CONF2_ENABLE_PORT, tag.cfg2.enable); 353 outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 354 355 outl ((u_short) addr, data); 356 357 outb (CONF2_ENABLE_PORT, 0); 358 outb (CONF2_FORWARD_PORT, 0); 359 break; 360 }; 361} 362 363/*----------------------------------------------------------------------- 364** 365** Register an interupt handler for a pci device. 366** 367**----------------------------------------------------------------------- 368*/ 369 370static int 371pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr) 372{ 373 int result; 374 result = register_intr( 375 irq, /* isa irq */ 376 0, /* deviced?? */ 377 0, /* flags? */ 378 (inthand2_t*) func, /* handler */ 379 maskptr, /* mask pointer */ 380 arg); /* handler arg */ 381 382 if (result) { 383 printf ("@@@ pcibus_ihandler_attach: result=%d\n", result); 384 return (result); 385 }; 386 update_intr_masks(); 387 388 INTREN ((1ul<<irq)); 389 return (0); 390} 391 392static int 393pcibus_ihandler_detach (int irq, void(*func)()) 394{ 395 int result; 396 397 INTRDIS ((1ul<<irq)); 398 399 result = unregister_intr (irq, (inthand2_t*) func); 400 401 if (result) 402 printf ("@@@ pcibus_ihandler_detach: result=%d\n", result); 403 404 update_intr_masks(); 405 406 return (result); 407} 408 409static int 410pcibus_imask_include (int irq, unsigned* maskptr) 411{ 412 unsigned mask; 413 414 if (!maskptr) return (0); 415 416 mask = 1ul << irq; 417 418 if (*maskptr & mask) 419 return (-1); 420 421 INTRMASK (*maskptr, mask); 422 update_intr_masks(); 423 424 return (0); 425} 426 427static int 428pcibus_imask_exclude (int irq, unsigned* maskptr) 429{ 430 unsigned mask; 431 432 if (!maskptr) return (0); 433 434 mask = 1ul << irq; 435 436 if (! (*maskptr & mask)) 437 return (-1); 438 439 *maskptr &= ~mask; 440 update_intr_masks(); 441 442 return (0); 443}
| 220 return; 221 } 222 if (result != 0xfffffffful) 223 printf ("pcibus_setup: " 224 "wrote 0x%08x, read back 0x%08x, expected 0x%08x\n", 225 CONF1_ENABLE_CHK2, result, CONF1_ENABLE_RES2); 226 227 /*--------------------------------------- 228 ** No PCI bus host bridge found 229 **--------------------------------------- 230 */ 231 232 pci_mechanism = 0; 233 pci_maxdevice = 0; 234} 235 236/*-------------------------------------------------------------------- 237** 238** Build a pcitag from bus, device and function number 239** 240**-------------------------------------------------------------------- 241*/ 242 243static pcici_t 244pcibus_tag (unsigned char bus, unsigned char device, unsigned char func) 245{ 246 pcici_t tag; 247 248 tag.cfg1 = 0; 249 if (device >= 32) return tag; 250 if (func >= 8) return tag; 251 252 switch (pci_mechanism) { 253 254 case 1: 255 tag.cfg1 = CONF1_ENABLE 256 | (((u_long) bus ) << 16ul) 257 | (((u_long) device) << 11ul) 258 | (((u_long) func ) << 8ul); 259 break; 260 case 2: 261 if (device >= 16) break; 262 tag.cfg2.port = 0xc000 | (device << 8ul); 263 tag.cfg2.enable = 0xf1 | (func << 1ul); 264 tag.cfg2.forward = bus; 265 break; 266 }; 267 return tag; 268} 269 270static pcici_t 271pcibus_ftag (pcici_t tag, u_char func) 272{ 273 switch (pci_mechanism) { 274 275 case 1: 276 tag.cfg1 &= ~0x700ul; 277 tag.cfg1 |= (((u_long) func) << 8ul); 278 break; 279 case 2: 280 tag.cfg2.enable = 0xf1 | (func << 1ul); 281 break; 282 }; 283 return tag; 284} 285 286/*-------------------------------------------------------------------- 287** 288** Read register from configuration space. 289** 290**-------------------------------------------------------------------- 291*/ 292 293static u_long 294pcibus_read (pcici_t tag, u_long reg) 295{ 296 u_long addr, data = 0; 297 298 if (!tag.cfg1) return (0xfffffffful); 299 300 switch (pci_mechanism) { 301 302 case 1: 303 addr = tag.cfg1 | (reg & 0xfc); 304#ifdef PCI_DEBUG 305 printf ("pci_conf_read(1): addr=%x ", addr); 306#endif 307 outl (CONF1_ADDR_PORT, addr); 308 data = inl (CONF1_DATA_PORT); 309 outl (CONF1_ADDR_PORT, 0 ); 310 break; 311 312 case 2: 313 addr = tag.cfg2.port | (reg & 0xfc); 314#ifdef PCI_DEBUG 315 printf ("pci_conf_read(2): addr=%x ", addr); 316#endif 317 outb (CONF2_ENABLE_PORT , tag.cfg2.enable ); 318 outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 319 320 data = inl ((u_short) addr); 321 322 outb (CONF2_ENABLE_PORT, 0); 323 outb (CONF2_FORWARD_PORT, 0); 324 break; 325 }; 326 327#ifdef PCI_DEBUG 328 printf ("data=%x\n", data); 329#endif 330 331 return (data); 332} 333 334/*-------------------------------------------------------------------- 335** 336** Write register into configuration space. 337** 338**-------------------------------------------------------------------- 339*/ 340 341static void 342pcibus_write (pcici_t tag, u_long reg, u_long data) 343{ 344 u_long addr; 345 346 if (!tag.cfg1) return; 347 348 switch (pci_mechanism) { 349 350 case 1: 351 addr = tag.cfg1 | (reg & 0xfc); 352#ifdef PCI_DEBUG 353 printf ("pci_conf_write(1): addr=%x data=%x\n", 354 addr, data); 355#endif 356 outl (CONF1_ADDR_PORT, addr); 357 outl (CONF1_DATA_PORT, data); 358 outl (CONF1_ADDR_PORT, 0 ); 359 break; 360 361 case 2: 362 addr = tag.cfg2.port | (reg & 0xfc); 363#ifdef PCI_DEBUG 364 printf ("pci_conf_write(2): addr=%x data=%x\n", 365 addr, data); 366#endif 367 outb (CONF2_ENABLE_PORT, tag.cfg2.enable); 368 outb (CONF2_FORWARD_PORT, tag.cfg2.forward); 369 370 outl ((u_short) addr, data); 371 372 outb (CONF2_ENABLE_PORT, 0); 373 outb (CONF2_FORWARD_PORT, 0); 374 break; 375 }; 376} 377 378/*----------------------------------------------------------------------- 379** 380** Register an interupt handler for a pci device. 381** 382**----------------------------------------------------------------------- 383*/ 384 385static int 386pcibus_ihandler_attach (int irq, void(*func)(), int arg, unsigned * maskptr) 387{ 388 int result; 389 result = register_intr( 390 irq, /* isa irq */ 391 0, /* deviced?? */ 392 0, /* flags? */ 393 (inthand2_t*) func, /* handler */ 394 maskptr, /* mask pointer */ 395 arg); /* handler arg */ 396 397 if (result) { 398 printf ("@@@ pcibus_ihandler_attach: result=%d\n", result); 399 return (result); 400 }; 401 update_intr_masks(); 402 403 INTREN ((1ul<<irq)); 404 return (0); 405} 406 407static int 408pcibus_ihandler_detach (int irq, void(*func)()) 409{ 410 int result; 411 412 INTRDIS ((1ul<<irq)); 413 414 result = unregister_intr (irq, (inthand2_t*) func); 415 416 if (result) 417 printf ("@@@ pcibus_ihandler_detach: result=%d\n", result); 418 419 update_intr_masks(); 420 421 return (result); 422} 423 424static int 425pcibus_imask_include (int irq, unsigned* maskptr) 426{ 427 unsigned mask; 428 429 if (!maskptr) return (0); 430 431 mask = 1ul << irq; 432 433 if (*maskptr & mask) 434 return (-1); 435 436 INTRMASK (*maskptr, mask); 437 update_intr_masks(); 438 439 return (0); 440} 441 442static int 443pcibus_imask_exclude (int irq, unsigned* maskptr) 444{ 445 unsigned mask; 446 447 if (!maskptr) return (0); 448 449 mask = 1ul << irq; 450 451 if (! (*maskptr & mask)) 452 return (-1); 453 454 *maskptr &= ~mask; 455 update_intr_masks(); 456 457 return (0); 458}
|