📄 prep_setup.c
字号:
/* 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. */static void __initmk48t59_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);}static 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");}static 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 */}/* * On IBM PReP's, power management is handled by a Signetics 87c750 behind the * Utah component on the ISA bus. To access the 750 you must write a series of * nibbles to port 0x82a (decoded by the Utah). This is described somewhat in * the IBM Carolina Technical Specification. * -Hollis */static void __preputah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value){ /* * byte1: 0 0 0 1 0 d a5 a4 * byte2: 0 0 0 1 a3 a2 a1 a0 * * d = the bit's value, enabled or disabled * (a5 a4 a3) = the byte number, minus 20 * (a2 a1 a0) = the bit number * * example: set the 5th bit of byte 21 (21.5) * a5 a4 a3 = 001 (byte 1) * a2 a1 a0 = 101 (bit 5) * * byte1 = 0001 0100 (0x14) * byte2 = 0001 1101 (0x1d) */ unsigned char byte1=0x10, byte2=0x10; const unsigned int pm_reg_1=0x82a; /* ISA address */ /* the 750's '20.0' is accessed as '0.0' through Utah (which adds 20) */ bytenum -= 20; byte1 |= (!!value) << 2; /* set d */ byte1 |= (bytenum >> 1) & 0x3; /* set a5, a4 */ byte2 |= (bytenum & 0x1) << 3; /* set a3 */ byte2 |= bitnum & 0x7; /* set a2, a1, a0 */ outb(byte1, pm_reg_1); /* first nibble */ mb(); udelay(100); /* important: let controller recover */ outb(byte2, pm_reg_1); /* second nibble */ mb(); udelay(100); /* important: let controller recover */}static void __prepprep_power_off(void){ if ( _prep_type == _PREP_IBM) { /* tested on: * Carolina's: 7248-43P, 6070 (PowerSeries 850) * should work on: * Carolina: 6050 (PowerSeries 830) * 7043-140 (Tiger 1) */ unsigned long flags; __cli(); /* set exception prefix high - to the prom */ save_flags( flags ); restore_flags( flags|MSR_IP ); utah_sig87c750_setbit(21, 5, 1); /* set bit 21.5, "PMEXEC_OFF" */ while ( 1 ) ; /* not reached */ } else { prep_halt(); }}static unsigned int __prepprep_irq_cannonicalize(u_int irq){ if (irq == 2) { return 9; } else { return irq; }}static int __prepprep_get_irq(struct pt_regs *regs){ return i8259_irq();} static void __initprep_init_IRQ(void){ int i; if (OpenPIC_Addr != NULL) openpic_init(1, NUM_8259_INTERRUPTS, 0, -1); for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ ) irq_desc[i].handler = &i8259_pic; i8259_init(0xbffffff0); /* PCI interrupt ack address for MPC105 and 106 */}#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)/* * IDE stuff. */static 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; case 0xfff0: return 14; /* MCP(N)750 ide0 */ case 0xffe0: return 15; /* MCP(N)750 ide1 */ default: return 0; }}static 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; }}static int __prepprep_ide_check_region(ide_ioreg_t from, unsigned int extent){ return check_region(from, extent);}static void __prepprep_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name){ request_region(from, extent, name);}static void __prepprep_ide_release_region(ide_ioreg_t from, unsigned int extent){ release_region(from, extent);}static 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;}#endif#ifdef CONFIG_SMP/* PReP (MTX) support */static int __initsmp_prep_probe(void){ extern int mot_multi; if (mot_multi) { openpic_request_IPIs(); smp_hw_index[1] = 1; return 2; } return 1;}static void __initsmp_prep_kick_cpu(int nr){ *(unsigned long *)KERNELBASE = nr; asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); printk("CPU1 reset, waiting\n");}static void __initsmp_prep_setup_cpu(int cpu_nr){ if (OpenPIC_Addr) do_openpic_setup_cpu();}static struct smp_ops_t prep_smp_ops __prepdata = { smp_openpic_message_pass, smp_prep_probe, smp_prep_kick_cpu, smp_prep_setup_cpu,};#endif /* CONFIG_SMP *//* * This finds the amount of physical ram and does necessary * setup for prep. This is pretty architecture specific so * this will likely stay separate from the pmac. * -- Cort */static unsigned long __initprep_find_end_of_memory(void){ unsigned long total = 0; extern unsigned int boot_mem_size;#ifdef CONFIG_PREP_RESIDUAL total = res->TotalMemory;#endif if (total == 0 && boot_mem_size != 0) total = boot_mem_size; else if (total == 0) { /* * I need a way to probe the amount of memory if the residual * data doesn't contain it. -- Cort */ total = 0x02000000; printk(KERN_INFO "Ramsize from residual data was 0" " -- defaulting to %ldM\n", total>>20); } return (total);}/* * Setup the bat mappings we're going to load that cover * the io areas. RAM was mapped by mapin_ram(). * -- Cort */static void __initprep_map_io(void){ io_block_mapping(0x80000000, PREP_ISA_IO_BASE, 0x10000000, _PAGE_IO); io_block_mapping(0xf0000000, PREP_ISA_MEM_BASE, 0x08000000, _PAGE_IO);}static void __initprep_init2(void){#ifdef CONFIG_NVRAM request_region(PREP_NVRAM_AS0, 0x8, "nvram");#endif request_region(0x20,0x20,"pic1"); request_region(0xa0,0x20,"pic2"); request_region(0x00,0x20,"dma1"); request_region(0x40,0x20,"timer"); request_region(0x80,0x10,"dma page reg"); request_region(0xc0,0x20,"dma2");}void __initprep_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7){#ifdef CONFIG_PREP_RESIDUAL /* make a copy of residual data */ if ( r3 ) { memcpy((void *)res,(void *)(r3+KERNELBASE), sizeof(RESIDUAL)); }#endif#ifdef CONFIG_BLK_DEV_INITRD if ( r4 ) { initrd_start = r4 + KERNELBASE; initrd_end = r5 + KERNELBASE; }#endif /* CONFIG_BLK_DEV_INITRD */ /* Copy cmd_line parameters */ if ( r6 ) { *(char *)(r7 + KERNELBASE) = 0; strcpy(cmd_line, (char *)(r6 + KERNELBASE)); } 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 */#ifdef CONFIG_PREP_RESIDUAL if ( res->ResidualLength != 0 ) { if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) ) _prep_type = _PREP_IBM; else _prep_type = _PREP_Motorola; } else /* assume motorola if no residual (netboot?) */#endif { _prep_type = _PREP_Motorola; } ppc_md.setup_arch = prep_setup_arch; ppc_md.show_percpuinfo = prep_show_percpuinfo; ppc_md.show_cpuinfo = prep_show_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 = prep_init2; 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_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; } ppc_md.find_end_of_memory = prep_find_end_of_memory; ppc_md.setup_io_mappings = prep_map_io;#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) 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.ide_init_hwif = prep_ide_init_hwif_ports;#endif#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_SMP ppc_md.smp_ops = &prep_smp_ops;#endif /* CONFIG_SMP */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -