1
2
3
4
5
6
7
8
9
10
11
12#include <linux/string.h>
13#include <linux/init.h>
14#include <linux/ioport.h>
15#include <asm/addrspace.h>
16#include <asm/errno.h>
17#include <asm/dec/machtype.h>
18#include <asm/dec/tcinfo.h>
19#include <asm/dec/tcmodule.h>
20#include <asm/dec/interrupts.h>
21
22#include <asm/ptrace.h>
23#include <linux/kernel.h>
24#include <linux/module.h>
25
26#define TC_DEBUG
27
28MODULE_LICENSE("GPL");
29slot_info tc_bus[MAX_SLOT];
30static int max_tcslot;
31static tcinfo *info;
32
33unsigned long system_base;
34
35extern void (*dbe_board_handler)(struct pt_regs *regs);
36extern unsigned long *(*rex_slot_address)(int);
37extern void *(*rex_gettcinfo)(void);
38
39
40
41
42
43int search_tc_card(char *name)
44{
45 int slot;
46 slot_info *sip;
47
48 for (slot = 0; slot <= max_tcslot; slot++) {
49 sip = &tc_bus[slot];
50 if ((sip->flags & FREE) && (strncmp(sip->name, name, strlen(name)) == 0)) {
51 return slot;
52 }
53 }
54
55 return -ENODEV;
56}
57
58void 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
68void release_tc_card(int slot)
69{
70 if (tc_bus[slot].flags & FREE) {
71 printk("release_tc_card: attempting to release a card already free\n");
72 return;
73 }
74 tc_bus[slot].flags &= ~IN_USE;
75 tc_bus[slot].flags |= FREE;
76}
77
78unsigned long get_tc_base_addr(int slot)
79{
80 return tc_bus[slot].base_addr;
81}
82
83unsigned long get_tc_irq_nr(int slot)
84{
85 return tc_bus[slot].interrupt;
86}
87
88unsigned long get_tc_speed(void)
89{
90 return 100000 * (10000 / (unsigned long)info->clk_period);
91}
92
93
94
95
96static void __init my_dbe_handler(struct pt_regs *regs)
97{
98 regs->cp0_epc += 4;
99}
100
101static void __init tc_probe(unsigned long startaddr, unsigned long size, int max_slot)
102{
103 int i, slot;
104 long offset;
105 unsigned char *module;
106 void (*old_be_handler)(struct pt_regs *regs);
107
108
109
110 old_be_handler = dbe_board_handler;
111 dbe_board_handler = my_dbe_handler;
112 for (slot = 0; slot <= max_slot; slot++) {
113 module = (char *)(startaddr + slot * size);
114 offset = -1;
115 if (module[OLDCARD + TC_PATTERN0] == 0x55 && module[OLDCARD + TC_PATTERN1] == 0x00
116 && module[OLDCARD + TC_PATTERN2] == 0xaa && module[OLDCARD + TC_PATTERN3] == 0xff)
117 offset = OLDCARD;
118 if (module[TC_PATTERN0] == 0x55 && module[TC_PATTERN1] == 0x00
119 && module[TC_PATTERN2] == 0xaa && module[TC_PATTERN3] == 0xff)
120 offset = 0;
121
122 if (offset != -1) {
123 tc_bus[slot].base_addr = (unsigned long)module;
124 for(i = 0; i < 8; i++) {
125 tc_bus[slot].firmware[i] = module[TC_FIRM_VER + offset + 4 * i];
126 tc_bus[slot].vendor[i] = module[TC_VENDOR + offset + 4 * i];
127 tc_bus[slot].name[i] = module[TC_MODULE + offset + 4 * i];
128 }
129 tc_bus[slot].firmware[8] = 0;
130 tc_bus[slot].vendor[8] = 0;
131 tc_bus[slot].name[8] = 0;
132
133
134
135
136 switch (slot) {
137 case 0:
138 tc_bus[slot].interrupt = TC0;
139 break;
140 case 1:
141 tc_bus[slot].interrupt = TC1;
142 break;
143 case 2:
144 tc_bus[slot].interrupt = TC2;
145 break;
146
147
148
149 case 5:
150 tc_bus[slot].interrupt = SCSI_INT;
151 break;
152 case 6:
153 tc_bus[slot].interrupt = ETHER;
154 break;
155 default:
156 tc_bus[slot].interrupt = -1;
157 break;
158 }
159 }
160 }
161
162 dbe_board_handler = old_be_handler;
163}
164
165
166
167
168void __init tc_init(void)
169{
170 int tc_clock;
171 int i;
172 unsigned long slot0addr;
173 unsigned long slot_size;
174
175 if (!TURBOCHANNEL)
176 return;
177
178 for (i = 0; i < MAX_SLOT; i++) {
179 tc_bus[i].base_addr = 0;
180 tc_bus[i].name[0] = 0;
181 tc_bus[i].vendor[0] = 0;
182 tc_bus[i].firmware[0] = 0;
183 tc_bus[i].interrupt = -1;
184 tc_bus[i].flags = FREE;
185 }
186
187 info = (tcinfo *) rex_gettcinfo();
188 slot0addr = (unsigned long)KSEG1ADDR(rex_slot_address(0));
189
190 switch (mips_machtype) {
191 case MACH_DS5000_200:
192 max_tcslot = 6;
193 break;
194 case MACH_DS5000_1XX:
195 case MACH_DS5000_2X0:
196 max_tcslot = 2;
197 break;
198 case MACH_DS5000_XX:
199 default:
200 max_tcslot = 1;
201 break;
202 }
203
204 tc_clock = 10000 / info->clk_period;
205
206 if (TURBOCHANNEL && info->slot_size && slot0addr) {
207 printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision,
208 tc_clock / 10, tc_clock % 10);
209 printk("(with%s parity)\n", info->parity ? "" : "out");
210
211 slot_size = info->slot_size << 20;
212
213 tc_probe(slot0addr, slot_size, max_tcslot);
214
215
216
217
218
219
220 if(mips_machtype == MACH_DS5000_XX)
221 i = 2;
222 else
223 i = 1;
224
225 system_base = slot0addr + slot_size * (max_tcslot + i);
226
227#ifdef TC_DEBUG
228 for (i = 0; i <= max_tcslot; i++)
229 if (tc_bus[i].base_addr) {
230 printk(" slot %d: ", i);
231 printk("%s %s %s\n", tc_bus[i].vendor,
232 tc_bus[i].name, tc_bus[i].firmware);
233 }
234#endif
235 ioport_resource.end = KSEG2 - 1;
236 }
237}
238
239subsys_initcall(tc_init);
240
241EXPORT_SYMBOL(search_tc_card);
242EXPORT_SYMBOL(claim_tc_card);
243EXPORT_SYMBOL(release_tc_card);
244EXPORT_SYMBOL(get_tc_base_addr);
245EXPORT_SYMBOL(get_tc_irq_nr);
246EXPORT_SYMBOL(get_tc_speed);
247
248