Skip site navigation (1)Skip section navigation (2)
Date:      1 Jun 1998 10:50:31 +0100
From:      Graeme Brown <graeme.brown@bt-sys.bt.co.uk>
To:        David Greenman <dg@root.com>
Cc:        "FreeBSD-Net (FreeBSD.Org) List" <freebsd-net@FreeBSD.ORG>
Subject:   My fxp troubles under FreeBSD 2.2.6
Message-ID:  <n1315424303.32309@maczebedee>

next in thread | raw e-mail | index | archive | help
David

I looked a little into the FreeBSD 2.2.6 kernel source code under
/usr/src/sys/pci at  function   pci_map_mem()  in  file  pci.c

/*-----------------------------------------------------------------------
**
**	Map device into virtual and physical space
**
**	Actually the device should have been mapped by the bios.
**	This function only reads and verifies the value.
**
**      PCI-Specification:  6.2.5.1: address maps
**
**-----------------------------------------------------------------------
*/

int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa)
{
	struct pcicb *link = pcicb;
	unsigned    data ,paddr;
	vm_size_t   psize, poffs;
	vm_offset_t vaddr;

	/*
	**	sanity check
	*/

	if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) {
		printf ("pci_map_mem failed: bad register=0x%x\n",
			(unsigned)reg);
		return (0);
	};

	/*
	**	save old mapping, get size and type of memory
	**
	**	type is in the lowest four bits.
	**	If device requires 2^n bytes, the next
	**	n-4 bits are read as 0.
	*/

	paddr = pci_conf_read (tag, reg) & PCI_MAP_MEMORY_ADDRESS_MASK;
	pci_conf_write (tag, reg, 0xfffffffful);
	data = pci_conf_read (tag, reg);
	pci_conf_write (tag, reg, paddr);

	/*
	**	check the type
	*/

	if (!((data & PCI_MAP_MEMORY_TYPE_MASK) == PCI_MAP_MEMORY_TYPE_32BIT_1M
	      && (paddr & ~0xfffff) == 0)
	    && (data & PCI_MAP_MEMORY_TYPE_MASK) != PCI_MAP_MEMORY_TYPE_32BIT){
		printf ("pci_map_mem failed: bad memory type=0x%x\n",
			(unsigned) data);
		return (0);
	};

	/*
	**	get the size.
	*/

	psize = -(data & PCI_MAP_MEMORY_ADDRESS_MASK);

	if (!paddr || paddr == PCI_MAP_MEMORY_ADDRESS_MASK) {
		paddr = pci_memalloc (pcicb, 0, psize);
		if (!paddr) {
			printf ("pci_map_mem: not configured by bios.\n");
			return (0);
		};
		pci_register_memory (pcicb, paddr, paddr+psize-1);
	};

	if (paddr < pcicb->pcicb_membase ||
		paddr + psize - 1 > pcicb->pcicb_memlimit) {
		printf ("pci_map_mem failed: device's memrange 0x%x-0x%x is "
			"incompatible with its bridge's memrange 0x%x-0x%x\n",
			(unsigned) paddr,
			(unsigned) (paddr + psize - 1),
			(unsigned) pcicb->pcicb_membase,
			(unsigned) pcicb->pcicb_memlimit);
/*		return (0);*/
/* ACHTUNG: Ist der Code richtig, wenn eine PCI-PCI-Bridge fuer
 * die PCI-Slots verwendet wird, aber die Onboard-Devices direkt 
 * an der CPU-PCI-Bridge haengen (Siehe Compaq Prolinea Problem) ???
 */
	}
	pci_conf_write (tag, reg, paddr);

	/*
	**	Truncate paddr to page boundary.
	**	(Or does pmap_mapdev the job?)
	*/

	poffs = paddr - trunc_page (paddr);
	vaddr = (vm_offset_t) pmap_mapdev (paddr-poffs, psize+poffs);

	if (!vaddr) return (0);

	vaddr += poffs;

#ifndef PCI_QUIET
	/*
	**	display values.
	*/

	if (bootverbose)
		printf ("\treg%d: virtual=0x%lx physical=0x%lx size=0x%lx\n",
		 (unsigned) reg, (u_long)vaddr, (u_long)paddr, (u_long)psize);
#endif
	/*
	**      set the configuration register and
	**      return the address to the driver
	**      Make sure to enable each upstream bridge
	**      so memory and DMA can go all the way.
	*/

	for (;;) {
		data =  pci_conf_read (tag, PCI_COMMAND_STATUS_REG) & 0xffff;
		data |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
		(void)  pci_conf_write(tag, PCI_COMMAND_STATUS_REG, data);
		if ((link = link->pcicb_up) == NULL)
			break;
		tag = link->pcicb_bridge;
	}

	*va = vaddr;
	*pa = paddr;

	return (1);
}



The error message being triggered by  the test 

if (paddr < pcicb->pcicb_membase ||
		paddr + psize - 1 > pcicb->pcicb_memlimit) {
		printf ("pci_map_mem failed: device's memrange 0x%x-0x%x is "
			"incompatible with its bridge's memrange 0x%x-0x%x\n",
			(unsigned) paddr,
			(unsigned) (paddr + psize - 1),
			(unsigned) pcicb->pcicb_membase,
			(unsigned) pcicb->pcicb_memlimit);
/*		return (0);*/
/* ACHTUNG: Ist der Code richtig, wenn eine PCI-PCI-Bridge fuer
 * die PCI-Slots verwendet wird, aber die Onboard-Devices direkt 
 * an der CPU-PCI-Bridge haengen (Siehe Compaq Prolinea Problem) ???
 */

I notice the comment in German translates (if I remenber my high-school
German) as 

ATTENTION: Is the code correct if a PCI-PCI-Bridge for the PCI slots
is changed but the Onboard-Devices directly on the CPU-PCI bridge
hang (as in "get hung-up" or as in "are connected-to" ??)  ( See Compaq
Prolinea Problem) ???

I notice the author of pci.c is Wolfgang Stanglmeier. Is he contactable 
via email ?  Who is/are the PCI bus specialist(s) within the FreeBSD Org ? Can
we have his/their comments on my problem ?

TIA
Graeme N Brown
BT Laboratories, UK
email: graeme.brown@bt-sys.bt.co.uk



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?n1315424303.32309>