📄 cpuio.c
字号:
#include "config.h"#include "cpuio.h"#include "stddefs.h"#include "mpc860.h"#include "ether.h"#include "genlib.h"#include "arch_ppc.h"#include "bcsr.h"int (*remoteputchar)(), (*remotegetchar)(), (*remotegotachar)();int (*remoterawon)(), (*remoterawoff)();EPPC *IMMRBase;int ConsoleBaudRate;/* InitUART(): Refer to 16-340 MPC860 Users Manual for SMC Parameter RAM config. Refer to page 16-362 (MPC860 User Manual) for a UART example. Got a some of this from Motorola's website.*/voidInitUART(int baud){ volatile int timeout, baud_clock; volatile struct smc_uart_bd *rbd, *tbd; if (baud == 0) baud = ConsoleBaudRate; /* Keep track of the last baud rate, so that it can be used if the */ /* incoming baudrate is NULL. */ ConsoleBaudRate = baud; /* Set IMMRBase pointing to the MPC860's internal register memory map. */ IMMRBase = (EPPC *)(ppcMfimmr() & 0xFFFF0000); /* Set up the pin (muxed with PIP) to be SMTXD1/SMRXD1: */ /* (see page 16-460 of MPC860 Users Manual) */ IMMRBase->pip_pbpar |= 0x000000c0; IMMRBase->pip_pbdir &= 0xffffff3f; IMMRBase->pip_pbodr &= 0xff3f; /* Set up SI Mode Register to assign BRG1 to SMC1. */ /* (see page 16-114 of MPC860 Users Manual) */ IMMRBase->si_simode &= ~0x0000f000; /* NMSI mode, using BRG1. */ /* SDMA Control Register: */ IMMRBase->dma_sdcr = 0x0001; /* SMC Mode register (pg 16-352 MPC860 Users Manual): */ /* 8 data bits, 1 stop bit, no parity */ /* TE & RE not yet enabled. */ IMMRBase->smc_regs[SMC1_REG].smc_smcmr = 0x4820; /* Set up a very basic buffer descriptor configuration. */ /* Both transmit and receive will use only a 1-byte buffer, both of */ /* these buffers will be in DPRAM. */ rbd = &IMMRBase->qcp_or_ud.umd.u_rbd; tbd = &IMMRBase->qcp_or_ud.umd.u_tbd; /* Set parameter ram to point to buffer descriptors in DPRAM: */ /* Note that this will generate a compiler warning because we are */ /* casting a pointer to a short. This can be ignored because these */ /* two entries are offsets relative to the base of the IMMR, not the */ /* actual address. */ IMMRBase->PRAM[PAGE3].pg.other.smc_dsp1.psmc1.u1.rbase = (ushort)rbd; IMMRBase->PRAM[PAGE3].pg.other.smc_dsp1.psmc1.u1.tbase = (ushort)tbd; /* Set RFCR,TFCR -- Rx,Tx Function Code */ /* Normal Operation and Motorola byte ordering */ IMMRBase->PRAM[PAGE3].pg.other.smc_dsp1.psmc1.u1.rfcr = 0x10; IMMRBase->PRAM[PAGE3].pg.other.smc_dsp1.psmc1.u1.tfcr = 0x10; /* MRBLR = MAX buffer length */ IMMRBase->PRAM[PAGE3].pg.other.smc_dsp1.psmc1.u1.mrblr = 1; /* MAX_IDL = Disable MAX Idle Feature */ IMMRBase->PRAM[PAGE3].pg.other.smc_dsp1.psmc1.u1.max_idl = 0; IMMRBase->PRAM[PAGE3].pg.other.smc_dsp1.psmc1.u1.brkln = 0; /* BRKEC = No break condition occurred */ IMMRBase->PRAM[PAGE3].pg.other.smc_dsp1.psmc1.u1.brkec = 0; /* BRKCR = 1 break char sent on top XMIT */ IMMRBase->PRAM[PAGE3].pg.other.smc_dsp1.psmc1.u1.brkcr = 1; /* Mask all interrupts: */ IMMRBase->smc_regs[SMC1_REG].smc_smcm = 0; IMMRBase->cpmi_cicr = 0; /* Disable all CPM interrups */ IMMRBase->cpmi_cipr = 0xFFFFFFFF; /* Clear all pending interrupt events */ IMMRBase->cpmi_cimr = 0; /* Mask all event interrupts */ /* Initialize buffer descriptors: */ rbd->status = 0xa000; /* 16-354 */ rbd->length = 1; rbd->baddr = IMMRBase->qcp_or_ud.umd.u_rxbuf; tbd->status = 0x2000; /* 16-359 */ tbd->length = 1; tbd->baddr = IMMRBase->qcp_or_ud.umd.u_txbuf; /* Clear any events: */ IMMRBase->smc_regs[SMC1_REG].smc_smce = 0xFF; /* Issue CPM Command to init RX/TX params (wait for completion): */ IMMRBase->cp_cr = 0x0091; timeout = 500000; while(IMMRBase->cp_cr & 0x0001) { timeout--; if (timeout <= 0) break; } /* Setup baudrate based on incoming baud value: * Clock is 4Mhz multplied up based on upper 12 bits of PLPRCR. * (0x10000 | (((baud_clock/(baud*16)) - 1) << 1)) */ baud_clock = (((IMMRBase->clkr_plprcr & 0xfff00000) >> 20) + 1) * MON_CPU_CLOCK; IMMRBase->brgc1 = (0x10000 | (((baud_clock/(baud*16)) - 1) << 1)); /* SMC Mode register (pg 16-352 MPC860 Users Manual): */ /* TE & RE now enabled. */ IMMRBase->smc_regs[SMC1_REG].smc_smcmr = 0x4823; /* Null out the remote "CHARFUNC_" functions. */ InitRemoteIO();}intdevInit(int baud){ InitUART(baud); return(0);}voidsignal_lamp_on(void){ *(vulong *)BCSR4_BASE &= ~SIGNAL_LAMP;}voidsignal_lamp_off(void){ *(vulong *)BCSR4_BASE |= SIGNAL_LAMP;}/* rawon() & rawoff(): Used primarily by xmodem. When xmodem runs, it must be assured that the interface is in RAW mode. For the case of the monitor alone, it will always be in a raw mode. These functions are primarily for use when an application has re-loaded the serial driver and may have put it in a non-raw mode. The mon_con() calls CHARFUNC_RAWMODEON and CHARFUNC_RAWMODEOFF establish these pointers.*/voidrawon(void){ if (remoterawon) remoterawon();}voidrawoff(void){ if (remoterawoff) remoterawoff();}/* rputchar(): Raw put char.*/intrputchar(char c){ volatile struct smc_uart_bd *tbd; /* First check to see if the default rputchar() function has */ /* been overridden... */ if (remoteputchar) { remoteputchar(c); return(c); } tbd = &IMMRBase->qcp_or_ud.umd.u_tbd; /* Wait for ready bit to clear... */ while(1) { if (!(tbd->status & 0x8000)) break; }#if INCLUDE_ETHERNET SendIPMonChar(c,0);#endif *tbd->baddr = (uchar)c; tbd->status |= 0x8000; return((int)c);}voidflush_console(void){ int i; volatile struct smc_uart_bd *tbd; if (remoteputchar) return; /* Wait (with a timeout) till the xmit buffer is empty. */ tbd = &IMMRBase->qcp_or_ud.umd.u_tbd; for(i=0;i<100000;i++) { if (!(tbd->status & 0x8000)) break; }}/* getchar(): Block on the Uart's status until a byte is available in the receive buffer, then return with it.*/int getchar(){ char c; int ledtoggle; volatile struct smc_uart_bd *rbd; /* First check to see if the default getchar() function has */ /* been overridden... */ if (remotegetchar) return(remotegetchar()); rbd = &IMMRBase->qcp_or_ud.umd.u_rbd; /* Wait for character present: */ ledtoggle = 0; /* Blink the AUX LED to indicate that we are alive. */ while(rbd->status & 0x8000) { switch(++ledtoggle) { case LOOPS_PER_SECOND: signal_lamp_on(); break; case (LOOPS_PER_SECOND * 2): signal_lamp_off(); ledtoggle = 0; break; }#if INCLUDE_ETHERNET pollethernet();#endif } /* Retrieve character and clear status bit: */ c = *rbd->baddr; rbd->status |= 0x8000; return((int)c);}intgotachar(){ if (IMMRBase->qcp_or_ud.umd.u_rbd.status & 0x8000) return(0); else return(1);}/* Enable/Disable BreakInterrupt(): Called by monitor to simply enable or disable the processor's ability to generate an interrupt when a break condition is detected on SCC1 which is used as the debug port.*/voidEnableBreakInterrupt(){}voidDisableBreakInterrupt(){}/* assignputchar(): This allows the default rputchar function to be overridden with another function. This is particularly useful for this processor because if an application uses it's own serial port driver, then all of the buffer descriptor stuff in the monitor is overridden so a call to rputchar() after the application has taken over and re-loaded the buffer descriptors would not work. Being able to assign a remote rputchar() function allows the application to take over the uart, but still allows it to call monitor functions that may call rputchar() (which would be directed back to the application's putchar function).*/voidassignputchar(func)int (*func)();{ remoteputchar = func;}voidassigngetchar(func)int (*func)();{ remotegetchar = func;}/* NA here ... */voidsetTraceBit(){}voidclrTraceBit(){}char *portSize(unsigned long ps){ switch(ps) { case 0x00000c00: return("rsvd"); case 0x00000000: return("32"); case 0x00000400: return(" 8"); case 0x00000800: return("16"); } return("???");}char *CSDeviceNames[] = { "Boot Flash SIMM", "BCSRs", "DRAM Bank 1", "", "", "", "", "",};voidCSInfo(){ int i; vulong *br, *or; /* Set IMMRBase pointing to the MPC860's internal register memory map. */ IMMRBase = (EPPC *)(ppcMfimmr() & 0xFFFF0000); printf("\n%s Chip Select Ctrl-Regs:\n",CPU_NAME); br = &IMMRBase->memc_br0; or = &IMMRBase->memc_or0; for(i=0;i<8;i++,br+=2,or+=2) { printf(" CS%d %s...\n",i,CSDeviceNames[i]); printf(" BR%d: 0x%08x, OR%d: 0x%08x\n",i,*br,i,*or); printf(" Base: 0x%08x %s, %s bit, read-%s\n", (ulong)(*br & 0xffff8000), (*br & 0x00000001) ? " valid" : "invalid", portSize(*br & 0x00000c00), (*br & 0x00000100) ? "only " : "write"); }}voidinitCPUio(){ ulong bcsr1; uchar *cp, *end; /* Set IMMRBase pointing to the MPC860's internal register memory map. * The IMMR register should have already been set in reset.s; so here * we are just grabbing a copy for C-use. */ IMMRBase = (EPPC *)(ppcMfimmr() & 0xFFFF0000); /* Clear the internal RAM of the MPC860: */ cp = (uchar *)&(IMMRBase->qcp_or_ud.umd); end = cp + 0x2000; while(cp < end) *cp++ = 0; /* At startup, the board is configured with ethernet and rs232 * disabled. Set the appropriate bits in BCSR1 to enable these... */ bcsr1 = *(ulong *)BCSR1_BASE; bcsr1 &= ~RS232DISABLE_1; bcsr1 &= ~RS232DISABLE_2; bcsr1 &= ~ETHERDISABLE; *(ulong *)BCSR1_BASE = bcsr1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -