1 /*
2 * (C) Copyright 2003
3 *
4 * Thomas Frieden (ThomasF@hyperion-entertainment.com)
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 *
24 */
25 #include <common.h>
26 #include <asm/processor.h>
27 #include <asm/string.h>
28 #include <devices.h>
29 #include <pci.h>
30 #include "memio.h"
31 #include "catweasel.h"
32 #include "cw4.h"
33 #include "../menu/menu.h"
34
35 #define CATW_PCI_VENDOR 0xe159
36 #define CATW_PCI_PRODUCT 0x0001
37
38 #define CATW4_SUBSYS_VENDOR 0x5213
39 #define CATW4_SUBSYS_ID1 0x0002
40 #define CATW4_SUBSYS_ID2 0x0003
41
42 #define CATW_KEY_DATA 0xd0
43 #define CATW_KEY_STATUS 0xd4
44
45 #define CATW_KS_READY 0x80
46
47 #define CATW_NAME "amikbd"
48
49 #define CATW4_FILEID FileID('C','A','T','4')
50
51 #undef CATW_DEBUG
52 #ifdef CATW_DEBUG
53 #define dprintf(fmt,args...) printf (fmt ,##args)
54 #else
55 #define dprintf(fmt,args...)
56 #endif
57
58 int catw_getc(void);
59 int catw_testc(void);
60
61 static int catw_pci = -1;
62 static unsigned long catw_iobase = 0;
63
64 static int catw_poll_delay = 20000;
65
66 static char catw_shift_state = 0;
67
68 static unsigned char catw_normal_xlate[0x70] =
69 { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
70 /* 00 - 0F */ '`','1','2','3','4','5','6','7','8','9','0','�','\'','\\',0, '0',
71 /* 10 - 1F */ 'q','w','e','r','t','z','u','i','o','p','�','+', 0 ,'1','2','3',
72 /* 20 - 2F */ 'a','s','d','f','g','h','j','k','l','�','�','#', 0 ,'4','5','6',
73 /* 30 - 3F */ '<','y','x','c','v','b','n','m',',','.','-', 0 , 0 ,'7','8','9',
74 /* 40 - 4F */ ' ', 8 , 9 , 13, 13, 27,127, 0 , 0 , 0 ,'-', 0 , 0 , 0 , 0 , 0 ,
75 /* 50 - 5F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,'[',']','/','*','+', 0 ,
76 /* 60 - 6F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
77 };
78
79 static unsigned char catw_shifted_xlate[0x70] =
80 { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
81 /* 00 - 0F */ '~','!','"','�','$','%','&','/','(',')','=','?','`','|', 0, '0',
82 /* 10 - 1F */ 'Q','W','E','R','T','Z','U','I','O','P','�','*', 0 ,'1','2','3',
83 /* 20 - 2F */ 'A','S','D','F','G','H','J','K','L','�','�','^', 0 ,'4','5','6',
84 /* 30 - 3F */ '>','Y','X','C','V','B','N','M',';',':','_', 0 , 0 ,'7','8','9',
85 /* 40 - 4F */ ' ', 8 , 9 , 13, 13, 27,127, 0 , 0 , 0 ,'-', 0 , 0 , 0 , 0 , 0 ,
86 /* 50 - 5F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,'{','}','/','*','+', 0 ,
87 /* 60 - 6F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
88 };
89
90 //"
91
92 #define CATW_BUFFER_SIZE 20
93 static unsigned char catw_buffer[CATW_BUFFER_SIZE];
94 static int catw_inptr = 0, catw_outptr = 0;
95
catw_handle(int c)96 void catw_handle(int c)
97 {
98 int kup = (c&0x80);
99 int key = (c&0x7f);
100
101 switch (key)
102 {
103 case 0x60:
104 case 0x61:
105 case 0x62:
106 if (kup)
107 catw_shift_state = 0;
108 else
109 catw_shift_state = 1;
110 break;
111 case 0x78:
112 /* Reset */
113 dprintf("Reset!\n");
114 break;
115 }
116 }
117
catw_xlate(int c)118 int catw_xlate(int c)
119 {
120 c &= 0x7f;
121
122 switch(c)
123 {
124 case 0x4C:
125 return KEY_PREV_ITEM;
126 case 0x4D:
127 return KEY_NEXT_ITEM;
128 case 0x4E:
129 return KEY_NEXT_OPTION;
130 case 0x4F:
131 return KEY_PREV_OPTION;
132 default:
133 if (catw_shift_state)
134 return catw_shifted_xlate[c];
135 else
136 return catw_normal_xlate[c];
137 }
138 }
139
catw_fpga_ready(void)140 static int catw_fpga_ready(void)
141 {
142 if ((in_byte(catw_iobase + 0x07) & 8) == 8) return 1;
143 else return 0;
144 }
145
catw_config_done(void)146 static int catw_config_done(void)
147 {
148 if ((in_byte(catw_iobase + 0x07) & 4) == 4) return 1;
149 else return 0;
150 }
151
catw_reset_fpga(void)152 static void catw_reset_fpga(void)
153 {
154 dprintf("Resetting fpga...\n");
155 out_byte(catw_iobase + 0x02, 227);
156 out_byte(catw_iobase + 0x03, 0);
157 udelay(1000);
158 out_byte(catw_iobase + 0x03, 65);
159 dprintf("Done\n");
160 }
161
catw_get_config(uint32 * size)162 static void *catw_get_config(uint32 *size)
163 {
164 *size = 59215;
165 return &cw4[0];
166 }
167
catw_program_fpga_config(void)168 static int catw_program_fpga_config(void)
169 {
170 uint32 length;
171 uint8 b;
172 int i;
173 int try;
174 uint8 *config = (uint8*)catw_get_config(&length);
175
176 if (!config)
177 {
178 dprintf("Couldn't find core config\n");
179 return 0;
180 }
181
182 #ifdef CATW_DEBUG
183 dprintf("Found a config string of %d bytes\n", length);
184 dprintf("starting with...\n");
185 {
186 int i;
187 for (i=0; i<40; i++)
188 {
189 dprintf("%02x ", *(config+i));
190 }
191 dprintf("\n");
192 dprintf("...\n");
193
194 for (i=0; i<40; i++)
195 {
196 dprintf("%02x ", *(config+length-40+i));
197 }
198 dprintf("\n");
199 }
200 #endif
201
202 for (i=0; i<length-1; i++)
203 {
204 b = *(config+i);
205 try = 0;
206
207 if ((b & 0x01) == 0x01)
208 out_byte(catw_iobase + 0x03, 0x43);
209 else
210 out_byte(catw_iobase + 0x03, 0x41);
211
212 while (catw_fpga_ready() == 0)
213 {
214 udelay(2000);
215 try++;
216 dprintf("waiting for FPGA (try = %d)\n", try);
217 if (try == 10)
218 {
219 dprintf("PANIC: FPGA failed on catw_fpga_ready()\n");
220 dprintf("at byte offset %d\n", i);
221 dprintf("byte written was %02x\n", b);
222 return 0;
223 }
224 }
225
226 out_byte(catw_iobase + 0xc0, b);
227 }
228
229 return 1;
230 }
231
232
catw_kb_init(void)233 int catw_kb_init(void)
234 {
235 int i;
236 device_t catw_kbddev;
237 int error;
238 char *s;
239 uint16 subsys_vendor, subsys_device;
240
241 /* Some init */
242 catw_shift_state = 0;
243
244 /* Find the device */
245 catw_pci = pci_find_device(CATW_PCI_VENDOR, CATW_PCI_PRODUCT, 0);
246 if (catw_pci == -1)
247 {
248 dprintf("No Catweasel controller (0x%0x4, 0x%04x) attached\n", CATW_PCI_VENDOR, CATW_PCI_PRODUCT);
249 return -1;
250 }
251
252 /* Get IO base */
253 for (i = 0; i < 6; i++)
254 {
255 pci_read_config_dword(catw_pci, PCI_BASE_ADDRESS_0+4*i, (u32 *)&catw_iobase);
256 if (catw_iobase & 1)
257 {
258 /* Found the IO base */
259 break;
260 }
261 }
262
263 /* Check the iobase */
264 if (catw_iobase & 1)
265 {
266 catw_iobase &= ~1;
267 dprintf("I/O base: %p\n", (u32 *)catw_iobase);
268 }
269 else
270 {
271 printf("Error: Unable to find I/O address range\n");
272 return -1;
273 }
274
275 pci_read_config_word(catw_pci, PCI_SUBSYSTEM_VENDOR_ID, &subsys_vendor);
276 pci_read_config_word(catw_pci, PCI_SUBSYSTEM_ID, &subsys_device);
277
278 if (subsys_vendor == CATW4_SUBSYS_VENDOR &&
279 ((subsys_device == CATW4_SUBSYS_ID1) || (subsys_device == CATW4_SUBSYS_ID1)))
280 {
281 dprintf("Catweasel Mark IV detected\n");
282 /* Send Mark IV initialisation sequence */
283 out_byte(catw_iobase + 0x00, 0xF1);
284 out_byte(catw_iobase + 0x01, 0x00);
285 out_byte(catw_iobase + 0x02, 0xE3);
286 out_byte(catw_iobase + 0x03, 0x41);
287 out_byte(catw_iobase + 0x04, 0x00);
288 out_byte(catw_iobase + 0x05, 0x00);
289 out_byte(catw_iobase + 0x29, 0x00);
290 out_byte(catw_iobase + 0x2B, 0x00);
291
292 #ifdef CATW_DEBUG
293 if (catw_config_done())
294 dprintf("FPGA already configured\n");
295 else
296 dprintf("FPGA Empty\n");
297 #endif
298
299 catw_reset_fpga();
300 if (catw_config_done())
301 {
302 printf("**PANIC** FPGA reset failed\n");
303 return -1;
304 }
305 #ifdef CATW_DEBUG
306 else
307 {
308 dprintf("FPGA reset OK\n");
309 }
310 #endif
311
312 if (0 == catw_program_fpga_config())
313 {
314 printf("**ERROR** FPGA Programming failed\n");
315 return -1;
316 }
317
318 if (catw_config_done())
319 {
320 printf("Catweasel Mark IV configured\n\n");
321 }
322 else
323 {
324 printf("**ERROR** Catweasel Mark IV configuration failed\n");
325 return -1;
326 }
327 udelay(1000);
328 }
329 /* Catweasel mark III cannot work on Sam
330 * it's a +5V only PCI card...
331 else
332 {
333 dprintf("Catweasel Mark III detected\n");
334 // Send initialisation sequence for Mark III
335 out_byte(catw_iobase + 0x00, 0xf1);
336 out_byte(catw_iobase + 0x01, 0x00);
337 out_byte(catw_iobase + 0x02, 0x00);
338 out_byte(catw_iobase + 0x04, 0x00);
339 out_byte(catw_iobase + 0x05, 0x00);
340 out_byte(catw_iobase + 0x29, 0x00);
341 out_byte(catw_iobase + 0x2b, 0x00);
342 }
343 */
344
345 out_byte(catw_iobase + CATW_KEY_DATA, 0);
346
347 /* Register us as a possible keyboard device */
348 memset(&catw_kbddev, 0, sizeof(catw_kbddev));
349 strcpy(catw_kbddev.name, CATW_NAME);
350 catw_kbddev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
351 catw_kbddev.putc = NULL;
352 catw_kbddev.puts = NULL;
353 catw_kbddev.getc = catw_getc;
354 catw_kbddev.tstc = catw_testc;
355
356 s = getenv("catw_poll_delay");
357 if (s)
358 {
359 catw_poll_delay = simple_strtol(s, NULL, 0) * 1000;
360 }
361
362 error = device_register(&catw_kbddev);
363 if (0 == error )
364 {
365 /* Check if we are stdin */
366 if (0 == strcmp(getenv("stdin"), CATW_NAME))
367 {
368 if (overwrite_console())
369 return 1;
370
371 error = console_assign(stdin,CATW_NAME);
372 if (0 == error)
373 {
374 dprintf("Catweasel keyboard initialized 1\n");
375 return 1;
376 }
377 else
378 {
379 dprintf("Catweasel keyboard initialized 2\n");
380 return error;
381 }
382 }
383
384 dprintf("Catweasel keyboard initialized 3\n");
385 return 1;
386 }
387
388 return error;
389 }
390
catw_push(unsigned char c)391 static void catw_push(unsigned char c)
392 {
393 if (catw_inptr == CATW_BUFFER_SIZE-1)
394 {
395 if (catw_outptr == 0) return;
396 catw_inptr = 0;
397 }
398 else if (catw_inptr + 1 == catw_outptr)
399 {
400 return;
401 }
402
403 catw_buffer[++catw_inptr] = c;
404 }
405
catw_pop(void)406 static int catw_pop(void)
407 {
408 if (catw_inptr == catw_outptr) return -1;
409 if (catw_outptr >= CATW_BUFFER_SIZE-1)
410 catw_outptr = 0;
411 else
412 ++catw_outptr;
413
414 return (int)catw_buffer[catw_outptr];
415 }
416
catw_poll(void)417 static void catw_poll(void)
418 {
419 int x;
420
421 x = in_byte(catw_iobase + CATW_KEY_STATUS);
422
423 if (x & CATW_KS_READY)
424 {
425 x = in_byte(catw_iobase + CATW_KEY_DATA);
426 dprintf("got char: %x\n", x);
427 catw_handle(x);
428
429 if (!(x&0x80))
430 {
431 x = catw_xlate(x);
432 if (x)
433 {
434 dprintf("xlate: %x\n", x);
435 catw_push((unsigned char)x);
436 }
437 }
438 udelay(1000);
439 out_byte(catw_iobase + CATW_KEY_DATA, 0);
440 }
441 }
442
catw_getc(void)443 int catw_getc(void)
444 {
445 int c;
446
447 do
448 {
449 udelay(catw_poll_delay);
450 catw_poll();
451 c = catw_pop();
452 } while (c == -1);
453
454 return c;
455 }
456
457 unsigned long long get_ticks(void);
458 unsigned long ticks2usec(unsigned long ticks);
459
catw_testc(void)460 int catw_testc(void)
461 {
462 catw_poll();
463 if (catw_inptr == catw_outptr) return 0;
464 else return 1;
465 }
466