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