📄 apus_setup.c
字号:
"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);}/****************************************************** from setup.c/IDE */#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)/* * IDE stuff. */void ide_insw(ide_ioreg_t port, void *buf, int ns);void ide_outsw(ide_ioreg_t port, void *buf, int ns);voidapus_ide_insw(ide_ioreg_t port, void *buf, int ns){ ide_insw(port, buf, ns);}voidapus_ide_outsw(ide_ioreg_t port, void *buf, int ns){ ide_outsw(port, buf, ns);}intapus_ide_default_irq(ide_ioreg_t base){ return 0;}ide_ioreg_tapus_ide_default_io_base(int index){ return 0;}intapus_ide_check_region(ide_ioreg_t from, unsigned int extent){ return 0;}voidapus_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name){}voidapus_ide_release_region(ide_ioreg_t from, unsigned int extent){}voidapus_ide_fix_driveid(struct hd_driveid *id){ u_char *p = (u_char *)id; int i, j, cnt; u_char t; if (!MACH_IS_AMIGA && !MACH_IS_MAC) return; for (i = 0; i < num_driveid_types; i++) { cnt = driveid_types[i] & T_MASK_COUNT; switch (driveid_types[i] & T_MASK_TYPE) { case T_CHAR: p += cnt; break; case T_SHORT: for (j = 0; j < cnt; j++) { t = p[0]; p[0] = p[1]; p[1] = t; p += 2; } break; case T_INT: for (j = 0; j < cnt; j++) { t = p[0]; p[0] = p[3]; p[3] = t; t = p[1]; p[1] = p[2]; p[2] = t; p += 4; } break; case T_TEXT: for (j = 0; j < cnt; j += 2) { t = p[0]; p[0] = p[1]; p[1] = t; p += 2; } break; } }}__initvoid apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq){ if (data_port || ctrl_port) printk("apus_ide_init_hwif_ports: must not be called\n");}#endif/****************************************************** IRQ stuff */__apusstatic unsigned int apus_irq_cannonicalize(unsigned int irq){ return irq;}__apusint apus_get_irq_list(char *buf){#ifdef CONFIG_APUS extern int amiga_get_irq_list(char *buf); return amiga_get_irq_list (buf);#else return 0;#endif}/* IPL must be between 0 and 7 */__apusstatic inline void apus_set_IPL(unsigned long ipl){ APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT); APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK); APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | ((~ipl) & IPLEMU_IPLMASK)); APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);}__apusstatic inline unsigned long apus_get_IPL(void){ /* This returns the present IPL emulation level. */ unsigned long __f; APUS_READ(APUS_IPL_EMU, __f); return ((~__f) & IPLEMU_IPLMASK);}__apusstatic inline unsigned long apus_get_prev_IPL(struct pt_regs* regs){ /* The value saved in mq is the IPL_EMU value at the time of interrupt. The lower bits are the current interrupt level, the upper bits the requested level. Thus, to restore the IPL level to the post-interrupt state, we will need to use the lower bits. */ unsigned long __f = regs->mq; return ((~__f) & IPLEMU_IPLMASK);}#ifdef CONFIG_APUSvoid free_irq(unsigned int irq, void *dev_id){ extern void amiga_free_irq(unsigned int irq, void *dev_id); amiga_free_irq (irq, dev_id);}int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id){ extern int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); return amiga_request_irq (irq, handler, irqflags, devname, dev_id);}/* In Linux/m68k the sys_request_irq deals with vectors 0-7. That's what callers expect - but on Linux/APUS we actually use the IRQ_AMIGA_AUTO vectors (24-31), so we put this dummy function in between to adjust the vector argument (rather have cruft here than in the generic irq.c). */int sys_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id){ extern int request_sysirq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id); return request_sysirq(irq+IRQ_AMIGA_AUTO, handler, irqflags, devname, dev_id);}#endif__apusint apus_get_irq(struct pt_regs* regs){#ifdef CONFIG_APUS int level = apus_get_IPL();#ifdef __INTERRUPT_DEBUG printk("<%d:%d>", level, apus_get_prev_IPL(regs));#endif if (0 == level) return -8; if (7 == level) return -9; return level + IRQ_AMIGA_AUTO;#else return 0;#endif}__apusvoid apus_post_irq(struct pt_regs* regs, int level){#ifdef __INTERRUPT_DEBUG printk("{%d}", apus_get_prev_IPL(regs));#endif /* Restore IPL to the previous value */ apus_set_IPL(apus_get_prev_IPL(regs));}/****************************************************** keyboard */__apusstatic int apus_kbd_setkeycode(unsigned int scancode, unsigned int keycode){ return -EOPNOTSUPP;}__apusstatic int apus_kbd_getkeycode(unsigned int scancode){ return scancode > 127 ? -EINVAL : scancode;}__apusstatic int apus_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode){ *keycodep = keycode; return 1;}__apusstatic char apus_kbd_unexpected_up(unsigned char keycode){ return 0200;}__apus static void apus_kbd_leds(unsigned char leds){}__apus 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 */}__apusint __debug_ser_out( unsigned char c ){ custom.serdat = c | 0x100; mb(); while (!(custom.serdatr & 0x2000)) barrier(); return 1;}__apusunsigned 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;}__apusint __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;}__apusvoid __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');}__apusvoid __debug_print_string(char* s){ unsigned char c; while((c = *s++)) __debug_ser_out(c); __debug_ser_out('\n'); __debug_ser_out('\r');}__apusstatic void apus_progress(char *s, unsigned short value){ __debug_print_string(s);}/****************************************************** init *//* The number of spurious interrupts */volatile unsigned int num_spurious;#define NUM_IRQ_NODES 100static irq_node_t nodes[NUM_IRQ_NODES];extern void (*amiga_default_handler[AUTO_IRQS])(int, void *, struct pt_regs *);static const char *default_names[SYS_IRQS] = { "spurious int", "int1 handler", "int2 handler", "int3 handler", "int4 handler", "int5 handler", "int6 handler", "int7 handler"};irq_node_t *new_irq_node(void){ irq_node_t *node; short i; for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) if (!node->handler) return node; printk ("new_irq_node: out of nodes\n"); return NULL;}extern void amiga_enable_irq(unsigned int irq);extern void amiga_disable_irq(unsigned int irq);struct hw_interrupt_type amiga_irqctrl = { " Amiga ", NULL, NULL, amiga_enable_irq, amiga_disable_irq, 0, 0};__initvoid apus_init_IRQ(void){ int i; for ( i = 0 ; i < NR_IRQS ; i++ ) irq_desc[i].handler = &amiga_irqctrl; for (i = 0; i < NUM_IRQ_NODES; i++) nodes[i].handler = NULL; for (i = 0; i < AUTO_IRQS; i++) { if (amiga_default_handler[i] != NULL) sys_request_irq(i, amiga_default_handler[i], 0, default_names[i], NULL); } amiga_init_IRQ(); int_control.int_sti = __no_use_sti; int_control.int_cli = __no_use_cli; int_control.int_save_flags = __no_use_save_flags; int_control.int_restore_flags = __no_use_restore_flags;}__initvoid apus_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.setup_residual = NULL; ppc_md.get_cpuinfo = apus_get_cpuinfo; ppc_md.irq_cannonicalize = apus_irq_cannonicalize; ppc_md.init_IRQ = apus_init_IRQ; ppc_md.get_irq = apus_get_irq; ppc_md.post_irq = apus_post_irq;#ifdef CONFIG_HEARTBEAT ppc_md.heartbeat = apus_heartbeat; ppc_md.heartbeat_count = 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.nvram_read_val = NULL; ppc_md.nvram_write_val = NULL; /* 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 = apus_kbd_translate; ppc_md.kbd_unexpected_up = apus_kbd_unexpected_up; ppc_md.kbd_leds = apus_kbd_leds; ppc_md.kbd_init_hw = apus_kbd_init_hw;#ifdef CONFIG_MAGIC_SYSRQ ppc_md.kbd_sysrq_xlate = NULL;#endif#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) ppc_ide_md.insw = apus_ide_insw; ppc_ide_md.outsw = apus_ide_outsw; ppc_ide_md.default_irq = apus_ide_default_irq; ppc_ide_md.default_io_base = apus_ide_default_io_base; ppc_ide_md.ide_check_region = apus_ide_check_region; ppc_ide_md.ide_request_region = apus_ide_request_region; ppc_ide_md.ide_release_region = apus_ide_release_region; ppc_ide_md.fix_driveid = apus_ide_fix_driveid; ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports; ppc_ide_md.io_base = _IO_BASE;#endif }/*************************************************** coexistence */void __init adbdev_init(void){}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -