📄 apus_setup.c
字号:
/*********************************************************** CACHE */#define L1_CACHE_BYTES 32#define MAX_CACHE_SIZE 8192void cache_push(__u32 addr, int length){ addr = mm_ptov(addr); if (MAX_CACHE_SIZE < length) length = MAX_CACHE_SIZE; while(length > 0){ __asm ("dcbf 0,%0\n\t" : : "r" (addr)); addr += L1_CACHE_BYTES; length -= L1_CACHE_BYTES; } /* Also flush trailing block */ __asm ("dcbf 0,%0\n\t" "sync \n\t" : : "r" (addr));}void cache_clear(__u32 addr, int length){ if (MAX_CACHE_SIZE < length) length = MAX_CACHE_SIZE; addr = mm_ptov(addr); __asm ("dcbf 0,%0\n\t" "sync \n\t" "icbi 0,%0 \n\t" "isync \n\t" : : "r" (addr)); addr += L1_CACHE_BYTES; length -= L1_CACHE_BYTES; while(length > 0){ __asm ("dcbf 0,%0\n\t" "sync \n\t" "icbi 0,%0 \n\t" "isync \n\t" : : "r" (addr)); addr += L1_CACHE_BYTES; length -= L1_CACHE_BYTES; } __asm ("dcbf 0,%0\n\t" "sync \n\t" "icbi 0,%0 \n\t" "isync \n\t" : : "r" (addr));}/****************************************************** from setup.c */voidapus_restart(char *cmd){ cli(); APUS_WRITE(APUS_REG_LOCK, REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2); APUS_WRITE(APUS_REG_LOCK, REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3); APUS_WRITE(APUS_REG_LOCK, REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3); APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET); APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET); for(;;);}voidapus_power_off(void){ for (;;);}voidapus_halt(void){ apus_restart(NULL);}/****************************************************** IRQ stuff */static unsigned char last_ipl[8];int apus_get_irq(struct pt_regs* regs){ unsigned char ipl_emu, mask; unsigned int level; APUS_READ(APUS_IPL_EMU, ipl_emu); level = (ipl_emu >> 3) & IPLEMU_IPLMASK; mask = IPLEMU_SETRESET|IPLEMU_DISABLEINT|level; level ^= 7; /* Save previous IPL value */ if (last_ipl[level]) return -2; last_ipl[level] = ipl_emu; /* Set to current IPL value */ APUS_WRITE(APUS_IPL_EMU, mask); APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|level);#ifdef __INTERRUPT_DEBUG printk("<%d:%d>", level, ~ipl_emu & IPLEMU_IPLMASK);#endif return level + IRQ_AMIGA_AUTO;}void apus_end_irq(unsigned int irq){ unsigned char ipl_emu; unsigned int level = irq - IRQ_AMIGA_AUTO;#ifdef __INTERRUPT_DEBUG printk("{%d}", ~last_ipl[level] & IPLEMU_IPLMASK);#endif /* Restore IPL to the previous value */ ipl_emu = last_ipl[level] & IPLEMU_IPLMASK; APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET|IPLEMU_DISABLEINT|ipl_emu); last_ipl[level] = 0; ipl_emu ^= 7; APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|ipl_emu);}/****************************************************** keyboard */static int apus_kbd_setkeycode(unsigned int scancode, unsigned int keycode){ return -EOPNOTSUPP;}static int apus_kbd_getkeycode(unsigned int scancode){ return scancode > 127 ? -EINVAL : scancode;}static char apus_kbd_unexpected_up(unsigned char keycode){ return 0200;}static void apus_kbd_init_hw(void){#ifdef CONFIG_APUS extern int amiga_keyb_init(void); amiga_keyb_init();#endif}/****************************************************** debugging *//* some serial hardware definitions */#define SDR_OVRUN (1<<15)#define SDR_RBF (1<<14)#define SDR_TBE (1<<13)#define SDR_TSRE (1<<12)#define AC_SETCLR (1<<15)#define AC_UARTBRK (1<<11)#define SER_DTR (1<<7)#define SER_RTS (1<<6)#define SER_DCD (1<<5)#define SER_CTS (1<<4)#define SER_DSR (1<<3)static __inline__ void ser_RTSon(void){ ciab.pra &= ~SER_RTS; /* active low */}int __debug_ser_out( unsigned char c ){ custom.serdat = c | 0x100; mb(); while (!(custom.serdatr & 0x2000)) barrier(); return 1;}unsigned char __debug_ser_in( void ){ unsigned char c; /* XXX: is that ok?? derived from amiga_ser.c... */ while( !(custom.intreqr & IF_RBF) ) barrier(); c = custom.serdatr; /* clear the interrupt, so that another character can be read */ custom.intreq = IF_RBF; return c;}int __debug_serinit( void ){ unsigned long flags; save_flags (flags); cli(); /* turn off Rx and Tx interrupts */ custom.intena = IF_RBF | IF_TBE; /* clear any pending interrupt */ custom.intreq = IF_RBF | IF_TBE; restore_flags (flags); /* * set the appropriate directions for the modem control flags, * and clear RTS and DTR */ ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */#ifdef CONFIG_KGDB /* turn Rx interrupts on for GDB */ custom.intena = IF_SETCLR | IF_RBF; ser_RTSon();#endif return 0;}void __debug_print_hex(unsigned long x){ int i; char hexchars[] = "0123456789ABCDEF"; for (i = 0; i < 8; i++) { __debug_ser_out(hexchars[(x >> 28) & 15]); x <<= 4; } __debug_ser_out('\n'); __debug_ser_out('\r');}void __debug_print_string(char* s){ unsigned char c; while((c = *s++)) __debug_ser_out(c); __debug_ser_out('\n'); __debug_ser_out('\r');}static void apus_progress(char *s, unsigned short value){ __debug_print_string(s);}/****************************************************** init *//* The number of spurious interrupts */volatile unsigned int num_spurious;extern struct irqaction amiga_sys_irqaction[AUTO_IRQS];extern void amiga_enable_irq(unsigned int irq);extern void amiga_disable_irq(unsigned int irq);struct hw_interrupt_type amiga_sys_irqctrl = { typename: "Amiga IPL", end: apus_end_irq,};struct hw_interrupt_type amiga_irqctrl = { typename: "Amiga ", enable: amiga_enable_irq, disable: amiga_disable_irq,};#define HARDWARE_MAPPED_SIZE (512*1024)unsigned long __init apus_find_end_of_memory(void){ int shadow = 0; unsigned long total; /* The memory size reported by ADOS excludes the 512KB reserved for PPC exception registers and possibly 512KB containing a shadow of the ADOS ROM. */ { unsigned long size = memory[0].size; /* If 2MB aligned, size was probably user specified. We can't tell anything about shadowing in this case so skip shadow assignment. */ if (0 != (size & 0x1fffff)){ /* Align to 512KB to ensure correct handling of both memfile and system specified sizes. */ size = ((size+0x0007ffff) & 0xfff80000); /* If memory is 1MB aligned, assume shadowing. */ shadow = !(size & 0x80000); } /* Add the chunk that ADOS does not see. by aligning the size to the nearest 2MB limit upwards. */ memory[0].size = ((size+0x001fffff) & 0xffe00000); } total = memory[0].size; /* Remove the memory chunks that are controlled by special Phase5 hardware. */ /* Remove the upper 512KB if it contains a shadow of the ADOS ROM. FIXME: It might be possible to disable this shadow HW. Check the booter (ppc_boot.c) */ if (shadow) total -= HARDWARE_MAPPED_SIZE; /* Remove the upper 512KB where the PPC exception vectors are mapped. */ total -= HARDWARE_MAPPED_SIZE; /* Linux/APUS only handles one block of memory -- the one on the PowerUP board. Other system memory is horrible slow in comparison. The user can use other memory for swapping using the z2ram device. */ ram_phys_base = memory[0].addr; return total;}static void __initapus_map_io(void){ /* Map PPC exception vectors. */ io_block_mapping(0xfff00000, 0xfff00000, 0x00020000, _PAGE_KERNEL); /* Map chip and ZorroII memory */ io_block_mapping(zTwoBase, 0x00000000, 0x01000000, _PAGE_IO);}__initvoid apus_init_IRQ(void){ struct irqaction *action; int i;#ifdef CONFIG_PCI apus_setup_pci_ptrs();#endif for ( i = 0 ; i < AMI_IRQS; i++ ) { irq_desc[i].status = IRQ_LEVEL; if (i < IRQ_AMIGA_AUTO) { irq_desc[i].handler = &amiga_irqctrl; } else { irq_desc[i].handler = &amiga_sys_irqctrl; action = &amiga_sys_irqaction[i-IRQ_AMIGA_AUTO]; if (action->name) setup_irq(i, action); } } amiga_init_IRQ();}__initvoid platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7){ extern int parse_bootinfo(const struct bi_record *); extern char _end[]; /* Parse bootinfo. The bootinfo is located right after the kernel bss */ parse_bootinfo((const struct bi_record *)&_end);#ifdef CONFIG_BLK_DEV_INITRD /* Take care of initrd if we have one. Use data from bootinfo to avoid the need to initialize PPC registers when kernel is booted via a PPC reset. */ if ( ramdisk.addr ) { initrd_start = (unsigned long) __va(ramdisk.addr); initrd_end = (unsigned long) __va(ramdisk.size + ramdisk.addr); }#endif /* CONFIG_BLK_DEV_INITRD */ ISA_DMA_THRESHOLD = 0x00ffffff; ppc_md.setup_arch = apus_setup_arch; ppc_md.show_cpuinfo = apus_show_cpuinfo; ppc_md.init_IRQ = apus_init_IRQ; ppc_md.get_irq = apus_get_irq;#ifdef CONFIG_HEARTBEAT ppc_md.heartbeat = apus_heartbeat; heartbeat_reset(0) = 1; /* assume UP for now */ heartbeat_count(0) = 1;#endif#ifdef APUS_DEBUG __debug_serinit(); ppc_md.progress = apus_progress;#endif ppc_md.init = NULL; ppc_md.restart = apus_restart; ppc_md.power_off = apus_power_off; ppc_md.halt = apus_halt; ppc_md.time_init = NULL; ppc_md.set_rtc_time = apus_set_rtc_time; ppc_md.get_rtc_time = apus_get_rtc_time; ppc_md.calibrate_decr = apus_calibrate_decr; ppc_md.find_end_of_memory = apus_find_end_of_memory; ppc_md.setup_io_mappings = apus_map_io; /* These should not be used for the APUS yet, since it uses the M68K keyboard now. */ ppc_md.kbd_setkeycode = apus_kbd_setkeycode; ppc_md.kbd_getkeycode = apus_kbd_getkeycode; ppc_md.kbd_translate = amiga_kbd_translate; ppc_md.kbd_unexpected_up = apus_kbd_unexpected_up; ppc_md.kbd_init_hw = apus_kbd_init_hw;#ifdef CONFIG_SYSRQ ppc_md.ppc_kbd_sysrq_xlate = amiga_sysrq_xlate; SYSRQ_KEY = 0xff;#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -