pci.c revision 6630
1/**************************************************************************
2**
3**  $Id: pci.c,v 1.14 1995/02/14 23:33:38 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#define PCI_PATCHLEVEL  "pl2 95/02/21"
40
41#include <pci.h>
42#if NPCI > 0
43
44#ifndef __FreeBSD2__
45#if __FreeBSD__ >= 2
46#define	__FreeBSD2__
47#endif
48#endif
49
50/*========================================================
51**
52**	#includes  and  declarations
53**
54**========================================================
55*/
56
57#include <sys/param.h>
58#include <sys/systm.h>
59#include <sys/malloc.h>
60#include <sys/errno.h>
61#include <sys/kernel.h>
62
63#include <vm/vm.h>
64#include <vm/vm_param.h>
65
66#include <pci/pcivar.h>
67#include <pci/pcireg.h>
68#include <pci/pcibus.h>
69
70#include <machine/pmap.h>
71#ifdef __FreeBSD2__
72#include <sys/devconf.h>
73
74struct pci_devconf {
75	struct kern_devconf pdc_kdc;
76	struct pci_info     pdc_pi;
77};
78
79static int
80pci_externalize (struct proc *, struct kern_devconf *, void *, size_t);
81
82static int
83pci_internalize (struct proc *, struct kern_devconf *, void *, size_t);
84#else /* __FreeBSD2__ */
85
86/*
87**	Function prototypes missing in system headers
88*/
89
90extern	pmap_t pmap_kernel(void);
91static	vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize);
92#endif /* __FreeBSD2__ */
93
94
95/*========================================================
96**
97**	Autoconfiguration of pci devices.
98**
99**	This is reverse to the isa configuration.
100**	(1) find a pci device.
101**	(2) look for a driver.
102**
103**========================================================
104*/
105
106/*--------------------------------------------------------
107**
108**	The pci devices can be mapped to any address.
109**	This is a list of possible starting addresses.
110**	It can be prepended by a config option.
111**
112**--------------------------------------------------------
113*/
114
115static	u_long	pci_stable[] = {
116#ifdef PCI_PMEM_START
117	(PCI_PMEM_START),
118#endif
119	0xf1000000,
120	0x53900000,
121	0xc0000000,
122	0x81000000,
123	0x0f000000,
124};
125
126static	vm_offset_t pci_paddr = 0;
127static	vm_offset_t pci_pold  = 0;
128static	vm_offset_t pci_pidx  = 0;
129
130
131/*--------------------------------------------------------
132**
133**	The pci ports can be mapped to any address.
134**	As default we start at 0x400
135**
136**--------------------------------------------------------
137*/
138
139#ifndef PCI_PORT_START
140#define PCI_PORT_START 0xbc00
141#endif
142
143static	u_short pci_ioaddr = PCI_PORT_START;
144
145/*--------------------------------------------------------
146**
147**	The pci device interrupt lines should have been
148**	assigned by the bios. But if the bios failed to
149**	to it, we set it.
150**
151**--------------------------------------------------------
152*/
153
154#ifndef PCI_IRQ
155#define PCI_IRQ 0
156#endif
157
158static	u_long      pci_irq   = PCI_IRQ;
159
160/*---------------------------------------------------------
161**
162**	pci_configure ()
163**
164**	Probe all devices on pci bus and attach them.
165**
166**	May be called more than once.
167**	Any device is attached only once.
168**	(Attached devices are remembered in pci_seen.)
169**
170**---------------------------------------------------------
171*/
172
173static void not_supported (pcici_t tag, u_long type);
174
175static unsigned long pci_seen[NPCI];
176
177static int pci_conf_count;
178
179void pci_configure()
180{
181	u_char	device,last_device;
182	u_short	bus;
183	pcici_t	tag;
184	pcidi_t type;
185	u_long	data;
186	int	unit;
187	int	pci_mechanism;
188	int	pciint;
189	int	irq;
190	char*	name=0;
191	u_short	old_ioaddr=pci_ioaddr;
192
193	int	dvi;
194	struct pci_device *dvp=0;
195
196#ifdef __FreeBSD2__
197	struct pci_devconf *pdcp;
198#endif
199
200	/*
201	**	first check pci bus driver available
202	*/
203
204	if (pcibus_set.ls_length <= 0)
205		return;
206
207#define pcibus (*((struct pcibus*) pcibus_set.ls_items[0]))
208	/*
209	**	check pci bus present
210	*/
211
212	pci_mechanism = pcibus.pb_mode ();
213	if (!pci_mechanism) return;
214	last_device = pci_mechanism==1 ? 31 : 15;
215
216	/*
217	**	hello world ..
218	*/
219
220	pci_pold=pci_paddr;
221	for (bus=0;bus<NPCI;bus++) {
222#ifndef PCI_QUIET
223	    printf ("%s%d: scanning device 0..%d, mechanism=%d.\n",
224		pcibus.pb_name, bus, last_device, pci_mechanism);
225#endif
226	    for (device=0; device<=last_device; device ++) {
227
228		if (pci_seen[bus] & (1ul << device))
229			continue;
230
231		tag  = pcibus.pb_tag (bus, device, 0);
232		type = pcibus.pb_read (tag, PCI_ID_REG);
233
234		if ((!type) || (type==0xfffffffful)) continue;
235
236		/*
237		**	lookup device in ioconfiguration:
238		*/
239
240        	for (dvi=0; dvi<pcidevice_set.ls_length; dvi++) {
241			dvp = (struct pci_device*) pcidevice_set.ls_items[dvi];
242			if ((name=(*dvp->pd_probe)(tag, type)))
243				break;
244			dvp = NULL;
245		};
246
247		if (dvp==NULL) {
248#ifndef PCI_QUIET
249			if (pci_conf_count)
250				continue;
251			printf("%s%d:%d: ", pcibus.pb_name, bus, device);
252			not_supported (tag, type);
253#endif
254			continue;
255		};
256
257		pci_seen[bus] |= (1ul << device);
258		/*
259		**	Get and increment the unit.
260		*/
261
262		unit = (*dvp->pd_count)++;
263
264		/*
265		**	ignore device ?
266		*/
267
268		if (!*name) continue;
269
270		/*
271		**	Announce this device
272		*/
273
274		printf ("%s%d <%s>", dvp->pd_name, unit, name);
275
276		/*
277		**	Get the int pin number (pci interrupt number a-d)
278		**	from the pci configuration space.
279		*/
280
281		data = pcibus.pb_read (tag, PCI_INTERRUPT_REG);
282		pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
283
284		if (pciint) {
285
286			printf (" int %c", 0x60+pciint);
287
288			/*
289			**	If the interrupt line register is not set,
290			**	set it now from PCI_IRQ.
291			*/
292
293			if (!(PCI_INTERRUPT_LINE_EXTRACT(data))) {
294
295				irq = pci_irq & 0x0f;
296				pci_irq >>= 4;
297
298				data = PCI_INTERRUPT_LINE_INSERT(data, irq);
299				printf (" (config)");
300				pcibus.pb_write (tag, PCI_INTERRUPT_REG, data);
301			};
302
303			irq = PCI_INTERRUPT_LINE_EXTRACT(data);
304
305			/*
306			**	If it's zero, the isa irq number is unknown,
307			**	and we cannot bind the pci interrupt to isa.
308			*/
309
310			if (irq)
311				printf (" irq %d", irq);
312			else
313				printf (" not bound");
314		};
315
316		/*
317		**	enable memory access
318		*/
319
320		data = (pcibus.pb_read (tag, PCI_COMMAND_STATUS_REG)
321			& 0xffff) | PCI_COMMAND_MEM_ENABLE;
322
323		pcibus.pb_write (tag, (u_char) PCI_COMMAND_STATUS_REG, data);
324
325		/*
326		**	show pci slot.
327		*/
328
329		printf (" on pci%d:%d\n", bus, device);
330
331#ifdef __FreeBSD2__
332
333		/*
334		**	Allocate a devconf structure
335		*/
336
337		pdcp = (struct pci_devconf *)
338			malloc (sizeof (struct pci_devconf),M_DEVBUF,M_WAITOK);
339
340		/*
341		**	Fill in.
342		**
343		**	Sorry, this is not yet complete.
344		**	We should, and eventually will, set the
345		**	parent pointer to a pci bus devconf structure,
346		**	and arrange to set the state field dynamically.
347		**
348		**	But I'll go to vacation today, and after all,
349		**	wasn't there a new feature freeze on Oct 1.?
350		*/
351
352		pdcp -> pdc_pi.pi_bus	 = bus;
353		pdcp -> pdc_pi.pi_device = device;
354
355		pdcp -> pdc_kdc.kdc_name = dvp->pd_name;
356		pdcp -> pdc_kdc.kdc_unit = unit;
357
358		pdcp -> pdc_kdc.kdc_md.mddc_devtype = MDDT_PCI;
359
360		pdcp -> pdc_kdc.kdc_externalize = pci_externalize;
361		pdcp -> pdc_kdc.kdc_internalize = pci_internalize;
362
363		pdcp -> pdc_kdc.kdc_datalen     = PCI_EXTERNAL_LEN;
364		pdcp -> pdc_kdc.kdc_parentdata  = &pdcp->pdc_pi;
365		pdcp -> pdc_kdc.kdc_state       = DC_UNKNOWN;
366		pdcp -> pdc_kdc.kdc_description = name;
367
368		/*
369		**	And register this device
370		*/
371
372		dev_attach (&pdcp->pdc_kdc);
373
374#endif /* __FreeBSD2__ */
375
376
377		/*
378		**	attach device
379		**	may produce additional log messages,
380		**	i.e. when installing subdevices.
381		*/
382
383		(*dvp->pd_attach) (tag, unit);
384	    };
385	};
386
387#ifndef PCI_QUIET
388	if (pci_paddr != pci_pold)
389		printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
390			(u_long)pci_pold, (u_long)pci_paddr);
391	if (pci_ioaddr != old_ioaddr)
392		printf ("pci devices use ioports from 0x%x to 0x%x\n",
393			(unsigned)PCI_PORT_START, (unsigned)pci_ioaddr);
394#endif
395	pci_conf_count++;
396}
397
398/*-----------------------------------------------------------------
399**
400**	The following functions are provided for the device driver
401**	to read/write the configuration space.
402**
403**	pci_conf_read():
404**		Read a long word from the pci configuration space.
405**		Requires a tag (from pcitag) and the register
406**		number (should be a long word alligned one).
407**
408**	pci_conf_write():
409**		Writes a long word to the pci configuration space.
410**		Requires a tag (from pcitag), the register number
411**		(should be a long word alligned one), and a value.
412**
413**-----------------------------------------------------------------
414*/
415
416u_long
417pci_conf_read  (pcici_t tag, u_long reg)
418{
419	return (pcibus.pb_read (tag, reg));
420}
421
422void
423pci_conf_write (pcici_t tag, u_long reg, u_long data)
424{
425	pcibus.pb_write (tag, reg, data);
426}
427
428/*-----------------------------------------------------------------------
429**
430**	Map device into port space.
431**
432**	PCI-Specification:  6.2.5.1: address maps
433**
434**-----------------------------------------------------------------------
435*/
436
437int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
438{
439	u_long	data,oldmap;
440	u_short	size, ioaddr;
441
442	/*
443	**	sanity check
444	*/
445
446	if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
447		printf ("pci_map_port failed: bad register=0x%x\n",
448	       		(unsigned)reg);
449		return (0);
450	};
451
452	/*
453	**	get size and type of port
454	**
455	**	type is in the lowest two bits.
456	**	If device requires 2^n bytes, the next
457	**	n-2 bits are hardwired as 0.
458	*/
459
460#ifdef PCI_REMAP
461	oldmap = 0;
462#else
463	oldmap = pcibus.pb_read (tag, reg) & 0xfffffffc;
464	if (oldmap==0xfffffffc) oldmap=0;
465#endif
466	pcibus.pb_write (tag, reg, 0xfffffffful);
467	data = pcibus.pb_read (tag, reg);
468
469	switch (data & 0x03) {
470
471	case PCI_MAP_IO:
472		break;
473
474	default:	/* unknown */
475		printf ("pci_map_port failed: bad port type=0x%x\n",
476	       		(unsigned) data);
477		return (0);
478	};
479
480	/*
481	**	get the size
482	*/
483
484	size = -(data &  PCI_MAP_IO_ADDRESS_MASK);
485
486	if (!size) return (0);
487
488	/*
489	**	align physical address to virtual size,
490	**	set ioaddr,
491	**	and don't forget to increment pci_ioaddr
492	*/
493
494	if (oldmap) {
495		ioaddr = oldmap;
496	} else {
497		if ((data = pci_ioaddr % size))
498			pci_ioaddr += size - data;
499		ioaddr = pci_ioaddr;
500		pci_ioaddr += size;
501	};
502
503#ifndef PCI_QUIET
504	/*
505	**	display values.
506	*/
507
508	printf ("\treg%d: ioaddr=0x%x size=0x%x\n",
509		(unsigned) reg, (unsigned) ioaddr, (unsigned) size);
510#endif
511
512	/*
513	**	set device address
514	*/
515
516	pcibus.pb_write (tag, reg, (u_long) ioaddr);
517
518	/*
519	**	return them to the driver
520	*/
521
522	*pa = pci_ioaddr;
523
524	return (1);
525}
526
527/*-----------------------------------------------------------------------
528**
529**	Map device into virtual and physical space
530**
531**	PCI-Specification:  6.2.5.1: address maps
532**
533**-----------------------------------------------------------------------
534*/
535
536int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
537{
538	u_long data,oldmap,paddr;
539	vm_size_t vsize;
540	vm_offset_t vaddr;
541	int i;
542
543	/*
544	**	sanity check
545	*/
546
547	if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
548		printf ("pci_map_mem failed: bad register=0x%x\n",
549	       		(unsigned)reg);
550		return (0);
551	};
552
553	/*
554	**	save old mapping, get size and type of memory
555	**
556	**	type is in the lowest four bits.
557	**	If device requires 2^n bytes, the next
558	**	n-4 bits are read as 0.
559	*/
560
561#ifdef PCI_REMAP
562	oldmap = 0;
563#else
564	oldmap = pcibus.pb_read (tag, reg) & 0xfffffff0;
565	if (oldmap==0xfffffff0) oldmap = 0;
566#endif
567	pcibus.pb_write (tag, reg, 0xfffffffful);
568	data = pcibus.pb_read (tag, reg);
569
570	switch (data & 0x0f) {
571
572	case PCI_MAP_MEMORY_TYPE_32BIT:	/* 32 bit non cachable */
573		break;
574
575	default:	/* unknown */
576		printf ("pci_map_mem failed: bad memory type=0x%x\n",
577	       		(unsigned) data);
578		return (0);
579	};
580
581	/*
582	**	mask out the type,
583	**	and round up to a page size
584	*/
585
586	vsize = round_page (-(data &  PCI_MAP_MEMORY_ADDRESS_MASK));
587
588	if (!vsize) return (0);
589
590	if (oldmap) {
591		paddr = oldmap;
592		goto domap;
593	};
594
595next_try:
596	if (!pci_paddr) {
597		/*
598		**	Get a starting address.
599		*/
600		if (pci_pidx >= sizeof(pci_stable)/sizeof(u_long)) {
601			printf ("pci_map_mem: out of start addresses.\n");
602			return (0);
603		};
604
605		pci_paddr = pci_stable[pci_pidx++];
606		pci_pold  = 0;
607
608		if (pci_pidx>1)
609			printf ("\t(retry at 0x%x)\n",
610				(unsigned) pci_paddr);
611	};
612	/*
613	**	align physical address to virtual size
614	*/
615
616	if ((data = pci_paddr % vsize))
617		pci_paddr += vsize - data;
618
619	if (!pci_pold)
620		pci_pold = pci_paddr;
621
622	/*
623	**	set physical mapping address,
624	**	and reserve physical address range
625	*/
626
627	paddr     = pci_paddr;
628	pci_paddr += vsize;
629
630domap:
631	vaddr = (vm_offset_t) pmap_mapdev (paddr, vsize);
632
633	if (!vaddr) return (0);
634
635#ifndef PCI_QUIET
636	/*
637	**	display values.
638	*/
639
640	printf ("\treg%d: virtual=0x%lx physical=0x%lx\n",
641		(unsigned) reg, (u_long)vaddr, (u_long)paddr);
642#endif
643
644	/*
645	**	probe for already mapped device.
646	*/
647
648	if (!oldmap) for (i=0; i<vsize; i+=4) {
649		u_long* addr = (u_long*) (vaddr+i);
650		data = *addr;
651		if (data != 0xffffffff) {
652			printf ("\t(possible address conflict: "
653				"at 0x%x read: 0x%x)\n",
654				(unsigned) paddr+i, (unsigned) data);
655			pci_paddr = 0;
656			goto next_try;
657		};
658	};
659
660	/*
661	**	Set device address
662	*/
663
664	pcibus.pb_write (tag, reg, paddr);
665
666	/*
667	**	Check if correctly mapped.
668	**
669	**	W A R N I N G
670	**
671	**	This code assumes that the device will NOT return
672	**	only ones (0xffffffff) from all offsets.
673	*/
674
675	for (i=0; i<vsize; i+=4) {
676		u_long* addr = (u_long*) (vaddr+i);
677		data = *addr;
678		if (data != 0xffffffff)
679			break;
680	};
681
682	if (data==0xffffffff) {
683		printf ("\t(possible mapping problem: "
684			"at 0x%x read 0xffffffff)\n",
685			(unsigned) paddr);
686		pci_paddr = 0;
687		goto next_try;
688	};
689
690	/*
691	**	Return addresses to the driver
692	*/
693
694	*va = vaddr;
695	*pa = paddr;
696
697	return (1);
698}
699
700/*------------------------------------------------------------
701**
702**	Interface functions for the devconf module.
703**
704**------------------------------------------------------------
705*/
706
707static int
708pci_externalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t l)
709{
710	struct pci_externalize_buffer buffer;
711	struct pci_info * pip = kdcp->kdc_parentdata;
712	pcici_t tag;
713	int	i;
714
715	if (l < sizeof buffer) {
716		return ENOMEM;
717	};
718
719	tag = pcibus.pb_tag (pip->pi_bus, pip->pi_device, 0);
720
721	buffer.peb_pci_info	= *pip;
722
723	for (i=0; i<PCI_EXT_CONF_LEN; i++) {
724		buffer.peb_config[i] = pcibus.pb_read (tag, i*4);
725	};
726
727	return copyout(&buffer, u, sizeof buffer);
728}
729
730
731static int
732pci_internalize (struct proc *p, struct kern_devconf *kdcp, void *u, size_t s)
733{
734	return EOPNOTSUPP;
735}
736
737/*-----------------------------------------------------------------------
738**
739**	Map pci interrupts to isa interrupts.
740**
741**-----------------------------------------------------------------------
742*/
743
744int pci_map_int (pcici_t tag, int(*func)(), void* arg, unsigned* maskptr)
745{
746	int irq, result;
747
748	irq = PCI_INTERRUPT_LINE_EXTRACT(
749		pcibus.pb_read (tag, PCI_INTERRUPT_REG));
750
751	if (irq >= 16 || irq <= 0) {
752		printf ("pci_map_int failed: no int line set.\n");
753		return (0);
754	}
755
756	result = pcibus.pb_regint (tag, func, arg, maskptr);
757
758	if (!result) {
759		printf ("pci_map_int failed.\n");
760		return (0);
761	};
762
763	return (1);
764}
765
766/*-----------------------------------------------------------
767**
768**	Display of unknown devices.
769**
770**-----------------------------------------------------------
771*/
772struct vt {
773	u_short	ident;
774	char*	name;
775};
776
777static struct vt VendorTable[] = {
778	{0x1002, "ATI TECHNOLOGIES INC"},
779	{0x1011, "DIGITAL EQUIPMENT CORPORATION"},
780	{0x101A, "NCR"},
781	{0x102B, "MATROX"},
782	{0x1045, "OPTI"},
783	{0x5333, "S3 INC."},
784	{0x8086, "INTEL CORPORATION"},
785	{0,0}
786};
787
788static const char *const majclasses[] = {
789	"old", "storage", "network", "display",
790	"multimedia", "memory", "bridge"
791};
792
793void not_supported (pcici_t tag, u_long type)
794{
795	u_char	reg;
796	u_long	data;
797	struct vt * vp;
798
799	/*
800	**	lookup the names.
801	*/
802
803	for (vp=VendorTable; vp->ident; vp++)
804		if (vp->ident == (type & 0xffff))
805			break;
806
807	/*
808	**	and display them.
809	*/
810
811	if (vp->ident) printf (vp->name);
812		else   printf ("vendor=0x%lx", type & 0xffff);
813
814	printf (", device=0x%lx", type >> 16);
815
816	data = (pcibus.pb_read(tag, PCI_CLASS_REG) >> 24) & 0xff;
817	if (data < sizeof(majclasses) / sizeof(majclasses[0]))
818		printf(", class=%s", majclasses[data]);
819
820	printf (" [not supported]\n");
821
822	for (reg=PCI_MAP_REG_START; reg<PCI_MAP_REG_END; reg+=4) {
823		data = pcibus.pb_read (tag, reg);
824		if (!data) continue;
825		switch (data&7) {
826
827		case 1:
828		case 5:
829			printf ("	map(%x): io(%lx)\n",
830				reg, data & ~3);
831			break;
832		case 0:
833			printf ("	map(%x): mem32(%lx)\n",
834				reg, data & ~7);
835			break;
836		case 2:
837			printf ("	map(%x): mem20(%lx)\n",
838				reg, data & ~7);
839			break;
840		case 4:
841			printf ("	map(%x): mem64(%lx)\n",
842				reg, data & ~7);
843			break;
844		}
845	}
846}
847
848#ifndef __FreeBSD2__
849/*-----------------------------------------------------------
850**
851**	Mapping of physical to virtual memory
852**
853**-----------------------------------------------------------
854*/
855
856extern vm_map_t kernel_map;
857
858static	vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize)
859{
860	vm_offset_t	vaddr,value;
861	u_long		result;
862
863	vaddr  = vm_map_min (kernel_map);
864
865	result = vm_map_find (kernel_map, (void*)0, (vm_offset_t) 0,
866				&vaddr, vsize, TRUE);
867
868	if (result != KERN_SUCCESS) {
869		printf (" vm_map_find failed(%d)\n", result);
870		return (0);
871	};
872
873	/*
874	**	map physical
875	*/
876
877	value = vaddr;
878	while (vsize >= NBPG) {
879		pmap_enter (pmap_kernel(), vaddr, paddr,
880				VM_PROT_READ|VM_PROT_WRITE, TRUE);
881		vaddr += NBPG;
882		paddr += NBPG;
883		vsize -= NBPG;
884	};
885	return (value);
886}
887
888/*------------------------------------------------------------
889**
890**	Emulate the register_intr() function of FreeBSD 2.0
891**
892**	requires a patch:
893**	FreeBSD 2.0:	"/sys/i386/isa/vector.s"
894**	386bsd0.1:	"/sys/i386/isa/icu.s"
895**	386bsd1.0:	Please ask Jesus Monroy Jr.
896**
897**------------------------------------------------------------
898*/
899
900#include <machine/segments.h>
901
902int		pci_int_unit [16];
903inthand2_t*    (pci_int_hdlr [16]);
904unsigned int *	pci_int_mptr [16];
905unsigned int	pci_int_count[16];
906
907extern void
908	Vpci3(), Vpci4(), Vpci5(), Vpci6(), Vpci7(), Vpci8(), Vpci9(),
909	Vpci10(), Vpci11(), Vpci12(), Vpci13(), Vpci14(), Vpci15();
910
911static inthand_t* pci_int_glue[16] = {
912	0, 0, 0, Vpci3, Vpci4, Vpci5, Vpci6, Vpci7, Vpci8,
913	Vpci9, Vpci10, Vpci11, Vpci12, Vpci13, Vpci14, Vpci15 };
914
915static int
916register_intr __P((int intr, int device_id, unsigned int flags,
917		       inthand2_t *handler, unsigned int* mptr, int unit))
918{
919	if (intr >= 16 || intr <= 2)
920		return (EINVAL);
921	if (pci_int_hdlr [intr])
922		return (EBUSY);
923
924	pci_int_hdlr [intr] = handler;
925	pci_int_unit [intr] = unit;
926	pci_int_mptr [intr] = mptr;
927
928	setidt(NRSVIDT + intr, pci_int_glue[intr], SDT_SYS386IGT, SEL_KPL);
929	return (0);
930}
931#endif /* __FreeBSD2__ */
932#endif /* NPCI */
933