xref: /freebsd/sys/dev/pci/pci.c (revision b7a1a0a5ff8895e6a5c9404d02357ac9e2eb8091)
1 /**************************************************************************
2 **
3 **  $Id: pci.c,v 1.8 1994/10/25 23:09:08 se Exp $
4 **
5 **  General subroutines for the PCI bus on 80*86 systems.
6 **  pci_configure ()
7 **
8 **  386bsd / FreeBSD
9 **
10 **-------------------------------------------------------------------------
11 **
12 ** Copyright (c) 1994 Wolfgang Stanglmeier.  All rights reserved.
13 **
14 ** Redistribution and use in source and binary forms, with or without
15 ** modification, are permitted provided that the following conditions
16 ** are met:
17 ** 1. Redistributions of source code must retain the above copyright
18 **    notice, this list of conditions and the following disclaimer.
19 ** 2. Redistributions in binary form must reproduce the above copyright
20 **    notice, this list of conditions and the following disclaimer in the
21 **    documentation and/or other materials provided with the distribution.
22 ** 3. The name of the author may not be used to endorse or promote products
23 **    derived from this software without specific prior written permission.
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 **
36 ***************************************************************************
37 */
38 
39 #include <pci.h>
40 #if NPCI > 0
41 
42 #ifndef __FreeBSD2__
43 #if __FreeBSD__ >= 2
44 #define	__FreeBSD2__
45 #endif
46 #endif
47 
48 /*========================================================
49 **
50 **	#includes  and  declarations
51 **
52 **========================================================
53 */
54 
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/malloc.h>
58 #include <sys/errno.h>
59 
60 #include <vm/vm.h>
61 #include <vm/vm_param.h>
62 
63 #include <i386/isa/isa.h>
64 #include <i386/isa/isa_device.h>
65 #include <i386/isa/icu.h>
66 #include <i386/pci/pcireg.h>
67 
68 #ifdef __FreeBSD2__
69 #include <sys/devconf.h>
70 
71 struct pci_devconf {
72 	struct kern_devconf pdc_kdc;
73 	struct pci_info     pdc_pi;
74 };
75 #endif
76 
77 /*
78 **	Function prototypes missing in system headers
79 */
80 
81 #ifndef __FreeBSD2__
82 extern	pmap_t pmap_kernel(void);
83 static	vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize);
84 
85 /*
86  * Type of the first (asm) part of an interrupt handler.
87  */
88 typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss));
89 
90 /*
91  * Usual type of the second (C) part of an interrupt handler.  Some bogus
92  * ones need the arg to be the interrupt frame (and not a copy of it, which
93  * is all that is possible in C).
94  */
95 typedef void inthand2_t __P((int unit));
96 
97 /*
98 **	XXX	@FreeBSD2@
99 **
100 **	Unfortunately, the mptr argument is _no_ pointer in 2.0 FreeBSD.
101 **	We would prefer a pointer because it enables us to install
102 **	new interrupt handlers at any time.
103 **	(This is just going to be changed ... <se> :)
104 **	In 2.0 FreeBSD later installed interrupt handlers may change
105 **	the xyz_imask, but this would not be recognized by handlers
106 **	which are installed before.
107 */
108 
109 static int
110 register_intr __P((int intr, int device_id, unsigned int flags,
111 		       inthand2_t *handler, unsigned int * mptr, int unit));
112 extern unsigned intr_mask[ICU_LEN];
113 
114 #endif /* !__FreeBSD2__ */
115 
116 /*========================================================
117 **
118 **	Autoconfiguration of pci devices.
119 **
120 **	This is reverse to the isa configuration.
121 **	(1) find a pci device.
122 **	(2) look for a driver.
123 **
124 **========================================================
125 */
126 
127 /*--------------------------------------------------------
128 **
129 **	The pci devices can be mapped to any address.
130 **	As default we start at the last gigabyte.
131 **
132 **--------------------------------------------------------
133 */
134 
135 #ifndef PCI_PMEM_START
136 #define PCI_PMEM_START 0xc0000000
137 #endif
138 
139 static	vm_offset_t pci_paddr = PCI_PMEM_START;
140 
141 /*--------------------------------------------------------
142 **
143 **	The pci device interrupt lines should have been
144 **	assigned by the bios. But if the bios failed to
145 **	to it, we set it.
146 **
147 **--------------------------------------------------------
148 */
149 
150 #ifndef PCI_IRQ
151 #define PCI_IRQ 0
152 #endif
153 
154 static	u_long      pci_irq   = PCI_IRQ;
155 
156 /*---------------------------------------------------------
157 **
158 **	pci_configure ()
159 **
160 **	Probe all devices on pci bus and attach them.
161 **
162 **	May be called more than once.
163 **	Any device is attached only once.
164 **	(Attached devices are remembered in pci_seen.)
165 **
166 **---------------------------------------------------------
167 */
168 
169 static void not_supported (pcici_t tag, u_long type);
170 
171 static unsigned long pci_seen[NPCI];
172 
173 static int pci_conf_count;
174 
175 #ifdef __FreeBSD2__
176 static int
177 pci_externalize (struct proc *, struct kern_devconf *, void *, size_t);
178 
179 static int
180 pci_internalize (struct proc *, struct kern_devconf *, void *, size_t);
181 
182 #endif /* __FreeBSD2__ */
183 
184 void pci_configure()
185 {
186 	u_char	device,last_device;
187 	u_short	bus;
188 	pcici_t	tag;
189 	pcidi_t type;
190 	u_long	data;
191 	int	unit;
192 	int	pci_mechanism;
193 	int	pciint;
194 	int	irq;
195 	char*	name=0;
196 	vm_offset_t old_addr=pci_paddr;
197 
198 	struct pci_driver *drp=0;
199 	struct pci_device *dvp;
200 
201 #ifdef __FreeBSD2__
202 	struct pci_devconf *pdcp;
203 #endif
204 
205 	/*
206 	**	check pci bus present
207 	*/
208 
209 	pci_mechanism = pci_conf_mode ();
210 	if (!pci_mechanism) return;
211 	last_device = pci_mechanism==1 ? 31 : 15;
212 
213 	/*
214 	**	hello world ..
215 	*/
216 
217 
218 	for (bus=0;bus<NPCI;bus++) {
219 #ifndef PCI_QUIET
220 	    printf ("pci%d: scanning device 0..%d, mechanism=%d.\n",
221 		bus, last_device, pci_mechanism);
222 #endif
223 	    for (device=0; device<=last_device; device ++) {
224 
225 		if (pci_seen[bus] & (1ul << device))
226 			continue;
227 
228 		tag = pcitag (bus, device, 0);
229 		type = pci_conf_read (tag, PCI_ID_REG);
230 
231 		if ((!type) || (type==0xfffffffful)) continue;
232 
233 		/*
234 		**	lookup device in ioconfiguration:
235 		*/
236 
237 		for (dvp = pci_devtab; dvp->pd_name; dvp++) {
238 			drp = dvp->pd_driver;
239 			if (!drp)
240 				continue;
241 			if ((name=(*drp->probe)(tag, type)))
242 				break;
243 		};
244 
245 		if (!dvp->pd_name) {
246 #ifndef PCI_QUIET
247 			if (pci_conf_count)
248 				continue;
249 			printf("pci%d:%d: ", bus, device);
250 			not_supported (tag, type);
251 #endif
252 			continue;
253 		};
254 
255 		pci_seen[bus] |= (1ul << device);
256 		/*
257 		**	Get and increment the unit.
258 		*/
259 
260 		unit = (*drp->count)++;
261 
262 		/*
263 		**	ignore device ?
264 		*/
265 
266 		if (!*name) continue;
267 
268 		/*
269 		**	Announce this device
270 		*/
271 
272 		printf ("%s%d <%s>", dvp->pd_name, unit, name);
273 
274 		/*
275 		**	Get the int pin number (pci interrupt number a-d)
276 		**	from the pci configuration space.
277 		*/
278 
279 		data = pci_conf_read (tag, PCI_INTERRUPT_REG);
280 		pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
281 
282 		if (pciint) {
283 
284 			printf (" int %c", 0x60+pciint);
285 
286 			/*
287 			**	If the interrupt line register is not set,
288 			**	set it now from PCI_IRQ.
289 			*/
290 
291 			if (!(PCI_INTERRUPT_LINE_EXTRACT(data))) {
292 
293 				irq = pci_irq & 0x0f;
294 				pci_irq >>= 4;
295 
296 				data = PCI_INTERRUPT_LINE_INSERT(data, irq);
297 				printf (" (config)");
298 				pci_conf_write (tag, PCI_INTERRUPT_REG, data);
299 			};
300 
301 			irq = PCI_INTERRUPT_LINE_EXTRACT(data);
302 
303 			/*
304 			**	If it's zero, the isa irq number is unknown,
305 			**	and we cannot bind the pci interrupt to isa.
306 			*/
307 
308 			if (irq)
309 				printf (" irq %d", irq);
310 			else
311 				printf (" not bound");
312 		};
313 
314 		/*
315 		**	enable memory access
316 		*/
317 
318 		data = (pci_conf_read (tag, PCI_COMMAND_STATUS_REG)
319 			& 0xffff) | PCI_COMMAND_MEM_ENABLE;
320 
321 		pci_conf_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data);
322 
323 		/*
324 		**	show pci slot.
325 		*/
326 
327 		printf (" on pci%d:%d\n", bus, device);
328 
329 #ifdef __FreeBSD2__
330 
331 		/*
332 		**	Allocate a devconf structure
333 		*/
334 
335 		pdcp = (struct pci_devconf *)
336                 	malloc (sizeof (struct pci_devconf),M_DEVBUF,M_WAITOK);
337 
338 		/*
339 		**	Fill in.
340 		**
341 		**	Sorry, this is not yet complete.
342 		**	We should, and eventually will, set the
343 		**	parent pointer to a pci bus devconf structure,
344 		**	and arrange to set the state field dynamically.
345 		**
346 		**	But I'll go to vacation today, and after all,
347 		**	wasn't there a new feature freeze on Oct 1.?
348 		*/
349 
350 		pdcp -> pdc_pi.pi_bus	 = bus;
351 		pdcp -> pdc_pi.pi_device = device;
352 
353 		pdcp -> pdc_kdc.kdc_name = dvp->pd_name;
354 		pdcp -> pdc_kdc.kdc_unit = unit;
355 
356 		pdcp -> pdc_kdc.kdc_md.mddc_devtype = MDDT_PCI;
357 
358 		pdcp -> pdc_kdc.kdc_externalize = pci_externalize;
359 		pdcp -> pdc_kdc.kdc_internalize = pci_internalize;
360 
361 		pdcp -> pdc_kdc.kdc_datalen     = PCI_EXTERNAL_LEN;
362 		pdcp -> pdc_kdc.kdc_parentdata  = &pdcp->pdc_pi;
363 		pdcp -> pdc_kdc.kdc_state       = DC_UNKNOWN;
364 		pdcp -> pdc_kdc.kdc_description = name;
365 
366 		/*
367 		**	And register this device
368 		*/
369 
370 		dev_attach (&pdcp->pdc_kdc);
371 
372 #endif /* __FreeBSD2__ */
373 
374 
375 		/*
376 		**	attach device
377 		**	may produce additional log messages,
378 		**	i.e. when installing subdevices.
379 		*/
380 
381 		(*drp->attach) (tag, unit);
382 	    };
383 	};
384 
385 #ifndef PCI_QUIET
386 	if (pci_paddr != old_addr)
387 		printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
388 			(u_long)PCI_PMEM_START, (u_long)pci_paddr);
389 #endif
390 	pci_conf_count++;
391 }
392 
393 /*-----------------------------------------------------------------------
394 **
395 **	Map device into port space.
396 **
397 **	PCI-Specification:  6.2.5.1: address maps
398 **
399 **-----------------------------------------------------------------------
400 */
401 
402 int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
403 {
404 	/*
405 	**	@MAPIO@ not yet implemented.
406 	*/
407 	printf ("pci_map_port failed: not yet implemented\n");
408 	return (0);
409 }
410 
411 /*-----------------------------------------------------------------------
412 **
413 **	Map device into virtual and physical space
414 **
415 **	PCI-Specification:  6.2.5.1: address maps
416 **
417 **-----------------------------------------------------------------------
418 */
419 
420 int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
421 {
422 	u_long data;
423 	vm_size_t vsize;
424 	vm_offset_t vaddr;
425 
426 	/*
427 	**	sanity check
428 	*/
429 
430         if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
431         	printf ("pci_map_mem failed: bad register=0x%x\n",
432                		(unsigned)reg);
433                 return (0);
434 	};
435 
436 	/*
437 	**	get size and type of memory
438 	**
439 	**	type is in the lowest four bits.
440 	**	If device requires 2^n bytes, the next
441 	**	n-4 bits are read as 0.
442 	*/
443 
444 	pci_conf_write (tag, reg, 0xfffffffful);
445 	data = pci_conf_read (tag, reg);
446 
447 	switch (data & 0x0f) {
448 
449 	case PCI_MAP_MEMORY_TYPE_32BIT:	/* 32 bit non cachable */
450 		break;
451 
452 	default:	/* unknown */
453                 printf ("pci_map_mem failed: bad memory type=0x%x\n",
454                		(unsigned) data);
455                 return (0);
456 	};
457 
458 	/*
459 	**	mask out the type,
460 	**	and round up to a page size
461 	*/
462 
463 	vsize = round_page (-(data &  PCI_MAP_MEMORY_ADDRESS_MASK));
464 
465 	if (!vsize) return (0);
466 
467 	/*
468 	**	align physical address to virtual size
469 	*/
470 
471 	if ((data = pci_paddr % vsize))
472 		pci_paddr += vsize - data;
473 
474 	vaddr = (vm_offset_t) pmap_mapdev (pci_paddr, vsize);
475 
476 
477 	if (!vaddr) return (0);
478 
479 #ifndef PCI_QUIET
480 	/*
481 	**	display values.
482 	*/
483 
484 	printf ("\treg%d: virtual=0x%lx physical=0x%lx\n",
485 		(unsigned) reg, (u_long)vaddr, (u_long)pci_paddr);
486 #endif
487 
488 	/*
489 	**	return them to the driver
490 	*/
491 
492 	*va = vaddr;
493 	*pa = pci_paddr;
494 
495 	/*
496 	**	set device address
497 	*/
498 
499 	pci_conf_write (tag, reg, pci_paddr);
500 
501 	/*
502 	**	and don't forget to increment pci_paddr
503 	*/
504 
505 	pci_paddr += vsize;
506 
507 	return (1);
508 }
509 
510 /*------------------------------------------------------------
511 **
512 **	Interface functions for the devconf module.
513 **
514 **------------------------------------------------------------
515 */
516 
517 static int
518 pci_externalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t l)
519 {
520 	struct pci_externalize_buffer buffer;
521 	struct pci_info * pip = kdcp->kdc_parentdata;
522         pcici_t tag;
523 	int	i;
524 
525 	if (l < sizeof buffer) {
526                 return ENOMEM;
527 	};
528 
529 	tag = pcitag (pip->pi_bus, pip->pi_device, 0);
530 
531 	buffer.peb_pci_info	= *pip;
532 
533 	for (i=0; i<PCI_EXT_CONF_LEN; i++) {
534 		buffer.peb_config[i] = pci_conf_read (tag, i*4);
535 	};
536 
537         return copyout(&buffer, u, sizeof buffer);
538 }
539 
540 
541 static int
542 pci_internalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t s)
543 {
544         return EOPNOTSUPP;
545 }
546 
547 /*-----------------------------------------------------------------------
548 **
549 **	Map pci interrupts to isa interrupts.
550 **
551 **-----------------------------------------------------------------------
552 */
553 
554 static	unsigned int	pci_int_mask [16];
555 
556 int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
557 {
558 	int irq;
559 	unsigned mask;
560 
561 	irq = PCI_INTERRUPT_LINE_EXTRACT(
562 		pci_conf_read (tag, PCI_INTERRUPT_REG));
563 
564 	if (irq >= 16 || irq <= 0) {
565 		printf ("pci_map_int failed: no int line set.\n");
566 		return (0);
567 	}
568 
569 	mask = 1ul << irq;
570 
571 	if (!maskptr)
572 		maskptr = &pci_int_mask[irq];
573 
574 	INTRMASK (*maskptr, mask);
575 
576 	register_intr(
577 		irq,		/* isa irq	*/
578 		0,		/* deviced??	*/
579 		0,		/* flags?	*/
580 		(inthand2_t*) func, /* handler	*/
581 		maskptr,	/* mask pointer	*/
582 		(int) arg);	/* handler arg	*/
583 
584 #ifdef __FreeBSD2__
585 	/*
586 	**	XXX See comment at beginning of file.
587 	**
588 	**	Have to update all the interrupt masks ... Grrrrr!!!
589 	*/
590 	{
591 		unsigned * mp = &intr_mask[0];
592 		/*
593 		**	update the isa interrupt masks.
594 		*/
595 		for (mp=&intr_mask[0]; mp<&intr_mask[ICU_LEN]; mp++)
596 			if (*mp & *maskptr)
597 				*mp |= mask;
598 		/*
599 		**	update the pci interrupt masks.
600 		*/
601 		for (mp=&pci_int_mask[0]; mp<&pci_int_mask[16]; mp++)
602 			if (*mp & *maskptr)
603 				*mp |= mask;
604 	};
605 #endif
606 
607 	INTREN (mask);
608 
609 	return (1);
610 }
611 
612 /*-----------------------------------------------------------
613 **
614 **	Display of unknown devices.
615 **
616 **-----------------------------------------------------------
617 */
618 struct vt {
619 	u_short	ident;
620 	char*	name;
621 };
622 
623 static struct vt VendorTable[] = {
624 	{0x1002, "ATI TECHNOLOGIES INC"},
625 	{0x1011, "DIGITAL EQUIPMENT CORPORATION"},
626 	{0x101A, "NCR"},
627 	{0x102B, "MATROX"},
628 	{0x1045, "OPTI"},
629 	{0x5333, "S3 INC."},
630 	{0x8086, "INTEL CORPORATION"},
631 	{0,0}
632 };
633 
634 static const char *const majclasses[] = {
635 	"old", "storage", "network", "display",
636 	"multimedia", "memory", "bridge"
637 };
638 
639 void not_supported (pcici_t tag, u_long type)
640 {
641 	u_char	reg;
642 	u_long	data;
643 	struct vt * vp;
644 
645 	/*
646 	**	lookup the names.
647 	*/
648 
649 	for (vp=VendorTable; vp->ident; vp++)
650 		if (vp->ident == (type & 0xffff))
651 			break;
652 
653 	/*
654 	**	and display them.
655 	*/
656 
657 	if (vp->ident) printf (vp->name);
658 		else   printf ("vendor=0x%lx", type & 0xffff);
659 
660 	printf (", device=0x%lx", type >> 16);
661 
662 	data = (pci_conf_read(tag, PCI_CLASS_REG) >> 24) & 0xff;
663 	if (data < sizeof(majclasses) / sizeof(majclasses[0]))
664 		printf(", class=%s", majclasses[data]);
665 
666 	printf (" [not supported]\n");
667 
668 	for (reg=PCI_MAP_REG_START; reg<PCI_MAP_REG_END; reg+=4) {
669 		data = pci_conf_read (tag, reg);
670 		if (!data) continue;
671 		switch (data&7) {
672 
673 		case 1:
674 		case 5:
675 			printf ("	map(%x): io(%lx)\n",
676 				reg, data & ~3);
677 			break;
678 		case 0:
679 			printf ("	map(%x): mem32(%lx)\n",
680 				reg, data & ~7);
681 			break;
682 		case 2:
683 			printf ("	map(%x): mem20(%lx)\n",
684 				reg, data & ~7);
685 			break;
686 		case 4:
687 			printf ("	map(%x): mem64(%lx)\n",
688 				reg, data & ~7);
689 			break;
690 		}
691 	}
692 }
693 
694 #ifndef __FreeBSD2__
695 /*-----------------------------------------------------------
696 **
697 **	Mapping of physical to virtual memory
698 **
699 **-----------------------------------------------------------
700 */
701 
702 extern vm_map_t kernel_map;
703 
704 static	vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize)
705 {
706 	vm_offset_t	vaddr,value;
707 	u_long		result;
708 
709 	vaddr  = vm_map_min (kernel_map);
710 
711 	result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0,
712 				&vaddr, vsize, TRUE);
713 
714 	if (result != KERN_SUCCESS) {
715 		printf (" vm_map_find failed(%d)\n", result);
716 		return (0);
717 	};
718 
719 	/*
720 	**	map physical
721 	*/
722 
723 	value = vaddr;
724 	while (vsize >= NBPG) {
725 		pmap_enter (pmap_kernel(), vaddr, paddr,
726 				VM_PROT_READ|VM_PROT_WRITE, TRUE);
727 		vaddr += NBPG;
728 		paddr += NBPG;
729 		vsize -= NBPG;
730 	};
731 	return (value);
732 }
733 
734 /*------------------------------------------------------------
735 **
736 **	Emulate the register_intr() function of FreeBSD 2.0
737 **
738 **	requires a patch:
739 **	FreeBSD 2.0:	"/sys/i386/isa/vector.s"
740 **	386bsd0.1:	"/sys/i386/isa/icu.s"
741 **	386bsd1.0:	Please ask Jesus Monroy Jr.
742 **
743 **------------------------------------------------------------
744 */
745 
746 #include <machine/segments.h>
747 
748 int		pci_int_unit [16];
749 inthand2_t*    (pci_int_hdlr [16]);
750 unsigned int *	pci_int_mptr [16];
751 unsigned int	pci_int_count[16];
752 
753 extern void
754 	Vpci3(), Vpci4(), Vpci5(), Vpci6(), Vpci7(), Vpci8(), Vpci9(),
755 	Vpci10(), Vpci11(), Vpci12(), Vpci13(), Vpci14(), Vpci15();
756 
757 static inthand_t* pci_int_glue[16] = {
758 	0, 0, 0, Vpci3, Vpci4, Vpci5, Vpci6, Vpci7, Vpci8,
759 	Vpci9, Vpci10, Vpci11, Vpci12, Vpci13, Vpci14, Vpci15 };
760 
761 static int
762 register_intr __P((int intr, int device_id, unsigned int flags,
763 		       inthand2_t *handler, unsigned int* mptr, int unit))
764 {
765 	if (intr >= 16 || intr <= 2)
766 		return (EINVAL);
767 	if (pci_int_hdlr [intr])
768 		return (EBUSY);
769 
770 	pci_int_hdlr [intr] = handler;
771 	pci_int_unit [intr] = unit;
772 	pci_int_mptr [intr] = mptr;
773 
774 	setidt(NRSVIDT + intr, pci_int_glue[intr], SDT_SYS386IGT, SEL_KPL);
775 	return (0);
776 }
777 #endif /* __FreeBSD2__ */
778 #endif /* NPCI */
779