Import 2.3.9pre5
[davej-history.git] / drivers / tc / tc.c
blobc5e3d4c6bf0b131b53ef41b396d4a2836f635c91
1 /* $Id: $
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.
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.
10 * Copyright (c) Harald Koerfgen, 1998
14 #include <linux/string.h>
15 #include <asm/init.h>
16 #include <asm/addrspace.h>
17 #include <asm/errno.h>
18 #include <asm/dec/machtype.h>
19 #include <asm/dec/tcinfo.h>
20 #include <asm/dec/tcmodule.h>
21 #include <asm/dec/interrupts.h>
23 #include <asm/ptrace.h>
24 #include <linux/kernel.h>
26 #define TC_DEBUG
28 slot_info tc_bus[MAX_SLOT];
29 static int max_tcslot = 0;
30 static tcinfo *info = (tcinfo *)0;
32 unsigned long system_base = 0;
34 extern void (*dbe_board_handler)(struct pt_regs *regs);
35 extern unsigned long *(*rex_slot_address)(int);
36 extern void *(*rex_gettcinfo)(void);
39 * Interface to the world. Read comment in include/asm-mips/tc.h.
42 int search_tc_card(char *name)
44 int slot;
45 slot_info *sip;
47 for (slot = 0; slot <= max_tcslot; slot++) {
48 sip = &tc_bus[slot];
49 if ((sip->flags & FREE) && (strncmp(sip->name, name, strlen(name)) == 0)) {
50 return slot;
54 return -ENODEV;
57 void claim_tc_card(int slot)
59 if (tc_bus[slot].flags & IN_USE) {
60 printk("claim_tc_card: attempting to claim a card already in use\n");
61 return;
63 tc_bus[slot].flags &= ~FREE;
64 tc_bus[slot].flags |= IN_USE;
67 void release_tc_card(int slot)
69 if (tc_bus[slot].flags & FREE) {
70 printk("release_tc_card: attempting to release a card already free\n");
71 return;
73 tc_bus[slot].flags &= ~IN_USE;
74 tc_bus[slot].flags |= FREE;
77 unsigned long get_tc_base_addr(int slot)
79 return tc_bus[slot].base_addr;
82 unsigned long get_tc_irq_nr(int slot)
84 return tc_bus[slot].interrupt;
87 unsigned long get_tc_speed(void)
89 return 100000 * (10000 / (unsigned long)info->clk_period);
93 * Probing for TURBOchannel modules
95 __initfunc(static void my_dbe_handler(struct pt_regs *regs))
97 regs->cp0_epc += 4;
100 __initfunc(static void tc_probe(unsigned long startaddr, unsigned long size, int max_slot))
102 int i, slot;
103 long offset;
104 unsigned char *module;
105 void (*old_be_handler)(struct pt_regs *regs);
107 /* Install our exception handler temporarily */
109 old_be_handler = dbe_board_handler;
110 dbe_board_handler = my_dbe_handler;
111 for (slot = 0; slot <= max_slot; slot++) {
112 module = (char *)(startaddr + slot * size);
113 offset = -1;
114 if (module[OLDCARD + PATTERN0] == 0x55 && module[OLDCARD + PATTERN1] == 0x00
115 && module[OLDCARD + PATTERN2] == 0xaa && module[OLDCARD + PATTERN3] == 0xff)
116 offset = OLDCARD;
117 if (module[PATTERN0] == 0x55 && module[PATTERN1] == 0x00
118 && module[PATTERN2] == 0xaa && module[PATTERN3] == 0xff)
119 offset = 0;
121 if (offset != -1) {
122 tc_bus[slot].base_addr = (unsigned long)module;
123 for(i = 0; i < 8; i++) {
124 tc_bus[slot].firmware[i] = module[FIRM_VER + offset + 4 * i];
125 tc_bus[slot].vendor[i] = module[VENDOR + offset + 4 * i];
126 tc_bus[slot].name[i] = module[MODULE + offset + 4 * i];
128 tc_bus[slot].firmware[8] = 0;
129 tc_bus[slot].vendor[8] = 0;
130 tc_bus[slot].name[8] = 0;
132 * Looks unneccesary, but we may change
133 * TC? in the future
135 switch (slot) {
136 case 0:
137 tc_bus[slot].interrupt = TC0;
138 break;
139 case 1:
140 tc_bus[slot].interrupt = TC1;
141 break;
142 case 2:
143 tc_bus[slot].interrupt = TC2;
144 break;
146 * Yuck! DS5000/200 onboard devices
148 case 5:
149 tc_bus[slot].interrupt = SCSI_INT;
150 break;
151 case 6:
152 tc_bus[slot].interrupt = ETHER;
153 break;
154 default:
155 tc_bus[slot].interrupt = -1;
156 break;
161 dbe_board_handler = old_be_handler;
165 * the main entry
167 __initfunc(void tc_init(void))
169 int tc_clock;
170 int i;
171 unsigned long slot0addr;
172 unsigned long slot_size;
174 if (!TURBOCHANNEL)
175 return;
177 for (i = 0; i < MAX_SLOT; i++) {
178 tc_bus[i].base_addr = 0;
179 tc_bus[i].name[0] = 0;
180 tc_bus[i].vendor[0] = 0;
181 tc_bus[i].firmware[0] = 0;
182 tc_bus[i].interrupt = -1;
183 tc_bus[i].flags = FREE;
186 info = (tcinfo *) rex_gettcinfo();
187 slot0addr = (unsigned long)KSEG1ADDR(rex_slot_address(0));
189 switch (mips_machtype) {
190 case MACH_DS5000_200:
191 max_tcslot = 6;
192 break;
193 case MACH_DS5000_1XX:
194 case MACH_DS5000_2X0:
195 max_tcslot = 2;
196 break;
197 case MACH_DS5000_XX:
198 default:
199 max_tcslot = 1;
200 break;
203 tc_clock = 10000 / info->clk_period;
205 if (TURBOCHANNEL && info->slot_size && slot0addr) {
206 printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision,
207 tc_clock / 10, tc_clock % 10);
208 printk("(%sparity)\n", info->parity ? "" : "no ");
210 slot_size = info->slot_size << 20;
212 tc_probe(slot0addr, slot_size, max_tcslot);
215 * All TURBOchannel DECstations have the onboard devices
216 * where the (max_tcslot + 1 or 2 on DS5k/xx) Option Module
217 * would be.
219 if(mips_machtype == MACH_DS5000_XX)
220 i = 2;
221 else
222 i = 1;
224 system_base = slot0addr + slot_size * (max_tcslot + i);
226 #ifdef TC_DEBUG
227 for (i = 0; i <= max_tcslot; i++)
228 if (tc_bus[i].base_addr) {
229 printk(" slot %d: ", i);
230 printk("%s %s %s\n", tc_bus[i].vendor,
231 tc_bus[i].name, tc_bus[i].firmware);
233 #endif