1 /* $NetBSD: pci.c,v 1.2 2014/04/03 23:49:47 mrg 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 45 #include "boot.h" 46 47 #define PCI_NSLOTS 8 48 #define PCI_NREGS 10 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 #define DEVID (PCI_ID_REG >> 2) 60 #define CMD (PCI_COMMAND_STATUS_REG >> 2) 61 #define CLASS (PCI_CLASS_REG >> 2) 62 #define BAR_BASE (PCI_MAPREG_START >> 2) 63 64 struct PCI_cinfo { 65 u_long *config_addr; 66 u_long regs[PCI_NREGS]; 67 } PCI_slots[PCI_NSLOTS] = { 68 { (u_long *)0x80808000, {0xDEADBEEF,} }, 69 { (u_long *)0x80800800, {0xDEADBEEF,} }, 70 { (u_long *)0x80801000, {0xDEADBEEF,} }, 71 { (u_long *)0x80802000, {0xDEADBEEF,} }, 72 { (u_long *)0x80804000, {0xDEADBEEF,} }, 73 { (u_long *)0x80810000, {0xDEADBEEF,} }, 74 { (u_long *)0x80820000, {0xDEADBEEF,} }, 75 { (u_long *)0x80840000, {0xDEADBEEF,} }, 76 }; 77 78 /* 79 * The following code modifies the PCI Command register 80 * to enable memory and I/O accesses. 81 */ 82 void 83 enablePCI(int slot, int io, int mem, int master) 84 { 85 volatile u_char *ppci; 86 u_char enable = 0; 87 88 if (io) 89 enable |= PCI_COMMAND_IO_ENABLE; 90 if (mem) 91 enable |= PCI_COMMAND_MEM_ENABLE; 92 if (master) 93 enable |= PCI_COMMAND_MASTER_ENABLE; 94 95 ppci = (u_char *)&PCI_slots[slot].config_addr[CMD]; 96 *ppci = enable; 97 __asm volatile("eieio"); 98 } 99 100 int 101 PCISlotnum(u_int bus, u_int dev, u_int func) 102 { 103 u_long *tag; 104 int i; 105 106 if (bus != 0 || 107 dev < 8 || dev > 18 || 108 func > 7) 109 return -1; 110 111 tag = PCI_CONFIG_SPACE(dev, func); 112 for (i = 0; i < sizeof(PCI_slots) / sizeof(struct PCI_cinfo); i++) 113 if (tag == PCI_slots[i].config_addr) 114 return i; 115 return -1; 116 } 117 118 /* return mapped address for I/O or Memory */ 119 u_long 120 PCIAddress(int slotnum, u_int bar, int type) 121 { 122 struct PCI_cinfo *pslot; 123 124 if (bar >= 6) 125 return 0xffffffff; 126 127 pslot = &PCI_slots[slotnum]; 128 129 if (pslot->regs[DEVID] == 0xffffffff || 130 PCI_MAPREG_TYPE(pslot->regs[BAR_BASE + bar]) != type) 131 return 0xffffffff; 132 133 return PCI_MAPREG_MEM_ADDR(pslot->regs[BAR_BASE + bar]); 134 } 135 136 void 137 unlockVideo(int slot) 138 { 139 volatile u_int8_t *ppci; 140 141 ppci = (u_int8_t *)PCI_slots[slot].config_addr; 142 ppci[4] = 0x0003; /* enable memory and IO Access */ 143 #if 0 144 ppci[0x10] = 0x00000; /* Turn off memory mapping */ 145 ppci[0x11] = 0x00000; /* mem base = 0 */ 146 ppci[0x12] = 0x00000; 147 ppci[0x13] = 0x00000; 148 #endif 149 __asm__ volatile("eieio"); 150 151 outb(0x3d4, 0x11); 152 outb(0x3d5, 0x0e); /* unlock CR0-CR7 */ 153 } 154 155 int 156 scan_PCI(int start) 157 { 158 int slot, r; 159 struct PCI_cinfo *pslot; 160 int VGAslot = -1; 161 162 for (slot = start + 1; slot < PCI_NSLOTS; slot++) { 163 pslot = &PCI_slots[slot]; 164 for (r = 0; r < PCI_NREGS; r++) 165 pslot->regs[r] = bswap32(pslot->config_addr[r]); 166 if (pslot->regs[DEVID] != 0xffffffff) { 167 /* we have a card */ 168 if (((pslot->regs[CLASS] & 0xffffff00) == 169 0x03000000) || 170 ((pslot->regs[CLASS] & 0xffffff00) == 171 0x00010000)) { 172 /* it's a VGA card */ 173 if ((pslot->regs[CMD] & 0x03)) { 174 /* fW enabled it */ 175 VGAslot = slot; 176 break; 177 } 178 } 179 } 180 } 181 return VGAslot; 182 } 183 184 int 185 PCI_vendor(int slotnum) 186 { 187 struct PCI_cinfo *pslot = &PCI_slots[slotnum]; 188 189 return (pslot->regs[DEVID] & 0xffff); 190 } 191