1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-30 16:51:41 +00:00

New PCI attach code:

PCI BIOS mappings are retained, except if option PCI_REMAP
is specified in the kernel config file.
There is now a list of attach addresses, and the first
address that seems to make some device registers appear
is chosen.

Reviewed by:	se
Submitted by:	wolf
This commit is contained in:
Stefan Eßer 1995-02-22 14:17:15 +00:00
parent 1242c0a653
commit d9dc2f74ef
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=6630
2 changed files with 254 additions and 98 deletions

View File

@ -1,6 +1,6 @@
/************************************************************************** /**************************************************************************
** **
** $Id: pci.c,v 1.9 1994/11/02 23:47:13 se Exp $ ** $Id: pci.c,v 1.14 1995/02/14 23:33:38 se Exp $
** **
** General subroutines for the PCI bus on 80*86 systems. ** General subroutines for the PCI bus on 80*86 systems.
** pci_configure () ** pci_configure ()
@ -36,6 +36,8 @@
*************************************************************************** ***************************************************************************
*/ */
#define PCI_PATCHLEVEL "pl2 95/02/21"
#include <pci.h> #include <pci.h>
#if NPCI > 0 #if NPCI > 0
@ -104,16 +106,27 @@ static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize);
/*-------------------------------------------------------- /*--------------------------------------------------------
** **
** The pci devices can be mapped to any address. ** The pci devices can be mapped to any address.
** As default we start at the last gigabyte. ** This is a list of possible starting addresses.
** It can be prepended by a config option.
** **
**-------------------------------------------------------- **--------------------------------------------------------
*/ */
#ifndef PCI_PMEM_START static u_long pci_stable[] = {
#define PCI_PMEM_START 0xc0000000 #ifdef PCI_PMEM_START
(PCI_PMEM_START),
#endif #endif
0xf1000000,
0x53900000,
0xc0000000,
0x81000000,
0x0f000000,
};
static vm_offset_t pci_paddr = 0;
static vm_offset_t pci_pold = 0;
static vm_offset_t pci_pidx = 0;
static vm_offset_t pci_paddr = PCI_PMEM_START;
/*-------------------------------------------------------- /*--------------------------------------------------------
** **
@ -175,7 +188,6 @@ void pci_configure()
int pciint; int pciint;
int irq; int irq;
char* name=0; char* name=0;
vm_offset_t old_addr=pci_paddr;
u_short old_ioaddr=pci_ioaddr; u_short old_ioaddr=pci_ioaddr;
int dvi; int dvi;
@ -204,8 +216,8 @@ void pci_configure()
/* /*
** hello world .. ** hello world ..
*/ */
pci_pold=pci_paddr;
for (bus=0;bus<NPCI;bus++) { for (bus=0;bus<NPCI;bus++) {
#ifndef PCI_QUIET #ifndef PCI_QUIET
printf ("%s%d: scanning device 0..%d, mechanism=%d.\n", printf ("%s%d: scanning device 0..%d, mechanism=%d.\n",
@ -373,9 +385,9 @@ void pci_configure()
}; };
#ifndef PCI_QUIET #ifndef PCI_QUIET
if (pci_paddr != old_addr) if (pci_paddr != pci_pold)
printf ("pci uses physical addresses from 0x%lx to 0x%lx\n", printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
(u_long)PCI_PMEM_START, (u_long)pci_paddr); (u_long)pci_pold, (u_long)pci_paddr);
if (pci_ioaddr != old_ioaddr) if (pci_ioaddr != old_ioaddr)
printf ("pci devices use ioports from 0x%x to 0x%x\n", printf ("pci devices use ioports from 0x%x to 0x%x\n",
(unsigned)PCI_PORT_START, (unsigned)pci_ioaddr); (unsigned)PCI_PORT_START, (unsigned)pci_ioaddr);
@ -424,8 +436,8 @@ pci_conf_write (pcici_t tag, u_long reg, u_long data)
int pci_map_port (pcici_t tag, u_long reg, u_short* pa) int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
{ {
u_long data; u_long data,oldmap;
u_short size; u_short size, ioaddr;
/* /*
** sanity check ** sanity check
@ -445,6 +457,12 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
** n-2 bits are hardwired as 0. ** n-2 bits are hardwired as 0.
*/ */
#ifdef PCI_REMAP
oldmap = 0;
#else
oldmap = pcibus.pb_read (tag, reg) & 0xfffffffc;
if (oldmap==0xfffffffc) oldmap=0;
#endif
pcibus.pb_write (tag, reg, 0xfffffffful); pcibus.pb_write (tag, reg, 0xfffffffful);
data = pcibus.pb_read (tag, reg); data = pcibus.pb_read (tag, reg);
@ -468,11 +486,19 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
if (!size) return (0); if (!size) return (0);
/* /*
** align physical address to virtual size ** align physical address to virtual size,
** set ioaddr,
** and don't forget to increment pci_ioaddr
*/ */
if ((data = pci_ioaddr % size)) if (oldmap) {
pci_ioaddr += size - data; ioaddr = oldmap;
} else {
if ((data = pci_ioaddr % size))
pci_ioaddr += size - data;
ioaddr = pci_ioaddr;
pci_ioaddr += size;
};
#ifndef PCI_QUIET #ifndef PCI_QUIET
/* /*
@ -480,14 +506,14 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
*/ */
printf ("\treg%d: ioaddr=0x%x size=0x%x\n", printf ("\treg%d: ioaddr=0x%x size=0x%x\n",
(unsigned) reg, (unsigned) pci_ioaddr, (unsigned) size); (unsigned) reg, (unsigned) ioaddr, (unsigned) size);
#endif #endif
/* /*
** set device address ** set device address
*/ */
pcibus.pb_write (tag, reg, (u_long) pci_ioaddr); pcibus.pb_write (tag, reg, (u_long) ioaddr);
/* /*
** return them to the driver ** return them to the driver
@ -495,12 +521,6 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
*pa = pci_ioaddr; *pa = pci_ioaddr;
/*
** and don't forget to increment pci_ioaddr
*/
pci_ioaddr += size;
return (1); return (1);
} }
@ -515,7 +535,7 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa) int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
{ {
u_long data; u_long data,oldmap,paddr;
vm_size_t vsize; vm_size_t vsize;
vm_offset_t vaddr; vm_offset_t vaddr;
int i; int i;
@ -531,13 +551,19 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
}; };
/* /*
** get size and type of memory ** save old mapping, get size and type of memory
** **
** type is in the lowest four bits. ** type is in the lowest four bits.
** If device requires 2^n bytes, the next ** If device requires 2^n bytes, the next
** n-4 bits are read as 0. ** n-4 bits are read as 0.
*/ */
#ifdef PCI_REMAP
oldmap = 0;
#else
oldmap = pcibus.pb_read (tag, reg) & 0xfffffff0;
if (oldmap==0xfffffff0) oldmap = 0;
#endif
pcibus.pb_write (tag, reg, 0xfffffffful); pcibus.pb_write (tag, reg, 0xfffffffful);
data = pcibus.pb_read (tag, reg); data = pcibus.pb_read (tag, reg);
@ -551,7 +577,7 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
(unsigned) data); (unsigned) data);
return (0); return (0);
}; };
/* /*
** mask out the type, ** mask out the type,
** and round up to a page size ** and round up to a page size
@ -560,7 +586,29 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK)); vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK));
if (!vsize) return (0); if (!vsize) return (0);
if (oldmap) {
paddr = oldmap;
goto domap;
};
next_try:
if (!pci_paddr) {
/*
** Get a starting address.
*/
if (pci_pidx >= sizeof(pci_stable)/sizeof(u_long)) {
printf ("pci_map_mem: out of start addresses.\n");
return (0);
};
pci_paddr = pci_stable[pci_pidx++];
pci_pold = 0;
if (pci_pidx>1)
printf ("\t(retry at 0x%x)\n",
(unsigned) pci_paddr);
};
/* /*
** align physical address to virtual size ** align physical address to virtual size
*/ */
@ -568,53 +616,83 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
if ((data = pci_paddr % vsize)) if ((data = pci_paddr % vsize))
pci_paddr += vsize - data; pci_paddr += vsize - data;
vaddr = (vm_offset_t) pmap_mapdev (pci_paddr, vsize); if (!pci_pold)
pci_pold = pci_paddr;
/*
** set physical mapping address,
** and reserve physical address range
*/
paddr = pci_paddr;
pci_paddr += vsize;
domap:
vaddr = (vm_offset_t) pmap_mapdev (paddr, vsize);
if (!vaddr) return (0); if (!vaddr) return (0);
#ifndef PCI_QUIET #ifndef PCI_QUIET
/* /*
** display values. ** display values.
*/ */
printf ("\treg%d: virtual=0x%lx physical=0x%lx\n", printf ("\treg%d: virtual=0x%lx physical=0x%lx\n",
(unsigned) reg, (u_long)vaddr, (u_long)pci_paddr); (unsigned) reg, (u_long)vaddr, (u_long)paddr);
#endif #endif
/* /*
** probe for already mapped device. ** probe for already mapped device.
*/ */
for (i=0; i<vsize; i+=4) { if (!oldmap) for (i=0; i<vsize; i+=4) {
u_long* addr = (u_long*) (vaddr+i); u_long* addr = (u_long*) (vaddr+i);
data = *addr; data = *addr;
if (data != 0xffffffff) { if (data != 0xffffffff) {
printf ("WARNING: possible address conflict " printf ("\t(possible address conflict: "
"at 0x%08x (read: 0x%08x).\n", "at 0x%x read: 0x%x)\n",
(unsigned) pci_paddr+i, (unsigned) data); (unsigned) paddr+i, (unsigned) data);
break; pci_paddr = 0;
goto next_try;
}; };
}; };
/* /*
** return them to the driver ** Set device address
*/
pcibus.pb_write (tag, reg, paddr);
/*
** Check if correctly mapped.
**
** W A R N I N G
**
** This code assumes that the device will NOT return
** only ones (0xffffffff) from all offsets.
*/
for (i=0; i<vsize; i+=4) {
u_long* addr = (u_long*) (vaddr+i);
data = *addr;
if (data != 0xffffffff)
break;
};
if (data==0xffffffff) {
printf ("\t(possible mapping problem: "
"at 0x%x read 0xffffffff)\n",
(unsigned) paddr);
pci_paddr = 0;
goto next_try;
};
/*
** Return addresses to the driver
*/ */
*va = vaddr; *va = vaddr;
*pa = pci_paddr; *pa = paddr;
/*
** set device address
*/
pcibus.pb_write (tag, reg, pci_paddr);
/*
** and don't forget to increment pci_paddr
*/
pci_paddr += vsize;
return (1); return (1);
} }

View File

@ -1,6 +1,6 @@
/************************************************************************** /**************************************************************************
** **
** $Id: pci.c,v 1.9 1994/11/02 23:47:13 se Exp $ ** $Id: pci.c,v 1.14 1995/02/14 23:33:38 se Exp $
** **
** General subroutines for the PCI bus on 80*86 systems. ** General subroutines for the PCI bus on 80*86 systems.
** pci_configure () ** pci_configure ()
@ -36,6 +36,8 @@
*************************************************************************** ***************************************************************************
*/ */
#define PCI_PATCHLEVEL "pl2 95/02/21"
#include <pci.h> #include <pci.h>
#if NPCI > 0 #if NPCI > 0
@ -104,16 +106,27 @@ static vm_offset_t pmap_mapdev (vm_offset_t paddr, vm_size_t vsize);
/*-------------------------------------------------------- /*--------------------------------------------------------
** **
** The pci devices can be mapped to any address. ** The pci devices can be mapped to any address.
** As default we start at the last gigabyte. ** This is a list of possible starting addresses.
** It can be prepended by a config option.
** **
**-------------------------------------------------------- **--------------------------------------------------------
*/ */
#ifndef PCI_PMEM_START static u_long pci_stable[] = {
#define PCI_PMEM_START 0xc0000000 #ifdef PCI_PMEM_START
(PCI_PMEM_START),
#endif #endif
0xf1000000,
0x53900000,
0xc0000000,
0x81000000,
0x0f000000,
};
static vm_offset_t pci_paddr = 0;
static vm_offset_t pci_pold = 0;
static vm_offset_t pci_pidx = 0;
static vm_offset_t pci_paddr = PCI_PMEM_START;
/*-------------------------------------------------------- /*--------------------------------------------------------
** **
@ -175,7 +188,6 @@ void pci_configure()
int pciint; int pciint;
int irq; int irq;
char* name=0; char* name=0;
vm_offset_t old_addr=pci_paddr;
u_short old_ioaddr=pci_ioaddr; u_short old_ioaddr=pci_ioaddr;
int dvi; int dvi;
@ -204,8 +216,8 @@ void pci_configure()
/* /*
** hello world .. ** hello world ..
*/ */
pci_pold=pci_paddr;
for (bus=0;bus<NPCI;bus++) { for (bus=0;bus<NPCI;bus++) {
#ifndef PCI_QUIET #ifndef PCI_QUIET
printf ("%s%d: scanning device 0..%d, mechanism=%d.\n", printf ("%s%d: scanning device 0..%d, mechanism=%d.\n",
@ -373,9 +385,9 @@ void pci_configure()
}; };
#ifndef PCI_QUIET #ifndef PCI_QUIET
if (pci_paddr != old_addr) if (pci_paddr != pci_pold)
printf ("pci uses physical addresses from 0x%lx to 0x%lx\n", printf ("pci uses physical addresses from 0x%lx to 0x%lx\n",
(u_long)PCI_PMEM_START, (u_long)pci_paddr); (u_long)pci_pold, (u_long)pci_paddr);
if (pci_ioaddr != old_ioaddr) if (pci_ioaddr != old_ioaddr)
printf ("pci devices use ioports from 0x%x to 0x%x\n", printf ("pci devices use ioports from 0x%x to 0x%x\n",
(unsigned)PCI_PORT_START, (unsigned)pci_ioaddr); (unsigned)PCI_PORT_START, (unsigned)pci_ioaddr);
@ -424,8 +436,8 @@ pci_conf_write (pcici_t tag, u_long reg, u_long data)
int pci_map_port (pcici_t tag, u_long reg, u_short* pa) int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
{ {
u_long data; u_long data,oldmap;
u_short size; u_short size, ioaddr;
/* /*
** sanity check ** sanity check
@ -445,6 +457,12 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
** n-2 bits are hardwired as 0. ** n-2 bits are hardwired as 0.
*/ */
#ifdef PCI_REMAP
oldmap = 0;
#else
oldmap = pcibus.pb_read (tag, reg) & 0xfffffffc;
if (oldmap==0xfffffffc) oldmap=0;
#endif
pcibus.pb_write (tag, reg, 0xfffffffful); pcibus.pb_write (tag, reg, 0xfffffffful);
data = pcibus.pb_read (tag, reg); data = pcibus.pb_read (tag, reg);
@ -468,11 +486,19 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
if (!size) return (0); if (!size) return (0);
/* /*
** align physical address to virtual size ** align physical address to virtual size,
** set ioaddr,
** and don't forget to increment pci_ioaddr
*/ */
if ((data = pci_ioaddr % size)) if (oldmap) {
pci_ioaddr += size - data; ioaddr = oldmap;
} else {
if ((data = pci_ioaddr % size))
pci_ioaddr += size - data;
ioaddr = pci_ioaddr;
pci_ioaddr += size;
};
#ifndef PCI_QUIET #ifndef PCI_QUIET
/* /*
@ -480,14 +506,14 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
*/ */
printf ("\treg%d: ioaddr=0x%x size=0x%x\n", printf ("\treg%d: ioaddr=0x%x size=0x%x\n",
(unsigned) reg, (unsigned) pci_ioaddr, (unsigned) size); (unsigned) reg, (unsigned) ioaddr, (unsigned) size);
#endif #endif
/* /*
** set device address ** set device address
*/ */
pcibus.pb_write (tag, reg, (u_long) pci_ioaddr); pcibus.pb_write (tag, reg, (u_long) ioaddr);
/* /*
** return them to the driver ** return them to the driver
@ -495,12 +521,6 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
*pa = pci_ioaddr; *pa = pci_ioaddr;
/*
** and don't forget to increment pci_ioaddr
*/
pci_ioaddr += size;
return (1); return (1);
} }
@ -515,7 +535,7 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa) int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
{ {
u_long data; u_long data,oldmap,paddr;
vm_size_t vsize; vm_size_t vsize;
vm_offset_t vaddr; vm_offset_t vaddr;
int i; int i;
@ -531,13 +551,19 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
}; };
/* /*
** get size and type of memory ** save old mapping, get size and type of memory
** **
** type is in the lowest four bits. ** type is in the lowest four bits.
** If device requires 2^n bytes, the next ** If device requires 2^n bytes, the next
** n-4 bits are read as 0. ** n-4 bits are read as 0.
*/ */
#ifdef PCI_REMAP
oldmap = 0;
#else
oldmap = pcibus.pb_read (tag, reg) & 0xfffffff0;
if (oldmap==0xfffffff0) oldmap = 0;
#endif
pcibus.pb_write (tag, reg, 0xfffffffful); pcibus.pb_write (tag, reg, 0xfffffffful);
data = pcibus.pb_read (tag, reg); data = pcibus.pb_read (tag, reg);
@ -551,7 +577,7 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
(unsigned) data); (unsigned) data);
return (0); return (0);
}; };
/* /*
** mask out the type, ** mask out the type,
** and round up to a page size ** and round up to a page size
@ -560,7 +586,29 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK)); vsize = round_page (-(data & PCI_MAP_MEMORY_ADDRESS_MASK));
if (!vsize) return (0); if (!vsize) return (0);
if (oldmap) {
paddr = oldmap;
goto domap;
};
next_try:
if (!pci_paddr) {
/*
** Get a starting address.
*/
if (pci_pidx >= sizeof(pci_stable)/sizeof(u_long)) {
printf ("pci_map_mem: out of start addresses.\n");
return (0);
};
pci_paddr = pci_stable[pci_pidx++];
pci_pold = 0;
if (pci_pidx>1)
printf ("\t(retry at 0x%x)\n",
(unsigned) pci_paddr);
};
/* /*
** align physical address to virtual size ** align physical address to virtual size
*/ */
@ -568,53 +616,83 @@ int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
if ((data = pci_paddr % vsize)) if ((data = pci_paddr % vsize))
pci_paddr += vsize - data; pci_paddr += vsize - data;
vaddr = (vm_offset_t) pmap_mapdev (pci_paddr, vsize); if (!pci_pold)
pci_pold = pci_paddr;
/*
** set physical mapping address,
** and reserve physical address range
*/
paddr = pci_paddr;
pci_paddr += vsize;
domap:
vaddr = (vm_offset_t) pmap_mapdev (paddr, vsize);
if (!vaddr) return (0); if (!vaddr) return (0);
#ifndef PCI_QUIET #ifndef PCI_QUIET
/* /*
** display values. ** display values.
*/ */
printf ("\treg%d: virtual=0x%lx physical=0x%lx\n", printf ("\treg%d: virtual=0x%lx physical=0x%lx\n",
(unsigned) reg, (u_long)vaddr, (u_long)pci_paddr); (unsigned) reg, (u_long)vaddr, (u_long)paddr);
#endif #endif
/* /*
** probe for already mapped device. ** probe for already mapped device.
*/ */
for (i=0; i<vsize; i+=4) { if (!oldmap) for (i=0; i<vsize; i+=4) {
u_long* addr = (u_long*) (vaddr+i); u_long* addr = (u_long*) (vaddr+i);
data = *addr; data = *addr;
if (data != 0xffffffff) { if (data != 0xffffffff) {
printf ("WARNING: possible address conflict " printf ("\t(possible address conflict: "
"at 0x%08x (read: 0x%08x).\n", "at 0x%x read: 0x%x)\n",
(unsigned) pci_paddr+i, (unsigned) data); (unsigned) paddr+i, (unsigned) data);
break; pci_paddr = 0;
goto next_try;
}; };
}; };
/* /*
** return them to the driver ** Set device address
*/
pcibus.pb_write (tag, reg, paddr);
/*
** Check if correctly mapped.
**
** W A R N I N G
**
** This code assumes that the device will NOT return
** only ones (0xffffffff) from all offsets.
*/
for (i=0; i<vsize; i+=4) {
u_long* addr = (u_long*) (vaddr+i);
data = *addr;
if (data != 0xffffffff)
break;
};
if (data==0xffffffff) {
printf ("\t(possible mapping problem: "
"at 0x%x read 0xffffffff)\n",
(unsigned) paddr);
pci_paddr = 0;
goto next_try;
};
/*
** Return addresses to the driver
*/ */
*va = vaddr; *va = vaddr;
*pa = pci_paddr; *pa = paddr;
/*
** set device address
*/
pcibus.pb_write (tag, reg, pci_paddr);
/*
** and don't forget to increment pci_paddr
*/
pci_paddr += vsize;
return (1); return (1);
} }