Home | History | Annotate | Line # | Download | only in boot
pci.c revision 1.4.98.1
      1  1.4.98.1     rmind /*	$NetBSD: pci.c,v 1.4.98.1 2011/03/05 20:49:46 rmind Exp $	*/
      2       1.1  sakamoto 
      3  1.4.98.1     rmind /*
      4  1.4.98.1     rmind  * Copyright (C) 1995-1997 Gary Thomas (gdt (at) linuxppc.org)
      5       1.1  sakamoto  * All rights reserved.
      6       1.1  sakamoto  *
      7  1.4.98.1     rmind  * Adapted from a program by:
      8  1.4.98.1     rmind  *                                      Steve Sellgren
      9  1.4.98.1     rmind  *                                      San Francisco Indigo Company
     10  1.4.98.1     rmind  *                                      sfindigo!sellgren (at) uunet.uu.net
     11  1.4.98.1     rmind  * Adapted for Moto boxes by:
     12  1.4.98.1     rmind  *                                      Pat Kane & Mark Scott, 1996
     13  1.4.98.1     rmind  * Fixed for IBM/PowerStack II          Pat Kane 1997
     14       1.1  sakamoto  *
     15       1.1  sakamoto  * Redistribution and use in source and binary forms, with or without
     16       1.1  sakamoto  * modification, are permitted provided that the following conditions
     17       1.1  sakamoto  * are met:
     18       1.1  sakamoto  * 1. Redistributions of source code must retain the above copyright
     19       1.1  sakamoto  *    notice, this list of conditions and the following disclaimer.
     20       1.1  sakamoto  * 2. Redistributions in binary form must reproduce the above copyright
     21       1.1  sakamoto  *    notice, this list of conditions and the following disclaimer in the
     22       1.1  sakamoto  *    documentation and/or other materials provided with the distribution.
     23       1.1  sakamoto  * 3. All advertising materials mentioning features or use of this software
     24       1.1  sakamoto  *    must display the following acknowledgement:
     25  1.4.98.1     rmind  *      This product includes software developed by Gary Thomas.
     26  1.4.98.1     rmind  * 4. The name of the author may not be used to endorse or promote products
     27  1.4.98.1     rmind  *    derived from this software without specific prior written permission.
     28       1.1  sakamoto  *
     29  1.4.98.1     rmind  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     30  1.4.98.1     rmind  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     31  1.4.98.1     rmind  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     32  1.4.98.1     rmind  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     33  1.4.98.1     rmind  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     34  1.4.98.1     rmind  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     35  1.4.98.1     rmind  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     36  1.4.98.1     rmind  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     37  1.4.98.1     rmind  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     38  1.4.98.1     rmind  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     39       1.1  sakamoto  */
     40       1.1  sakamoto 
     41  1.4.98.1     rmind #include <lib/libsa/stand.h>
     42  1.4.98.1     rmind #include <sys/bswap.h>
     43       1.1  sakamoto #include <dev/pci/pcireg.h>
     44  1.4.98.1     rmind #include "boot.h"
     45       1.1  sakamoto 
     46  1.4.98.1     rmind #define NSLOTS 5
     47  1.4.98.1     rmind #define NPCIREGS  10
     48       1.1  sakamoto 
     49  1.4.98.1     rmind 
     50  1.4.98.1     rmind /*
     51  1.4.98.1     rmind  * should use devfunc number/indirect method to be totally safe on
     52  1.4.98.1     rmind  * all machines, this works for now on 3 slot Moto boxes
     53  1.4.98.1     rmind  */
     54  1.4.98.1     rmind 
     55  1.4.98.1     rmind #define PCI_CONFIG_SPACE_BASE	0x80800000
     56  1.4.98.1     rmind #define PCI_CONFIG_SPACE(d, f)	\
     57  1.4.98.1     rmind 		(u_long *)(PCI_CONFIG_SPACE_BASE | (1 << (d)) | ((f) << 8))
     58  1.4.98.1     rmind 
     59  1.4.98.1     rmind struct PCI_ConfigInfo {
     60  1.4.98.1     rmind 	u_long *config_addr;
     61  1.4.98.1     rmind 	u_long regs[NPCIREGS];
     62  1.4.98.1     rmind } PCI_slots [NSLOTS] = {
     63  1.4.98.1     rmind 	{ PCI_CONFIG_SPACE(11, 0), { 0xDE, 0xAD, 0xBE, 0xEF } },
     64  1.4.98.1     rmind 	{ PCI_CONFIG_SPACE(12, 0), { 0xDE, 0xAD, 0xBE, 0xEF } },
     65  1.4.98.1     rmind 	{ PCI_CONFIG_SPACE(13, 0), { 0xDE, 0xAD, 0xBE, 0xEF } },
     66  1.4.98.1     rmind 	{ PCI_CONFIG_SPACE(14, 0), { 0xDE, 0xAD, 0xBE, 0xEF } },
     67  1.4.98.1     rmind 	{ PCI_CONFIG_SPACE(15, 0), { 0xDE, 0xAD, 0xBE, 0xEF } },
     68  1.4.98.1     rmind };
     69  1.4.98.1     rmind 
     70  1.4.98.1     rmind 
     71  1.4.98.1     rmind #define DEVID		(PCI_ID_REG >> 2)
     72  1.4.98.1     rmind #define CMD		(PCI_COMMAND_STATUS_REG >> 2)
     73  1.4.98.1     rmind #define CLASS		(PCI_CLASS_REG >> 2)
     74  1.4.98.1     rmind #define BAR_BASE	(PCI_MAPREG_START >> 2)
     75  1.4.98.1     rmind 
     76  1.4.98.1     rmind /*
     77  1.4.98.1     rmind  * The following code modifies the PCI Command register
     78  1.4.98.1     rmind  * to enable memory and I/O accesses.
     79  1.4.98.1     rmind  */
     80  1.4.98.1     rmind void
     81  1.4.98.1     rmind enablePCI(int slot, int io, int mem, int master)
     82       1.1  sakamoto {
     83  1.4.98.1     rmind 	volatile u_char *ppci;
     84  1.4.98.1     rmind 	u_char enable = 0;
     85  1.4.98.1     rmind 
     86  1.4.98.1     rmind 	if (io)
     87  1.4.98.1     rmind 		enable |= PCI_COMMAND_IO_ENABLE;
     88  1.4.98.1     rmind 	if (mem)
     89  1.4.98.1     rmind 		enable |= PCI_COMMAND_MEM_ENABLE;
     90  1.4.98.1     rmind 	if (master)
     91  1.4.98.1     rmind 		enable |= PCI_COMMAND_MASTER_ENABLE;
     92  1.4.98.1     rmind 
     93  1.4.98.1     rmind 	ppci = (u_char *)&PCI_slots[slot].config_addr[CMD];
     94  1.4.98.1     rmind 	*ppci = enable;
     95  1.4.98.1     rmind 	__asm volatile("eieio");
     96  1.4.98.1     rmind }
     97  1.4.98.1     rmind 
     98  1.4.98.1     rmind void
     99  1.4.98.1     rmind scanPCI(void)
    100  1.4.98.1     rmind {
    101  1.4.98.1     rmind 	struct PCI_ConfigInfo *pslot;
    102  1.4.98.1     rmind 	int slt, r;
    103  1.4.98.1     rmind 
    104  1.4.98.1     rmind 	for (slt = 0; slt < NSLOTS; slt++) {
    105  1.4.98.1     rmind 		pslot = &PCI_slots[slt];
    106  1.4.98.1     rmind 		for (r = 0; r < NPCIREGS; r++)
    107  1.4.98.1     rmind 			pslot->regs[r] = bswap32(pslot->config_addr[r]);
    108  1.4.98.1     rmind 	}
    109  1.4.98.1     rmind }
    110  1.4.98.1     rmind 
    111  1.4.98.1     rmind int
    112  1.4.98.1     rmind findPCIVga(void)
    113  1.4.98.1     rmind {
    114  1.4.98.1     rmind 	struct PCI_ConfigInfo *pslot;
    115  1.4.98.1     rmind 	int theSlot = -1;
    116  1.4.98.1     rmind 	int highVgaSlot = -1;
    117  1.4.98.1     rmind 	int slt;
    118  1.4.98.1     rmind 
    119  1.4.98.1     rmind 	for (slt = 0; slt < NSLOTS; slt++) {
    120  1.4.98.1     rmind 		pslot = &PCI_slots[slt];
    121  1.4.98.1     rmind 		if (pslot->regs[DEVID] != 0xffffffff) {	/* card in slot ? */
    122  1.4.98.1     rmind 			if (PCI_CLASS(pslot->regs[CLASS]) ==
    123  1.4.98.1     rmind 			    PCI_CLASS_DISPLAY) {
    124  1.4.98.1     rmind 				highVgaSlot = slt;
    125  1.4.98.1     rmind 				if ((pslot->regs[CMD] & 0x03)) { /* did firmware enable it ? */
    126  1.4.98.1     rmind 					theSlot = slt;
    127  1.4.98.1     rmind 				}
    128  1.4.98.1     rmind 			}
    129  1.4.98.1     rmind 		}
    130  1.4.98.1     rmind 	}
    131  1.4.98.1     rmind 	if (theSlot == -1)
    132  1.4.98.1     rmind 		theSlot = highVgaSlot;
    133       1.1  sakamoto 
    134  1.4.98.1     rmind 	return theSlot;
    135       1.1  sakamoto }
    136       1.1  sakamoto 
    137  1.4.98.1     rmind int
    138  1.4.98.1     rmind PCISlotnum(u_int bus, u_int dev, u_int func)
    139       1.1  sakamoto {
    140  1.4.98.1     rmind 	u_long *tag;
    141  1.4.98.1     rmind 	int i;
    142       1.1  sakamoto 
    143  1.4.98.1     rmind 	if (bus != 0 ||
    144  1.4.98.1     rmind 	    dev < 11 || dev > 15 ||
    145  1.4.98.1     rmind 	    func > 7)
    146  1.4.98.1     rmind 		return -1;
    147  1.4.98.1     rmind 
    148  1.4.98.1     rmind 	tag = PCI_CONFIG_SPACE(dev, func);
    149  1.4.98.1     rmind 	for (i = 0; i < sizeof(PCI_slots) / sizeof(struct PCI_ConfigInfo); i++)
    150  1.4.98.1     rmind 		if (tag == PCI_slots[i].config_addr)
    151  1.4.98.1     rmind 			return i;
    152  1.4.98.1     rmind 	return -1;
    153       1.1  sakamoto }
    154       1.1  sakamoto 
    155  1.4.98.1     rmind /* return Vendor ID of card in the slot */
    156  1.4.98.1     rmind int
    157  1.4.98.1     rmind PCIVendor(int slotnum)
    158       1.1  sakamoto {
    159  1.4.98.1     rmind 	struct PCI_ConfigInfo *pslot;
    160       1.1  sakamoto 
    161  1.4.98.1     rmind 	pslot = &PCI_slots[slotnum];
    162       1.1  sakamoto 
    163  1.4.98.1     rmind 	return pslot->regs[DEVID] & 0xffff;
    164  1.4.98.1     rmind }
    165       1.1  sakamoto 
    166  1.4.98.1     rmind /* return mapped address for I/O or Memory */
    167  1.4.98.1     rmind u_long
    168  1.4.98.1     rmind PCIAddress(int slotnum, u_int bar, int type)
    169  1.4.98.1     rmind {
    170  1.4.98.1     rmind 	struct PCI_ConfigInfo *pslot;
    171       1.2  sakamoto 
    172  1.4.98.1     rmind 	if (bar >= 6)
    173  1.4.98.1     rmind 		return 0xffffffff;
    174       1.1  sakamoto 
    175  1.4.98.1     rmind 	pslot = &PCI_slots[slotnum];
    176       1.1  sakamoto 
    177  1.4.98.1     rmind 	if (pslot->regs[DEVID] == 0xffffffff ||
    178  1.4.98.1     rmind 	    PCI_MAPREG_TYPE(pslot->regs[BAR_BASE + bar]) != type)
    179  1.4.98.1     rmind 		return 0xffffffff;
    180       1.2  sakamoto 
    181  1.4.98.1     rmind 	return PCI_MAPREG_MEM_ADDR(pslot->regs[BAR_BASE + bar]);
    182  1.4.98.1     rmind }
    183       1.2  sakamoto 
    184  1.4.98.1     rmind #ifdef DEBUG
    185  1.4.98.1     rmind void
    186  1.4.98.1     rmind printPCIslots(void)
    187  1.4.98.1     rmind {
    188  1.4.98.1     rmind 	int i;
    189  1.4.98.1     rmind 	for (i = 0; i < NSLOTS; i++) {
    190  1.4.98.1     rmind 		printf("PCI Slot number: %d", i);
    191  1.4.98.1     rmind 		printf(" Vendor ID: 0x%x\n", PCIVendor(i));
    192       1.1  sakamoto 	}
    193       1.1  sakamoto }
    194  1.4.98.1     rmind #endif /* DEBUG */
    195