📄 start_32.c
字号:
/* * Copyright (C) 1996 Paul Mackerras. */#include <linux/config.h>#include <linux/string.h>#include <asm/machdep.h>#include <asm/io.h>#include <asm/page.h>#include <linux/adb.h>#include <linux/pmu.h>#include <linux/cuda.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/bitops.h>#include <asm/xmon.h>#include <asm/prom.h>#include <asm/bootx.h>#include <asm/machdep.h>#include <asm/errno.h>#include <asm/pmac_feature.h>#include <asm/processor.h>#include <asm/delay.h>#include <asm/btext.h>#include <asm/time.h>#include "nonstdio.h"static volatile unsigned char __iomem *sccc, *sccd;unsigned int TXRDY, RXRDY, DLAB;static int use_serial;static int use_screen;static int via_modem;static int xmon_use_sccb;static struct device_node *channel_node;void buf_access(void){ if (DLAB) sccd[3] &= ~DLAB; /* reset DLAB */}extern int adb_init(void);#ifdef CONFIG_PPC_CHRP/* * This looks in the "ranges" property for the primary PCI host bridge * to find the physical address of the start of PCI/ISA I/O space. * It is basically a cut-down version of pci_process_bridge_OF_ranges. */static unsigned long chrp_find_phys_io_base(void){ struct device_node *node; unsigned int *ranges; unsigned long base = CHRP_ISA_IO_BASE; int rlen = 0; int np; node = find_devices("isa"); if (node != NULL) { node = node->parent; if (node == NULL || node->type == NULL || strcmp(node->type, "pci") != 0) node = NULL; } if (node == NULL) node = find_devices("pci"); if (node == NULL) return base; ranges = (unsigned int *) get_property(node, "ranges", &rlen); np = prom_n_addr_cells(node) + 5; while ((rlen -= np * sizeof(unsigned int)) >= 0) { if ((ranges[0] >> 24) == 1 && ranges[2] == 0) { /* I/O space starting at 0, grab the phys base */ base = ranges[np - 3]; break; } ranges += np; } return base;}#endif /* CONFIG_PPC_CHRP */void xmon_map_scc(void){#ifdef CONFIG_PPC_MULTIPLATFORM volatile unsigned char __iomem *base; if (_machine == _MACH_Pmac) { struct device_node *np; unsigned long addr;#ifdef CONFIG_BOOTX_TEXT if (!use_screen && !use_serial && !machine_is_compatible("iMac")) { /* see if there is a keyboard in the device tree with a parent of type "adb" */ for (np = find_devices("keyboard"); np; np = np->next) if (np->parent && np->parent->type && strcmp(np->parent->type, "adb") == 0) break; /* needs to be hacked if xmon_printk is to be used from within find_via_pmu() */#ifdef CONFIG_ADB_PMU if (np != NULL && boot_text_mapped && find_via_pmu()) use_screen = 1;#endif#ifdef CONFIG_ADB_CUDA if (np != NULL && boot_text_mapped && find_via_cuda()) use_screen = 1;#endif } if (!use_screen && (np = find_devices("escc")) != NULL) { /* * look for the device node for the serial port * we're using and see if it says it has a modem */ char *name = xmon_use_sccb? "ch-b": "ch-a"; char *slots; int l; np = np->child; while (np != NULL && strcmp(np->name, name) != 0) np = np->sibling; if (np != NULL) { /* XXX should parse this properly */ channel_node = np; slots = get_property(np, "slot-names", &l); if (slots != NULL && l >= 10 && strcmp(slots+4, "Modem") == 0) via_modem = 1; } } btext_drawstring("xmon uses "); if (use_screen) btext_drawstring("screen and keyboard\n"); else { if (via_modem) btext_drawstring("modem on "); btext_drawstring(xmon_use_sccb? "printer": "modem"); btext_drawstring(" port\n"); }#endif /* CONFIG_BOOTX_TEXT */#ifdef CHRP_ESCC addr = 0xc1013020;#else addr = 0xf3013020;#endif TXRDY = 4; RXRDY = 1; np = find_devices("mac-io"); if (np && np->n_addrs) addr = np->addrs[0].address + 0x13020; base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE); sccc = base + (addr & ~PAGE_MASK); sccd = sccc + 0x10; } else { base = (volatile unsigned char *) isa_io_base;#ifdef CONFIG_PPC_CHRP if (_machine == _MACH_chrp) base = (volatile unsigned char __iomem *) ioremap(chrp_find_phys_io_base(), 0x1000);#endif sccc = base + 0x3fd; sccd = base + 0x3f8; if (xmon_use_sccb) { sccc -= 0x100; sccd -= 0x100; } TXRDY = 0x20; RXRDY = 1; DLAB = 0x80; }#elif defined(CONFIG_GEMINI) /* should already be mapped by the kernel boot */ sccc = (volatile unsigned char __iomem *) 0xffeffb0d; sccd = (volatile unsigned char __iomem *) 0xffeffb08; TXRDY = 0x20; RXRDY = 1; DLAB = 0x80;#elif defined(CONFIG_405GP) sccc = (volatile unsigned char __iomem *)0xef600305; sccd = (volatile unsigned char __iomem *)0xef600300; TXRDY = 0x20; RXRDY = 1; DLAB = 0x80;#endif /* platform */}static int scc_initialized = 0;void xmon_init_scc(void);extern void cuda_poll(void);static inline void do_poll_adb(void){#ifdef CONFIG_ADB_PMU if (sys_ctrler == SYS_CTRLER_PMU) pmu_poll_adb();#endif /* CONFIG_ADB_PMU */#ifdef CONFIG_ADB_CUDA if (sys_ctrler == SYS_CTRLER_CUDA) cuda_poll();#endif /* CONFIG_ADB_CUDA */}int xmon_write(void *ptr, int nb){ char *p = ptr; int i, c, ct;#ifdef CONFIG_SMP static unsigned long xmon_write_lock; int lock_wait = 1000000; int locked; while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0) if (--lock_wait == 0) break;#endif#ifdef CONFIG_BOOTX_TEXT if (use_screen) { /* write it on the screen */ for (i = 0; i < nb; ++i) btext_drawchar(*p++); goto out; }#endif if (!scc_initialized) xmon_init_scc(); ct = 0; for (i = 0; i < nb; ++i) { while ((*sccc & TXRDY) == 0) do_poll_adb(); c = p[i]; if (c == '\n' && !ct) { c = '\r'; ct = 1; --i; } else { ct = 0; } buf_access(); *sccd = c; eieio(); } out:#ifdef CONFIG_SMP if (!locked) clear_bit(0, &xmon_write_lock);#endif return nb;}int xmon_wants_key;int xmon_adb_keycode;#ifdef CONFIG_BOOTX_TEXTstatic int xmon_adb_shiftstate;static unsigned char xmon_keytab[128] = "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */ "yt123465=97-80]o" /* 0x10 - 0x1f */ "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */ "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */static unsigned char xmon_shift_keytab[128] = "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */ "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */ "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */ "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */static int xmon_get_adb_key(void){ int k, t, on; xmon_wants_key = 1; for (;;) { xmon_adb_keycode = -1; t = 0; on = 0; do { if (--t < 0) { on = 1 - on; btext_drawchar(on? 0xdb: 0x20); btext_drawchar('\b'); t = 200000; } do_poll_adb(); } while (xmon_adb_keycode == -1); k = xmon_adb_keycode; if (on) btext_drawstring(" \b"); /* test for shift keys */ if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) { xmon_adb_shiftstate = (k & 0x80) == 0; continue; } if (k >= 0x80) continue; /* ignore up transitions */ k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k]; if (k != 0) break; } xmon_wants_key = 0; return k;}#endif /* CONFIG_BOOTX_TEXT */int xmon_readchar(void){#ifdef CONFIG_BOOTX_TEXT if (use_screen) return xmon_get_adb_key();#endif if (!scc_initialized) xmon_init_scc(); while ((*sccc & RXRDY) == 0) do_poll_adb(); buf_access(); return *sccd;}int xmon_read_poll(void){ if ((*sccc & RXRDY) == 0) { do_poll_adb(); return -1; } buf_access(); return *sccd;}static unsigned char scc_inittab[] = { 13, 0, /* set baud rate divisor */ 12, 1, 14, 1, /* baud rate gen enable, src=rtxc */ 11, 0x50, /* clocks = br gen */ 5, 0xea, /* tx 8 bits, assert DTR & RTS */ 4, 0x46, /* x16 clock, 1 stop */ 3, 0xc1, /* rx enable, 8 bits */};void xmon_init_scc(void){ if ( _machine == _MACH_chrp ) { sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */ sccd[0] = 12; eieio(); /* DLL = 9600 baud */ sccd[1] = 0; eieio(); sccd[2] = 0; eieio(); /* FCR = 0 */ sccd[3] = 3; eieio(); /* LCR = 8N1 */ sccd[1] = 0; eieio(); /* IER = 0 */ } else if ( _machine == _MACH_Pmac ) { int i, x; unsigned long timeout; if (channel_node != 0) pmac_call_feature( PMAC_FTR_SCC_ENABLE, channel_node, PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1); printk(KERN_INFO "Serial port locked ON by debugger !\n"); if (via_modem && channel_node != 0) { unsigned int t0; pmac_call_feature( PMAC_FTR_MODEM_ENABLE, channel_node, 0, 1); printk(KERN_INFO "Modem powered up by debugger !\n"); t0 = get_tbl(); timeout = 3 * tb_ticks_per_sec; if (timeout == 0) /* assume 25MHz if tb_ticks_per_sec not set */ timeout = 75000000; while (get_tbl() - t0 < timeout) eieio(); } /* use the B channel if requested */ if (xmon_use_sccb) { sccc = (volatile unsigned char *) ((unsigned long)sccc & ~0x20); sccd = sccc + 0x10; } for (i = 20000; i != 0; --i) { x = *sccc; eieio(); } *sccc = 9; eieio(); /* reset A or B side */ *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio(); for (i = 0; i < sizeof(scc_inittab); ++i) { *sccc = scc_inittab[i]; eieio(); } } scc_initialized = 1; if (via_modem) { for (;;) { xmon_write("ATE1V1\r", 7); if (xmon_expect("OK", 5)) { xmon_write("ATA\r", 4); if (xmon_expect("CONNECT", 40)) break; } xmon_write("+++", 3); xmon_expect("OK", 3); } }}void xmon_enter(void){#ifdef CONFIG_ADB_PMU if (_machine == _MACH_Pmac) { pmu_suspend(); }#endif}void xmon_leave(void){#ifdef CONFIG_ADB_PMU if (_machine == _MACH_Pmac) { pmu_resume(); }#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -