📄 prep_setup.c
字号:
tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB); if (tmp & MK48T59_RTC_CB_STOP) { printk("Warning: RTC was stopped, date will be wrong.\n"); ppc_md.nvram_write_val(MK48T59_RTC_CONTROLB, tmp & ~MK48T59_RTC_CB_STOP); /* Low frequency crystal oscillators may take a very long * time to startup and stabilize. For now just ignore the * the issue, but attempting to calibrate the decrementer * from the RTC just after this wakeup is likely to be very * inaccurate. Firmware should not allow to load * the OS with the clock stopped anyway... */ } /* Ensure that the clock registers are updated */ tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); tmp &= ~(MK48T59_RTC_CA_READ | MK48T59_RTC_CA_WRITE); ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, tmp); return 0;}/* We use the NVRAM RTC to time a second to calibrate the decrementer, * the RTC registers have just been set up in the right state by the * preceding routine. */void __init mk48t59_calibrate_decr(void){ unsigned long freq; unsigned long t1; unsigned char save_control; long i; unsigned char sec; /* Make sure the time is not stopped. */ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB); ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, (save_control & (~MK48T59_RTC_CB_STOP))); /* Now make sure the read bit is off so the value will change. */ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); save_control &= ~MK48T59_RTC_CA_READ; ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control); /* Read the seconds value to see when it changes. */ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); /* Actually this is bad for precision, we should have a loop in * which we only read the seconds counter. nvram_read_val writes * the address bytes on every call and this takes a lot of time. * Perhaps an nvram_wait_change method returning a time * stamp with a loop count as parameter would be the solution. */ for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */ t1 = get_tbl(); if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) { break; } } sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); for (i = 0 ; i < 1000000 ; i++) { /* Should take up 1 second... */ freq = get_tbl()-t1; if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) { break; } } printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", freq/1000000, freq%1000000); tb_ticks_per_jiffy = freq / HZ; tb_to_us = mulhwu_scale_factor(freq, 1000000);}void __prepprep_restart(char *cmd){ unsigned long i = 10000; __cli(); /* set exception prefix high - to the prom */ _nmask_and_or_msr(0, MSR_IP); /* make sure bit 0 (reset) is a 0 */ outb( inb(0x92) & ~1L , 0x92 ); /* signal a reset to system control port A - soft reset */ outb( inb(0x92) | 1 , 0x92 ); while ( i != 0 ) i++; panic("restart failed\n");}/* * This function will restart a board regardless of port 92 functionality */void __prepprep_direct_restart(char *cmd){ u32 jumpaddr=0xfff00100; u32 defaultmsr=MSR_IP; /* * This will ALWAYS work regardless of port 92 * functionality */ __cli(); __asm__ __volatile__("\n\ mtspr 26, %1 /* SRR0 */ mtspr 27, %0 /* SRR1 */ rfi" : : "r" (defaultmsr), "r" (jumpaddr)); /* * Not reached */}void __prepprep_halt(void){ unsigned long flags; __cli(); /* set exception prefix high - to the prom */ save_flags( flags ); restore_flags( flags|MSR_IP ); /* make sure bit 0 (reset) is a 0 */ outb( inb(0x92) & ~1L , 0x92 ); /* signal a reset to system control port A - soft reset */ outb( inb(0x92) | 1 , 0x92 ); while ( 1 ) ; /* * Not reached */}void __prepprep_power_off(void){ prep_halt();}int __prepprep_setup_residual(char *buffer){ int len = 0; /* PREP's without residual data will give incorrect values here */ len += sprintf(len+buffer, "clock\t\t: "); if ( res->ResidualLength ) len += sprintf(len+buffer, "%ldMHz\n", (res->VitalProductData.ProcessorHz > 1024) ? res->VitalProductData.ProcessorHz>>20 : res->VitalProductData.ProcessorHz); else len += sprintf(len+buffer, "???\n"); return len;}u_int __prepprep_irq_cannonicalize(u_int irq){ if (irq == 2) { return 9; } else { return irq; }}#if 0void __prepprep_do_IRQ(struct pt_regs *regs, int cpu, int isfake){ int irq; if ( (irq = i8259_irq(0)) < 0 ) { printk(KERN_DEBUG "Bogus interrupt from PC = %lx\n", regs->nip); ppc_spurious_interrupts++; return; } ppc_irq_dispatch_handler( regs, irq );}#endifint __prepprep_get_irq(struct pt_regs *regs){ return i8259_irq(smp_processor_id());} void __initprep_init_IRQ(void){ int i; if (OpenPIC != NULL) { for ( i = 16 ; i < 36 ; i++ ) irq_desc[i].handler = &open_pic; openpic_init(1); } for ( i = 0 ; i < 16 ; i++ ) irq_desc[i].handler = &i8259_pic; i8259_init();#ifdef CONFIG_SMP request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS), openpic_ipi_action, 0, "IPI0", 0);#endif /* CONFIG_SMP */}#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)/* * IDE stuff. */void __prepprep_ide_insw(ide_ioreg_t port, void *buf, int ns){ _insw((unsigned short *)((port)+_IO_BASE), buf, ns);}void __prepprep_ide_outsw(ide_ioreg_t port, void *buf, int ns){ _outsw((unsigned short *)((port)+_IO_BASE), buf, ns);}int __prepprep_ide_default_irq(ide_ioreg_t base){ switch (base) { case 0x1f0: return 13; case 0x170: return 13; case 0x1e8: return 11; case 0x168: return 10; default: return 0; }}ide_ioreg_t __prepprep_ide_default_io_base(int index){ switch (index) { case 0: return 0x1f0; case 1: return 0x170; case 2: return 0x1e8; case 3: return 0x168; default: return 0; }}int __prepprep_ide_check_region(ide_ioreg_t from, unsigned int extent){ return check_region(from, extent);}void __prepprep_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name){ request_region(from, extent, name);}void __prepprep_ide_release_region(ide_ioreg_t from, unsigned int extent){ release_region(from, extent);}void __prepprep_ide_fix_driveid(struct hd_driveid *id){}void __initprep_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq){ ide_ioreg_t reg = data_port; int i; for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { hw->io_ports[i] = reg; reg += 1; } if (ctrl_port) { hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; } else { hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; } if (irq != NULL) *irq = 0;}#endifvoid __initprep_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7){ /* make a copy of residual data */ if ( r3 ) { memcpy((void *)res,(void *)(r3+KERNELBASE), sizeof(RESIDUAL)); } isa_io_base = PREP_ISA_IO_BASE; isa_mem_base = PREP_ISA_MEM_BASE; pci_dram_offset = PREP_PCI_DRAM_OFFSET; ISA_DMA_THRESHOLD = 0x00ffffff; DMA_MODE_READ = 0x44; DMA_MODE_WRITE = 0x48; /* figure out what kind of prep workstation we are */ if ( res->ResidualLength != 0 ) { if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) ) _prep_type = _PREP_IBM; else if (!strncmp(res->VitalProductData.PrintableModel, "Radstone",8)) { extern char *Motherboard_map_name; _prep_type = _PREP_Radstone; Motherboard_map_name= res->VitalProductData.PrintableModel; } else _prep_type = _PREP_Motorola; } else /* assume motorola if no residual (netboot?) */ { _prep_type = _PREP_Motorola; } prep_setup_pci_ptrs(); ppc_md.setup_arch = prep_setup_arch; ppc_md.setup_residual = prep_setup_residual; ppc_md.get_cpuinfo = prep_get_cpuinfo; ppc_md.irq_cannonicalize = prep_irq_cannonicalize; ppc_md.init_IRQ = prep_init_IRQ; /* this gets changed later on if we have an OpenPIC -- Cort */ ppc_md.get_irq = prep_get_irq; ppc_md.init = NULL; ppc_md.restart = prep_restart; ppc_md.power_off = prep_power_off; ppc_md.halt = prep_halt; ppc_md.time_init = NULL; if (_prep_type == _PREP_Radstone) { /* * We require a direct restart as port 92 does not work on * all Radstone boards */ ppc_md.restart = prep_direct_restart; /* * The RTC device used varies according to board type */ if(((ucSystemType==RS_SYS_TYPE_PPC1) && (ucBoardRevMaj>=5)) || (ucSystemType==RS_SYS_TYPE_PPC1a)) { ppc_md.set_rtc_time = mk48t59_set_rtc_time; ppc_md.get_rtc_time = mk48t59_get_rtc_time; ppc_md.time_init = mk48t59_init; } else { ppc_md.set_rtc_time = mc146818_set_rtc_time; ppc_md.get_rtc_time = mc146818_get_rtc_time; } /* * Determine the decrementer rate from the residual data */ ppc_md.calibrate_decr = prep_res_calibrate_decr; } else if (_prep_type == _PREP_IBM) { ppc_md.set_rtc_time = mc146818_set_rtc_time; ppc_md.get_rtc_time = mc146818_get_rtc_time; ppc_md.calibrate_decr = prep_calibrate_decr; } else { ppc_md.set_rtc_time = mk48t59_set_rtc_time; ppc_md.get_rtc_time = mk48t59_get_rtc_time; ppc_md.calibrate_decr = mk48t59_calibrate_decr; ppc_md.time_init = mk48t59_init; }#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) ppc_ide_md.insw = prep_ide_insw; ppc_ide_md.outsw = prep_ide_outsw; ppc_ide_md.default_irq = prep_ide_default_irq; ppc_ide_md.default_io_base = prep_ide_default_io_base; ppc_ide_md.ide_check_region = prep_ide_check_region; ppc_ide_md.ide_request_region = prep_ide_request_region; ppc_ide_md.ide_release_region = prep_ide_release_region; ppc_ide_md.fix_driveid = prep_ide_fix_driveid; ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports;#endif ppc_ide_md.io_base = _IO_BASE;#ifdef CONFIG_VT ppc_md.kbd_setkeycode = pckbd_setkeycode; ppc_md.kbd_getkeycode = pckbd_getkeycode; ppc_md.kbd_translate = pckbd_translate; ppc_md.kbd_unexpected_up = pckbd_unexpected_up; ppc_md.kbd_leds = pckbd_leds; ppc_md.kbd_init_hw = pckbd_init_hw;#ifdef CONFIG_MAGIC_SYSRQ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate; SYSRQ_KEY = 0x54;#endif#endif}#ifdef CONFIG_SOUND_MODULEEXPORT_SYMBOL(ppc_cs4232_dma);EXPORT_SYMBOL(ppc_cs4232_dma2);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -