1 /* 2 * tc-init: We assume the TURBOchannel to be up and running so 3 * just probe for Modules and fill in the global data structure 4 * tc_bus. 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 * 10 * Copyright (c) Harald Koerfgen, 1998 11 * Copyright (c) 2001, 2003 Maciej W. Rozycki 12 */ 13 #include <linux/string.h> 14 #include <linux/init.h> 15 #include <linux/ioport.h> 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 19 #include <asm/addrspace.h> 20 #include <asm/errno.h> 21 #include <asm/dec/machtype.h> 22 #include <asm/dec/prom.h> 23 #include <asm/dec/tcinfo.h> 24 #include <asm/dec/tcmodule.h> 25 #include <asm/dec/interrupts.h> 26 #include <asm/paccess.h> 27 #include <asm/ptrace.h> 28 29 #define TC_DEBUG 30 31 MODULE_LICENSE("GPL"); 32 slot_info tc_bus[MAX_SLOT]; 33 static int num_tcslots; 34 static tcinfo *info; 35 36 unsigned long system_base; 37 38 /* 39 * Interface to the world. Read comment in include/asm-mips/tc.h. 40 */ 41 42 int search_tc_card(const char *name) 43 { 44 int slot; 45 slot_info *sip; 46 47 for (slot = 0; slot < num_tcslots; slot++) { 48 sip = &tc_bus[slot]; 49 if ((sip->flags & FREE) && 50 (strncmp(sip->name, name, strlen(name)) == 0)) { 51 return slot; 52 } 53 } 54 55 return -ENODEV; 56 } 57 58 void claim_tc_card(int slot) 59 { 60 if (tc_bus[slot].flags & IN_USE) { 61 printk("claim_tc_card: attempting to claim a card already in use\n"); 62 return; 63 } 64 tc_bus[slot].flags &= ~FREE; 65 tc_bus[slot].flags |= IN_USE; 66 } 67 68 void release_tc_card(int slot) 69 { 70 if (tc_bus[slot].flags & FREE) { 71 printk("release_tc_card: " 72 "attempting to release a card already free\n"); 73 return; 74 } 75 tc_bus[slot].flags &= ~IN_USE; 76 tc_bus[slot].flags |= FREE; 77 } 78 79 unsigned long get_tc_base_addr(int slot) 80 { 81 return tc_bus[slot].base_addr; 82 } 83 84 unsigned long get_tc_irq_nr(int slot) 85 { 86 return tc_bus[slot].interrupt; 87 } 88 89 unsigned long get_tc_speed(void) 90 { 91 return 100000 * (10000 / (unsigned long)info->clk_period); 92 } 93 94 /* 95 * Probing for TURBOchannel modules 96 */ 97 static void __init tc_probe(unsigned long startaddr, unsigned long size, 98 int slots) 99 { 100 int i, slot, err; 101 long offset; 102 unsigned char pattern[4]; 103 unsigned char *module; 104 105 for (slot = 0; slot < slots; slot++) { 106 module = (char *)(startaddr + slot * size); 107 108 offset = OLDCARD; 109 110 err = 0; 111 err |= get_dbe(pattern[0], module + OLDCARD + TC_PATTERN0); 112 err |= get_dbe(pattern[1], module + OLDCARD + TC_PATTERN1); 113 err |= get_dbe(pattern[2], module + OLDCARD + TC_PATTERN2); 114 err |= get_dbe(pattern[3], module + OLDCARD + TC_PATTERN3); 115 if (err) 116 continue; 117 118 if (pattern[0] != 0x55 || pattern[1] != 0x00 || 119 pattern[2] != 0xaa || pattern[3] != 0xff) { 120 offset = NEWCARD; 121 122 err = 0; 123 err |= get_dbe(pattern[0], module + TC_PATTERN0); 124 err |= get_dbe(pattern[1], module + TC_PATTERN1); 125 err |= get_dbe(pattern[2], module + TC_PATTERN2); 126 err |= get_dbe(pattern[3], module + TC_PATTERN3); 127 if (err) 128 continue; 129 } 130 131 if (pattern[0] != 0x55 || pattern[1] != 0x00 || 132 pattern[2] != 0xaa || pattern[3] != 0xff) 133 continue; 134 135 tc_bus[slot].base_addr = (unsigned long)module; 136 for(i = 0; i < 8; i++) { 137 tc_bus[slot].firmware[i] = 138 module[TC_FIRM_VER + offset + 4 * i]; 139 tc_bus[slot].vendor[i] = 140 module[TC_VENDOR + offset + 4 * i]; 141 tc_bus[slot].name[i] = 142 module[TC_MODULE + offset + 4 * i]; 143 } 144 tc_bus[slot].firmware[8] = 0; 145 tc_bus[slot].vendor[8] = 0; 146 tc_bus[slot].name[8] = 0; 147 /* 148 * Looks unneccesary, but we may change 149 * TC? in the future 150 */ 151 switch (slot) { 152 case 0: 153 tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC0]; 154 break; 155 case 1: 156 tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC1]; 157 break; 158 case 2: 159 tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC2]; 160 break; 161 /* 162 * Yuck! DS5000/200 onboard devices 163 */ 164 case 5: 165 tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC5]; 166 break; 167 case 6: 168 tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC6]; 169 break; 170 default: 171 tc_bus[slot].interrupt = -1; 172 break; 173 } 174 } 175 } 176 177 /* 178 * the main entry 179 */ 180 void __init tc_init(void) 181 { 182 int tc_clock; 183 int i; 184 unsigned long slot0addr; 185 unsigned long slot_size; 186 187 if (!TURBOCHANNEL) 188 return; 189 190 for (i = 0; i < MAX_SLOT; i++) { 191 tc_bus[i].base_addr = 0; 192 tc_bus[i].name[0] = 0; 193 tc_bus[i].vendor[0] = 0; 194 tc_bus[i].firmware[0] = 0; 195 tc_bus[i].interrupt = -1; 196 tc_bus[i].flags = FREE; 197 } 198 199 info = (tcinfo *) rex_gettcinfo(); 200 slot0addr = (unsigned long)KSEG1ADDR(rex_slot_address(0)); 201 202 switch (mips_machtype) { 203 case MACH_DS5000_200: 204 num_tcslots = 7; 205 break; 206 case MACH_DS5000_1XX: 207 case MACH_DS5000_2X0: 208 case MACH_DS5900: 209 num_tcslots = 3; 210 break; 211 case MACH_DS5000_XX: 212 default: 213 num_tcslots = 2; 214 break; 215 } 216 217 tc_clock = 10000 / info->clk_period; 218 219 if (TURBOCHANNEL && info->slot_size && slot0addr) { 220 printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision, 221 tc_clock / 10, tc_clock % 10); 222 printk("(with%s parity)\n", info->parity ? "" : "out"); 223 224 slot_size = info->slot_size << 20; 225 226 tc_probe(slot0addr, slot_size, num_tcslots); 227 228 /* 229 * All TURBOchannel DECstations have the onboard devices 230 * where the (num_tcslots + 0 or 1 on DS5k/xx) Option Module 231 * would be. 232 */ 233 if(mips_machtype == MACH_DS5000_XX) 234 i = 1; 235 else 236 i = 0; 237 238 system_base = slot0addr + slot_size * (num_tcslots + i); 239 240 #ifdef TC_DEBUG 241 for (i = 0; i < num_tcslots; i++) 242 if (tc_bus[i].base_addr) { 243 printk(" slot %d: ", i); 244 printk("%s %s %s\n", tc_bus[i].vendor, 245 tc_bus[i].name, tc_bus[i].firmware); 246 } 247 #endif 248 ioport_resource.end = KSEG2 - 1; 249 } 250 } 251 252 subsys_initcall(tc_init); 253 254 EXPORT_SYMBOL(search_tc_card); 255 EXPORT_SYMBOL(claim_tc_card); 256 EXPORT_SYMBOL(release_tc_card); 257 EXPORT_SYMBOL(get_tc_base_addr); 258 EXPORT_SYMBOL(get_tc_irq_nr); 259 EXPORT_SYMBOL(get_tc_speed); 260 EXPORT_SYMBOL(system_base); 261