v2.4.8 -> v2.4.8.1
[opensuse:kernel.git] / arch / ppc / kernel / apus_setup.c
1 /*
2  * BK Id: SCCS/s.apus_setup.c 1.14 07/06/01 09:19:28 trini
3  */
4 /*
5  *  linux/arch/ppc/kernel/apus_setup.c
6  *
7  *  Copyright (C) 1998, 1999  Jesper Skov
8  *
9  *  Basically what is needed to replace functionality found in
10  *  arch/m68k allowing Amiga drivers to work under APUS.
11  *  Bits of code and/or ideas from arch/m68k and arch/ppc files.
12  *
13  * TODO:
14  *  This file needs a *really* good cleanup. Restructure and optimize.
15  *  Make sure it can be compiled for non-APUS configs. Begin to move
16  *  Amiga specific stuff into mach/amiga.
17  */
18
19 #include <linux/config.h>
20 #include <linux/types.h>
21 #include <linux/kernel.h>
22 #include <linux/sched.h>
23 #include <linux/kd.h>
24 #include <linux/init.h>
25 #include <linux/hdreg.h>
26 #include <linux/blk.h>
27 #include <linux/pci.h>
28
29 #ifdef CONFIG_APUS
30 #include <asm/logging.h>
31 #endif
32
33 /* Needs INITSERIAL call in head.S! */
34 #undef APUS_DEBUG
35
36
37 #include <linux/ide.h>
38 #define T_CHAR          (0x0000)        /* char:  don't touch  */
39 #define T_SHORT         (0x4000)        /* short: 12 -> 21     */
40 #define T_INT           (0x8000)        /* int:   1234 -> 4321 */
41 #define T_TEXT          (0xc000)        /* text:  12 -> 21     */
42
43 #define T_MASK_TYPE     (0xc000)
44 #define T_MASK_COUNT    (0x3fff)
45
46 #define D_CHAR(cnt)     (T_CHAR  | (cnt))
47 #define D_SHORT(cnt)    (T_SHORT | (cnt))
48 #define D_INT(cnt)      (T_INT   | (cnt))
49 #define D_TEXT(cnt)     (T_TEXT  | (cnt))
50
51 static u_short driveid_types[] = {
52         D_SHORT(10),    /* config - vendor2 */
53         D_TEXT(20),     /* serial_no */
54         D_SHORT(3),     /* buf_type, buf_size - ecc_bytes */
55         D_TEXT(48),     /* fw_rev - model */
56         D_CHAR(2),      /* max_multsect - vendor3 */
57         D_SHORT(1),     /* dword_io */
58         D_CHAR(2),      /* vendor4 - capability */
59         D_SHORT(1),     /* reserved50 */
60         D_CHAR(4),      /* vendor5 - tDMA */
61         D_SHORT(4),     /* field_valid - cur_sectors */
62         D_INT(1),       /* cur_capacity */
63         D_CHAR(2),      /* multsect - multsect_valid */
64         D_INT(1),       /* lba_capacity */
65         D_SHORT(194)    /* dma_1word - reservedyy */
66 };
67
68 #define num_driveid_types       (sizeof(driveid_types)/sizeof(*driveid_types))
69
70 #include <asm/bootinfo.h>
71 #include <asm/setup.h>
72 #include <asm/amigahw.h>
73 #include <asm/amigaints.h>
74 #include <asm/amigappc.h>
75 #include <asm/pgtable.h>
76 #include <asm/io.h>
77 #include <asm/dma.h>
78 #include <asm/machdep.h>
79 #include <asm/init.h>
80
81 #include "local_irq.h"
82
83 unsigned long m68k_machtype;
84 char debug_device[6] = "";
85
86 extern void amiga_init_IRQ(void);
87
88 void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
89 /* machine dependent keyboard functions */
90 int (*mach_keyb_init) (void) __initdata = NULL;
91 int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
92 void (*mach_kbd_leds) (unsigned int) = NULL;
93 /* machine dependent irq functions */
94 void (*mach_init_IRQ) (void) __initdata = NULL;
95 void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
96 void (*mach_get_model) (char *model) = NULL;
97 int (*mach_get_hardware_list) (char *buffer) = NULL;
98 int (*mach_get_irq_list) (char *) = NULL;
99 void (*mach_process_int) (int, struct pt_regs *) = NULL;
100 /* machine dependent timer functions */
101 unsigned long (*mach_gettimeoffset) (void);
102 void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
103 int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
104 int (*mach_set_clock_mmss) (unsigned long) = NULL;
105 void (*mach_reset)( void );
106 long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
107 #if defined(CONFIG_AMIGA_FLOPPY)
108 void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
109 void (*mach_floppy_eject) (void) = NULL;
110 #endif
111 #ifdef CONFIG_HEARTBEAT
112 void (*mach_heartbeat) (int) = NULL;
113 extern void apus_heartbeat (void);
114 #endif
115
116 extern unsigned long amiga_model;
117 extern unsigned decrementer_count;/* count value for 1e6/HZ microseconds */
118 extern unsigned count_period_num; /* 1 decrementer count equals */
119 extern unsigned count_period_den; /* count_period_num / count_period_den us */
120
121 int num_memory = 0;
122 struct mem_info memory[NUM_MEMINFO];/* memory description */
123 /* FIXME: Duplicate memory data to avoid conflicts with m68k shared code. */
124 int m68k_realnum_memory = 0;
125 struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
126
127 struct mem_info ramdisk;
128
129 extern void amiga_floppy_setup(char *, int *);
130 extern void config_amiga(void);
131
132 static int __60nsram = 0;
133
134 /* for cpuinfo */
135 static int __bus_speed = 0;
136 static int __speed_test_failed = 0;
137
138 /********************************************** COMPILE PROTECTION */
139 /* Provide some stubs that links to Amiga specific functions. 
140  * This allows CONFIG_APUS to be removed from generic PPC files while
141  * preventing link errors for other PPC targets.
142  */
143 unsigned long apus_get_rtc_time(void)
144 {
145 #ifdef CONFIG_APUS
146         extern unsigned long m68k_get_rtc_time(void);
147         
148         return m68k_get_rtc_time ();
149 #else
150         return 0;
151 #endif
152 }
153
154 int apus_set_rtc_time(unsigned long nowtime)
155 {
156 #ifdef CONFIG_APUS
157         extern int m68k_set_rtc_time(unsigned long nowtime);
158
159         return m68k_set_rtc_time (nowtime);
160 #else
161         return 0;
162 #endif
163 }
164
165
166
167 /* Here some functions we don't support, but which the other ports reference */
168 int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
169 {
170         printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
171         return 0; 
172 }
173 int pckbd_getkeycode(unsigned int scancode) 
174
175         printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
176         return 0; 
177 }
178 int pckbd_translate(unsigned char scancode, unsigned char *keycode,
179                     char raw_mode) 
180 {
181         printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
182         return 0; 
183 }
184 char pckbd_unexpected_up(unsigned char keycode)
185 {
186         printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
187         return 0;
188 }
189 void pckbd_leds(unsigned char leds)
190 {
191         printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
192 }
193 void pckbd_init_hw(void)
194 {
195         printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
196 }
197 unsigned char pckbd_sysrq_xlate[128];
198
199 struct pci_bus * __init pci_scan_peer_bridge(int bus)
200 {
201         printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
202         return NULL;
203 }
204
205 /*********************************************************** SETUP */
206 /* From arch/m68k/kernel/setup.c. */
207 void __init apus_setup_arch(void)
208 {
209 #ifdef CONFIG_APUS
210         extern char cmd_line[];
211         int i;
212         char *p, *q;
213
214         /* Let m68k-shared code know it should do the Amiga thing. */
215         m68k_machtype = MACH_AMIGA;
216
217         /* Parse the command line for arch-specific options.
218          * For the m68k, this is currently only "debug=xxx" to enable printing
219          * certain kernel messages to some machine-specific device.  */
220         for( p = cmd_line; p && *p; ) {
221             i = 0;
222             if (!strncmp( p, "debug=", 6 )) {
223                     strncpy( debug_device, p+6, sizeof(debug_device)-1 );
224                     debug_device[sizeof(debug_device)-1] = 0;
225                     if ((q = strchr( debug_device, ' ' ))) *q = 0;
226                     i = 1;
227             } else if (!strncmp( p, "60nsram", 7 )) {
228                     APUS_WRITE (APUS_REG_WAITSTATE, 
229                                 REGWAITSTATE_SETRESET
230                                 |REGWAITSTATE_PPCR
231                                 |REGWAITSTATE_PPCW);
232                     __60nsram = 1;
233                     i = 1;
234             }
235
236             if (i) {
237                 /* option processed, delete it */
238                 if ((q = strchr( p, ' ' )))
239                     strcpy( p, q+1 );
240                 else
241                     *p = 0;
242             } else {
243                 if ((p = strchr( p, ' ' ))) ++p;
244             }
245         }
246
247         config_amiga();
248
249 #if 0 /* Enable for logging - also include logging.o in Makefile rule */
250         {
251 #define LOG_SIZE 4096
252                 void* base;
253
254                 /* Throw away some memory - the P5 firmare stomps on top
255                  * of CHIP memory during bootup.
256                  */
257                 amiga_chip_alloc(0x1000);
258
259                 base = amiga_chip_alloc(LOG_SIZE+sizeof(klog_data_t));
260                 LOG_INIT(base, base+sizeof(klog_data_t), LOG_SIZE);
261         }
262 #endif
263 #endif
264 }
265
266 int
267 apus_get_cpuinfo(char *buffer)
268 {
269 #ifdef CONFIG_APUS
270         extern int __map_without_bats;
271         extern unsigned long powerup_PCI_present;
272         int len;
273
274         len = sprintf(buffer, "machine\t\t: Amiga\n");
275         len += sprintf(buffer+len, "bus speed\t: %d%s", __bus_speed,
276                        (__speed_test_failed) ? " [failed]\n" : "\n");
277         len += sprintf(buffer+len, "using BATs\t: %s\n",
278                        (__map_without_bats) ? "No" : "Yes");
279         len += sprintf(buffer+len, "ram speed\t: %dns\n", 
280                        (__60nsram) ? 60 : 70);
281         len += sprintf(buffer+len, "PCI bridge\t: %s\n",
282                        (powerup_PCI_present) ? "Yes" : "No");
283         return len;
284 #endif
285 }
286
287 static void get_current_tb(unsigned long long *time)
288 {
289         __asm __volatile ("1:mftbu 4      \n\t"
290                           "  mftb  5      \n\t"
291                           "  mftbu 6      \n\t"
292                           "  cmpw  4,6    \n\t"
293                           "  bne   1b     \n\t"
294                           "  stw   4,0(%0)\n\t"
295                           "  stw   5,4(%0)\n\t"
296                           : 
297                           : "r" (time)
298                           : "r4", "r5", "r6");
299 }
300
301
302 void apus_calibrate_decr(void)
303 {
304 #ifdef CONFIG_APUS
305         unsigned long freq;
306
307         /* This algorithm for determining the bus speed was
308            contributed by Ralph Schmidt. */
309         unsigned long long start, stop;
310         int bus_speed;
311         int speed_test_failed = 0;
312
313         {
314                 unsigned long loop = amiga_eclock / 10;
315
316                 get_current_tb (&start);
317                 while (loop--) {
318                         unsigned char tmp;
319
320                         tmp = ciaa.pra;
321                 }
322                 get_current_tb (&stop);
323         }
324
325         bus_speed = (((unsigned long)(stop-start))*10*4) / 1000000;
326         if (AMI_1200 == amiga_model)
327                 bus_speed /= 2;
328
329         if ((bus_speed >= 47) && (bus_speed < 53)) {
330                 bus_speed = 50;
331                 freq = 12500000;
332         } else if ((bus_speed >= 57) && (bus_speed < 63)) {
333                 bus_speed = 60;
334                 freq = 15000000;
335         } else if ((bus_speed >= 63) && (bus_speed < 69)) {
336                 bus_speed = 67;
337                 freq = 16666667;
338         } else {
339                 printk ("APUS: Unable to determine bus speed (%d). "
340                         "Defaulting to 50MHz", bus_speed);
341                 bus_speed = 50;
342                 freq = 12500000;
343                 speed_test_failed = 1;
344         }
345
346         /* Ease diagnostics... */
347         {
348                 extern int __map_without_bats;
349                 extern unsigned long powerup_PCI_present;
350
351                 printk ("APUS: BATs=%d, BUS=%dMHz",
352                         (__map_without_bats) ? 0 : 1,
353                         bus_speed);
354                 if (speed_test_failed)
355                         printk ("[FAILED - please report]");
356
357                 printk (", RAM=%dns, PCI bridge=%d\n",
358                         (__60nsram) ? 60 : 70,
359                         (powerup_PCI_present) ? 1 : 0);
360
361                 /* print a bit more if asked politely... */
362                 if (!(ciaa.pra & 0x40)){
363                         extern unsigned int bat_addrs[4][3];
364                         int b;
365                         for (b = 0; b < 4; ++b) {
366                                 printk ("APUS: BAT%d ", b);
367                                 printk ("%08x-%08x -> %08x\n",
368                                         bat_addrs[b][0],
369                                         bat_addrs[b][1],
370                                         bat_addrs[b][2]);
371                         }
372                 }
373
374         }
375
376         printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
377                freq/1000000, freq%1000000);
378         tb_ticks_per_jiffy = freq / HZ;
379         tb_to_us = mulhwu_scale_factor(freq, 1000000);
380
381         __bus_speed = bus_speed;
382         __speed_test_failed = speed_test_failed;
383 #endif
384 }
385
386 void arch_gettod(int *year, int *mon, int *day, int *hour,
387                  int *min, int *sec)
388 {
389 #ifdef CONFIG_APUS
390         if (mach_gettod)
391                 mach_gettod(year, mon, day, hour, min, sec);
392         else
393                 *year = *mon = *day = *hour = *min = *sec = 0;
394 #endif
395 }
396
397 /* for "kbd-reset" cmdline param */
398 __init
399 void kbd_reset_setup(char *str, int *ints)
400 {
401 }
402
403 /*********************************************************** FLOPPY */
404 #if defined(CONFIG_AMIGA_FLOPPY)
405 __init 
406 void floppy_setup(char *str, int *ints)
407 {
408         if (mach_floppy_setup)
409                 mach_floppy_setup (str, ints);
410 }
411
412 void floppy_eject(void)
413 {
414         if (mach_floppy_eject)
415                 mach_floppy_eject();
416 }
417 #endif
418
419 /*********************************************************** MEMORY */
420 #define KMAP_MAX 32
421 unsigned long kmap_chunks[KMAP_MAX*3];
422 int kmap_chunk_count = 0;
423
424 /* From pgtable.h */
425 static __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va)
426 {
427         pgd_t *dir = 0;
428         pmd_t *pmd = 0;
429         pte_t *pte = 0;
430
431         va &= PAGE_MASK;
432         
433         dir = pgd_offset( mm, va );
434         if (dir)
435         {
436                 pmd = pmd_offset(dir, va & PAGE_MASK);
437                 if (pmd && pmd_present(*pmd))
438                 {
439                         pte = pte_offset(pmd, va);
440                 }
441         }
442         return pte;
443 }
444
445
446 /* Again simulating an m68k/mm/kmap.c function. */
447 void kernel_set_cachemode( unsigned long address, unsigned long size,
448                            unsigned int cmode )
449 {
450         unsigned long mask, flags;
451
452         switch (cmode)
453         {
454         case IOMAP_FULL_CACHING:
455                 mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
456                 flags = 0;
457                 break;
458         case IOMAP_NOCACHE_SER:
459                 mask = ~0;
460                 flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
461                 break;
462         default:
463                 panic ("kernel_set_cachemode() doesn't support mode %d\n", 
464                        cmode);
465                 break;
466         }
467         
468         size /= PAGE_SIZE;
469         address &= PAGE_MASK;
470         while (size--)
471         {
472                 pte_t *pte;
473
474                 pte = my_find_pte(&init_mm, address);
475                 if ( !pte )
476                 {
477                         printk("pte NULL in kernel_set_cachemode()\n");
478                         return;
479                 }
480
481                 pte_val (*pte) &= mask;
482                 pte_val (*pte) |= flags;
483                 flush_tlb_page(find_vma(&init_mm,address),address);
484
485                 address += PAGE_SIZE;
486         }
487 }
488
489 unsigned long mm_ptov (unsigned long paddr)
490 {
491         unsigned long ret;
492         if (paddr < 16*1024*1024)
493                 ret = ZTWO_VADDR(paddr);
494         else {
495                 int i;
496
497                 for (i = 0; i < kmap_chunk_count;){
498                         unsigned long phys = kmap_chunks[i++];
499                         unsigned long size = kmap_chunks[i++];
500                         unsigned long virt = kmap_chunks[i++];
501                         if (paddr >= phys
502                             && paddr < (phys + size)){
503                                 ret = virt + paddr - phys;
504                                 goto exit;
505                         }
506                 }
507                 
508                 ret = (unsigned long) __va(paddr);
509         }
510 exit:
511 #ifdef DEBUGPV
512         printk ("PTOV(%lx)=%lx\n", paddr, ret);
513 #endif
514         return ret;
515 }
516
517 int mm_end_of_chunk (unsigned long addr, int len)
518 {
519         if (memory[0].addr + memory[0].size == addr + len)
520                 return 1;
521         return 0;
522 }
523
524 /*********************************************************** CACHE */
525
526 #define L1_CACHE_BYTES 32
527 #define MAX_CACHE_SIZE 8192
528 void cache_push(__u32 addr, int length)
529 {
530         addr = mm_ptov(addr);
531
532         if (MAX_CACHE_SIZE < length)
533                 length = MAX_CACHE_SIZE;
534
535         while(length > 0){
536                 __asm ("dcbf 0,%0\n\t"
537                        : : "r" (addr));
538                 addr += L1_CACHE_BYTES;
539                 length -= L1_CACHE_BYTES;
540         }
541         /* Also flush trailing block */
542         __asm ("dcbf 0,%0\n\t"
543                "sync \n\t"
544                : : "r" (addr));
545 }
546
547 void cache_clear(__u32 addr, int length)
548 {
549         if (MAX_CACHE_SIZE < length)
550                 length = MAX_CACHE_SIZE;
551
552         addr = mm_ptov(addr);
553
554         __asm ("dcbf 0,%0\n\t"
555                "sync \n\t"
556                "icbi 0,%0 \n\t"
557                "isync \n\t"
558                : : "r" (addr));
559         
560         addr += L1_CACHE_BYTES;
561         length -= L1_CACHE_BYTES;
562
563         while(length > 0){
564                 __asm ("dcbf 0,%0\n\t"
565                        "sync \n\t"
566                        "icbi 0,%0 \n\t"
567                        "isync \n\t"
568                        : : "r" (addr));
569                 addr += L1_CACHE_BYTES;
570                 length -= L1_CACHE_BYTES;
571         }
572
573         __asm ("dcbf 0,%0\n\t"
574                "sync \n\t"
575                "icbi 0,%0 \n\t"
576                "isync \n\t"
577                : : "r" (addr));
578 }
579
580 /****************************************************** from setup.c */
581 void
582 apus_restart(char *cmd)
583 {
584         cli();
585
586         APUS_WRITE(APUS_REG_LOCK, 
587                    REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
588         APUS_WRITE(APUS_REG_LOCK, 
589                    REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
590         APUS_WRITE(APUS_REG_LOCK, 
591                    REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
592         APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
593         APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
594         for(;;);
595 }
596
597 void
598 apus_power_off(void)
599 {
600         for (;;);
601 }
602
603 void
604 apus_halt(void)
605 {
606    apus_restart(NULL);
607 }
608
609 /****************************************************** from setup.c/IDE */
610 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
611 /*
612  * IDE stuff.
613  */
614 void ide_insw(ide_ioreg_t port, void *buf, int ns);
615 void ide_outsw(ide_ioreg_t port, void *buf, int ns);
616 void
617 apus_ide_insw(ide_ioreg_t port, void *buf, int ns)
618 {
619         ide_insw(port, buf, ns);
620 }
621
622 void
623 apus_ide_outsw(ide_ioreg_t port, void *buf, int ns)
624 {
625         ide_outsw(port, buf, ns);
626 }
627
628 int
629 apus_ide_default_irq(ide_ioreg_t base)
630 {
631         return 0;
632 }
633
634 ide_ioreg_t
635 apus_ide_default_io_base(int index)
636 {
637         return 0;
638 }
639
640 void
641 apus_ide_fix_driveid(struct hd_driveid *id)
642 {
643    u_char *p = (u_char *)id;
644    int i, j, cnt;
645    u_char t;
646
647    if (!MACH_IS_AMIGA && !MACH_IS_MAC)
648         return;
649    for (i = 0; i < num_driveid_types; i++) {
650       cnt = driveid_types[i] & T_MASK_COUNT;
651       switch (driveid_types[i] & T_MASK_TYPE) {
652          case T_CHAR:
653             p += cnt;
654             break;
655          case T_SHORT:
656             for (j = 0; j < cnt; j++) {
657                t = p[0];
658                p[0] = p[1];
659                p[1] = t;
660                p += 2;
661             }
662             break;
663          case T_INT:
664             for (j = 0; j < cnt; j++) {
665                t = p[0];
666                p[0] = p[3];
667                p[3] = t;
668                t = p[1];
669                p[1] = p[2];
670                p[2] = t;
671                p += 4;
672             }
673             break;
674          case T_TEXT:
675             for (j = 0; j < cnt; j += 2) {
676                t = p[0];
677                p[0] = p[1];
678                p[1] = t;
679                p += 2;
680             }
681             break;
682       }
683    }
684 }
685
686 __init
687 void apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, 
688                                ide_ioreg_t ctrl_port, int *irq)
689 {
690         if (data_port || ctrl_port)
691                 printk("apus_ide_init_hwif_ports: must not be called\n");
692 }
693 #endif
694 /****************************************************** IRQ stuff */
695
696 static unsigned int apus_irq_cannonicalize(unsigned int irq)
697 {
698         return irq;
699 }
700
701 int apus_get_irq_list(char *buf)
702 {
703 #ifdef CONFIG_APUS
704         extern int amiga_get_irq_list(char *buf);
705         
706         return amiga_get_irq_list (buf);
707 #else
708         return 0;
709 #endif
710 }
711
712 /* IPL must be between 0 and 7 */
713 static inline void apus_set_IPL(unsigned long ipl)
714 {
715         APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
716         APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
717         APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | ((~ipl) & IPLEMU_IPLMASK));
718         APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
719 }
720
721 static inline unsigned long apus_get_IPL(void)
722 {
723         /* This returns the present IPL emulation level. */
724         unsigned long __f;
725         APUS_READ(APUS_IPL_EMU, __f);
726         return ((~__f) & IPLEMU_IPLMASK);
727 }
728
729 static inline unsigned long apus_get_prev_IPL(struct pt_regs* regs)
730 {
731         /* The value saved in mq is the IPL_EMU value at the time of
732            interrupt. The lower bits are the current interrupt level,
733            the upper bits the requested level. Thus, to restore the
734            IPL level to the post-interrupt state, we will need to use
735            the lower bits. */
736         unsigned long __f = regs->mq;
737         return ((~__f) & IPLEMU_IPLMASK);
738 }
739
740
741 #ifdef CONFIG_APUS
742 void free_irq(unsigned int irq, void *dev_id)
743 {
744         extern void amiga_free_irq(unsigned int irq, void *dev_id);
745
746         amiga_free_irq (irq, dev_id);
747 }
748
749 int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
750         unsigned long irqflags, const char * devname, void *dev_id)
751 {
752         extern int  amiga_request_irq(unsigned int irq, 
753                                       void (*handler)(int, void *, 
754                                                       struct pt_regs *),
755                                       unsigned long flags, 
756                                       const char *devname, 
757                                       void *dev_id);
758
759         return amiga_request_irq (irq, handler, irqflags, devname, dev_id);
760 }
761
762 /* In Linux/m68k the sys_request_irq deals with vectors 0-7. That's what
763    callers expect - but on Linux/APUS we actually use the IRQ_AMIGA_AUTO
764    vectors (24-31), so we put this dummy function in between to adjust
765    the vector argument (rather have cruft here than in the generic irq.c). */
766 int sys_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
767                     unsigned long irqflags, const char * devname, void *dev_id)
768 {
769         extern int request_sysirq(unsigned int irq, 
770                                   void (*handler)(int, void *, 
771                                                   struct pt_regs *),
772                                   unsigned long irqflags,
773                                   const char * devname, void *dev_id);
774         return request_sysirq(irq+IRQ_AMIGA_AUTO, handler, irqflags, 
775                               devname, dev_id);
776 }
777 #endif
778
779 int apus_get_irq(struct pt_regs* regs)
780 {
781 #ifdef CONFIG_APUS
782         int level = apus_get_IPL();
783
784 #ifdef __INTERRUPT_DEBUG
785         printk("<%d:%d>", level, apus_get_prev_IPL(regs));
786 #endif
787
788         if (0 == level)
789                 return -8;
790         if (7 == level)
791                 return -9;
792
793         return level + IRQ_AMIGA_AUTO;
794 #else
795         return 0;
796 #endif
797 }
798
799 void apus_post_irq(struct pt_regs* regs, int level)
800 {
801 #ifdef __INTERRUPT_DEBUG
802         printk("{%d}", apus_get_prev_IPL(regs));
803 #endif
804         /* Restore IPL to the previous value */
805         apus_set_IPL(apus_get_prev_IPL(regs));
806 }
807
808 /****************************************************** keyboard */
809 static int apus_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
810 {
811         return -EOPNOTSUPP;
812 }
813
814 static int apus_kbd_getkeycode(unsigned int scancode)
815 {
816         return scancode > 127 ? -EINVAL : scancode;
817 }
818
819 static int apus_kbd_translate(unsigned char keycode, unsigned char *keycodep,
820                               char raw_mode)
821 {
822         *keycodep = keycode;
823         return 1;
824 }
825
826 static char apus_kbd_unexpected_up(unsigned char keycode)
827 {
828         return 0200;
829 }
830
831 static void apus_kbd_leds(unsigned char leds)
832 {
833 }
834
835 static void apus_kbd_init_hw(void)
836 {
837 #ifdef CONFIG_APUS
838         extern int amiga_keyb_init(void);
839
840         amiga_keyb_init();
841 #endif
842 }
843
844
845 /****************************************************** debugging */
846
847 /* some serial hardware definitions */
848 #define SDR_OVRUN   (1<<15)
849 #define SDR_RBF     (1<<14)
850 #define SDR_TBE     (1<<13)
851 #define SDR_TSRE    (1<<12)
852
853 #define AC_SETCLR   (1<<15)
854 #define AC_UARTBRK  (1<<11)
855
856 #define SER_DTR     (1<<7)
857 #define SER_RTS     (1<<6)
858 #define SER_DCD     (1<<5)
859 #define SER_CTS     (1<<4)
860 #define SER_DSR     (1<<3)
861
862 static __inline__ void ser_RTSon(void)
863 {
864     ciab.pra &= ~SER_RTS; /* active low */
865 }
866
867 int __debug_ser_out( unsigned char c )
868 {
869         custom.serdat = c | 0x100;
870         mb();
871         while (!(custom.serdatr & 0x2000))
872                 barrier();
873         return 1;
874 }
875
876 unsigned char __debug_ser_in( void )
877 {
878         unsigned char c;
879
880         /* XXX: is that ok?? derived from amiga_ser.c... */
881         while( !(custom.intreqr & IF_RBF) )
882                 barrier();
883         c = custom.serdatr;
884         /* clear the interrupt, so that another character can be read */
885         custom.intreq = IF_RBF;
886         return c;
887 }
888
889 int __debug_serinit( void )
890 {       
891         unsigned long flags;
892         
893         save_flags (flags);
894         cli();
895
896         /* turn off Rx and Tx interrupts */
897         custom.intena = IF_RBF | IF_TBE;
898
899         /* clear any pending interrupt */
900         custom.intreq = IF_RBF | IF_TBE;
901
902         restore_flags (flags);
903
904         /*
905          * set the appropriate directions for the modem control flags,
906          * and clear RTS and DTR
907          */
908         ciab.ddra |= (SER_DTR | SER_RTS);   /* outputs */
909         ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
910         
911 #ifdef CONFIG_KGDB
912         /* turn Rx interrupts on for GDB */
913         custom.intena = IF_SETCLR | IF_RBF;
914         ser_RTSon();
915 #endif
916
917         return 0;
918 }
919
920 void __debug_print_hex(unsigned long x)
921 {
922         int i;
923         char hexchars[] = "0123456789ABCDEF";
924
925         for (i = 0; i < 8; i++) {
926                 __debug_ser_out(hexchars[(x >> 28) & 15]);
927                 x <<= 4;
928         }
929         __debug_ser_out('\n');
930         __debug_ser_out('\r');
931 }
932
933 void __debug_print_string(char* s)
934 {
935         unsigned char c;
936         while((c = *s++))
937                 __debug_ser_out(c);
938         __debug_ser_out('\n');
939         __debug_ser_out('\r');
940 }
941
942 static void apus_progress(char *s, unsigned short value)
943 {
944         __debug_print_string(s);
945 }
946
947 /****************************************************** init */
948
949 /* The number of spurious interrupts */
950 volatile unsigned int num_spurious;
951
952 #define NUM_IRQ_NODES 100
953 static irq_node_t nodes[NUM_IRQ_NODES];
954
955 extern void (*amiga_default_handler[AUTO_IRQS])(int, void *, struct pt_regs *);
956
957 static const char *default_names[SYS_IRQS] = {
958         "spurious int", "int1 handler", "int2 handler", "int3 handler",
959         "int4 handler", "int5 handler", "int6 handler", "int7 handler"
960 };
961
962 irq_node_t *new_irq_node(void)
963 {
964         irq_node_t *node;
965         short i;
966
967         for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
968                 if (!node->handler)
969                         return node;
970
971         printk ("new_irq_node: out of nodes\n");
972         return NULL;
973 }
974
975 extern void amiga_enable_irq(unsigned int irq);
976 extern void amiga_disable_irq(unsigned int irq);
977
978 struct hw_interrupt_type amiga_irqctrl = {
979         " Amiga  ",
980         NULL,
981         NULL,
982         amiga_enable_irq,
983         amiga_disable_irq,
984         0,
985         0
986 };
987
988 #define HARDWARE_MAPPED_SIZE (512*1024)
989 unsigned long __init apus_find_end_of_memory(void)
990 {
991         int shadow = 0;
992         unsigned long total;
993
994         /* The memory size reported by ADOS excludes the 512KB
995            reserved for PPC exception registers and possibly 512KB
996            containing a shadow of the ADOS ROM. */
997         {
998                 unsigned long size = memory[0].size;
999
1000                 /* If 2MB aligned, size was probably user
1001                    specified. We can't tell anything about shadowing
1002                    in this case so skip shadow assignment. */
1003                 if (0 != (size & 0x1fffff)){
1004                         /* Align to 512KB to ensure correct handling
1005                            of both memfile and system specified
1006                            sizes. */
1007                         size = ((size+0x0007ffff) & 0xfff80000);
1008                         /* If memory is 1MB aligned, assume
1009                            shadowing. */
1010                         shadow = !(size & 0x80000);
1011                 }
1012
1013                 /* Add the chunk that ADOS does not see. by aligning
1014                    the size to the nearest 2MB limit upwards.  */
1015                 memory[0].size = ((size+0x001fffff) & 0xffe00000);
1016         }
1017
1018         total = memory[0].size;
1019
1020         /* Remove the memory chunks that are controlled by special
1021            Phase5 hardware. */
1022
1023         /* Remove the upper 512KB if it contains a shadow of
1024            the ADOS ROM. FIXME: It might be possible to
1025            disable this shadow HW. Check the booter
1026            (ppc_boot.c) */
1027         if (shadow)
1028                 total -= HARDWARE_MAPPED_SIZE;
1029
1030         /* Remove the upper 512KB where the PPC exception
1031            vectors are mapped. */
1032         total -= HARDWARE_MAPPED_SIZE;
1033
1034         /* Linux/APUS only handles one block of memory -- the one on
1035            the PowerUP board. Other system memory is horrible slow in
1036            comparison. The user can use other memory for swapping
1037            using the z2ram device. */
1038         ram_phys_base = memory[0].addr;
1039         return total;
1040 }
1041
1042 __init
1043 void apus_init_IRQ(void)
1044 {
1045         int i;
1046
1047         for ( i = 0 ; i < NR_IRQS ; i++ )
1048                 irq_desc[i].handler = &amiga_irqctrl;
1049
1050         for (i = 0; i < NUM_IRQ_NODES; i++)
1051                 nodes[i].handler = NULL;
1052
1053         for (i = 0; i < AUTO_IRQS; i++) {
1054                 if (amiga_default_handler[i] != NULL)
1055                         sys_request_irq(i, amiga_default_handler[i],
1056                                         0, default_names[i], NULL);
1057         }
1058
1059         amiga_init_IRQ();
1060
1061 }
1062
1063 __init
1064 void apus_init(unsigned long r3, unsigned long r4, unsigned long r5,
1065                unsigned long r6, unsigned long r7)
1066 {
1067         extern int parse_bootinfo(const struct bi_record *);
1068         extern char _end[];
1069         
1070         /* Parse bootinfo. The bootinfo is located right after
1071            the kernel bss */
1072         parse_bootinfo((const struct bi_record *)&_end);
1073 #ifdef CONFIG_BLK_DEV_INITRD
1074         /* Take care of initrd if we have one. Use data from
1075            bootinfo to avoid the need to initialize PPC
1076            registers when kernel is booted via a PPC reset. */
1077         if ( ramdisk.addr ) {
1078                 initrd_start = (unsigned long) __va(ramdisk.addr);
1079                 initrd_end = (unsigned long) 
1080                         __va(ramdisk.size + ramdisk.addr);
1081         }
1082 #endif /* CONFIG_BLK_DEV_INITRD */
1083
1084         ISA_DMA_THRESHOLD = 0x00ffffff;
1085
1086         ppc_md.setup_arch     = apus_setup_arch;
1087         ppc_md.setup_residual = NULL;
1088         ppc_md.get_cpuinfo    = apus_get_cpuinfo;
1089         ppc_md.irq_cannonicalize = apus_irq_cannonicalize;
1090         ppc_md.init_IRQ       = apus_init_IRQ;
1091         ppc_md.get_irq        = apus_get_irq;
1092         
1093 #error Should use the ->end() member of irq_desc[x]. -- Cort
1094         /*ppc_md.post_irq       = apus_post_irq;*/
1095         
1096 #ifdef CONFIG_HEARTBEAT
1097         ppc_md.heartbeat      = apus_heartbeat;
1098         ppc_md.heartbeat_count = 1;
1099 #endif
1100 #ifdef APUS_DEBUG
1101         __debug_serinit();
1102         ppc_md.progress       = apus_progress;
1103 #endif
1104         ppc_md.init           = NULL;
1105
1106         ppc_md.restart        = apus_restart;
1107         ppc_md.power_off      = apus_power_off;
1108         ppc_md.halt           = apus_halt;
1109
1110         ppc_md.time_init      = NULL;
1111         ppc_md.set_rtc_time   = apus_set_rtc_time;
1112         ppc_md.get_rtc_time   = apus_get_rtc_time;
1113         ppc_md.calibrate_decr = apus_calibrate_decr;
1114
1115         ppc_md.find_end_of_memory = apus_find_end_of_memory;
1116
1117         ppc_md.nvram_read_val = NULL;
1118         ppc_md.nvram_write_val = NULL;
1119
1120         /* These should not be used for the APUS yet, since it uses
1121            the M68K keyboard now. */
1122         ppc_md.kbd_setkeycode    = apus_kbd_setkeycode;
1123         ppc_md.kbd_getkeycode    = apus_kbd_getkeycode;
1124         ppc_md.kbd_translate     = apus_kbd_translate;
1125         ppc_md.kbd_unexpected_up = apus_kbd_unexpected_up;
1126         ppc_md.kbd_leds          = apus_kbd_leds;
1127         ppc_md.kbd_init_hw       = apus_kbd_init_hw;
1128 #ifdef CONFIG_MAGIC_SYSRQ
1129         ppc_md.kbd_sysrq_xlate   = NULL;
1130 #endif
1131
1132 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
1133         ppc_ide_md.insw = apus_ide_insw;
1134         ppc_ide_md.outsw = apus_ide_outsw;
1135         ppc_ide_md.default_irq = apus_ide_default_irq;
1136         ppc_ide_md.default_io_base = apus_ide_default_io_base;
1137         ppc_ide_md.fix_driveid = apus_ide_fix_driveid;
1138         ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports;
1139
1140         ppc_ide_md.io_base = _IO_BASE;
1141 #endif          
1142 }
1143
1144
1145 /*************************************************** coexistence */
1146 void __init adbdev_init(void)
1147 {
1148 }