⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p16550u.c

📁 mips架构的bootloader,99左右的版本 但源代码现在没人更新了
💻 C
字号:
/************************************************************** File: lib/p16550u.c* Purpose: PMON driver for 16550-like UART in RAP chip.* Author: Phil Bunce (pjb@carmel.com)* Revision History:*	970827	Start of revision history*	980701	Merged into PMON5*	980817	Switched over to Russell's version.*	980817	Added divisors for 200B*//** Desc: Driver for the 16550U UART to be used with PMON.  This UART is*       a modified version of the SWAN which is used in the RAP.*       Assumes FIFO Polled Mode of operation.**       The functions which are handled are:*        1) OP_RXRDY   Reciver FIFO ready?*        2) OP_TXRDY   Transmitter FIFO ready?*        3) OP_TX      Send data in the Transmitter FIFO*        4) OP_RX      Receive data in the Receiver FIFO*        5) OP_INIT    Initialize the 16550U UART*        6) OP_BAUD    Change the baud rate to specified value*** Polled I/O routines for LSI LOGIC UART implementation*** Each 16550U has the following registers:**  Register   Description                             Offset*  --------   ------------------------------------    --------------------*  Config     Configuration Register                  OFFSET_config*  Divisor    Baud Rate Generator Count Register      OFFSET_divisor*  Reset      Reset / Halt Register                   OFFSET_reset*  Status     Status Register                         OFFSET_status*  RxBuff     Receive Buffer                          OFFSET_rxbuff*  TxBuff     Transmit Buffer                         OFFSET_txbuff*  Interval   Interval Timer Register                 OFFSET_interval*  Abrd       ABRD Minimum Sample Register            OFFSET_abrd*  Channel    Channel Configuration Register          OFFSET_channel*** Information regarding the registers can be found in LSI Logic's* L64388A2 RAP Technical Manual.****************************************************************/#include <terms.h>#include <defines.h>typedef unsigned long ulong;typedef unsigned short ushort;#define OFFSET_config              0x00 #define OFFSET_divisor             0x08 #define OFFSET_reset               0x10 #define OFFSET_status              0x18 #define OFFSET_rxbuff              0x20 #define OFFSET_txbuff              0x28 #define OFFSET_interval            0x30 #define OFFSET_abrd                0x38 #define OFFSET_channel             0x40 #define STATUS_RDY                 0x00008000#define STATUS_TXEMPTY             0x00000002#define STATUS_TXALMOSTFULL        0x01000000#define BRG_PS                     0x00100000/* Driver for p16550U UART */int p16550U(int, unsigned long, int, int);/**************************************************************** Baud rate divisor tables. ***************************************************************//* assumes a 18.432 MHz crystal is in use *//* btab = 18432000/(baudrate*16) */static long btab_18[] = {	-1,	/* B0 */	23040,	/* B50 */	15360,	/* B75 */	10473,	/* B110 */	8597,	/* B134 */	7680,	/* B150 */	5760,	/* B200 */	3840,	/* B300 */	1920,	/* B600 */	960,	/* B1200 */	640,	/* B1800 */	480,	/* B2400 */	240,	/* B4800 */	120,	/* B9600 */	60,	/* B19200 */	30,	/* B38400 */	20,	/* B57600 */	-1,	/* B76800 */	10,	/* B115200 */	-1,	/* B153600 */	5,	/* B230400 */	-1,	/* B307200 */	2,	/* B460800 */	-1,	/* B921600 */	0	/* end */	};/* assumes a 40 MHz crystal is in use *//* btab = 40000000/(baudrate*16) */static long btab_40[] = {	-1,	/* B0 */	50000,	/* B50 */	33333,	/* B75 */	22727,	/* B110 */	18657,	/* B134 */	16667,	/* B150 */	12500,	/* B200 */	8333,	/* B300 */	4167,	/* B600 */	2083,	/* B1200 */	1389,	/* B1800 */	1042,	/* B2400 */	521,	/* B4800 */	260,	/* B9600 */	130,	/* B19200 */	65,	/* B38400 */	43,	/* B57600 */	-1,	/* B76800 */	22,	/* B115200 */	-1,	/* B153600 */	11,	/* B230400 */	-1,	/* B307200 */	5,	/* B460800 */	-1,	/* B921600 */	0	/* end */	};/* assumes a 80 MHZ crystal is in use *//* btab = 80000000/(baudrate*16) */static long btab_80[] = {	-1,	/* B0 */	100000,	/* B50 */	66667,	/* B75 */	45455,	/* B110 */	37313,	/* B134 */	33333,	/* B150 */	25000,	/* B200 */	16667,	/* B300 */	8333,	/* B600 */	4167,	/* B1200 */	2778,	/* B1800 */	2083,	/* B2400 */	1042,	/* B4800 */	521,	/* B9600 */	260,	/* B19200 */	130,	/* B38400 */	87,	/* B57600 */	-1,	/* B76800 */	43,	/* B115200 */	-1,	/* B153600 */	22,	/* B230400 */	-1,	/* B307200 */	11,	/* B460800 */	-1,	/* B921600 */	0	/* end */	};#define DEFRATE 13  /* default baud rate is 9600 baud */ /* inw is used to read a word sized value from a register */#define inw(a) (*((volatile unsigned long *)(a)))/* outw is used to place a word sized value into a register */#define outw(a,v) (*((volatile unsigned long *)(a))=(v))/******************************************************************* Func: p16550u* Desc: Provide capabilities to send, recieve, initialize,*       and monitor the 16550U UART.** Params: int op, int chan, int ch, struct p16550Uinfo* Output: int*******************************************************************/int p16550u(int op, unsigned long base_addr, int chan, int ch) {unsigned long m,v;long *btab;int i,brate;/* determine what clock frequency we're running at */#ifdef CLKFREQif (CLKFREQ == 40) {   btab = btab_40;} else if(CLKFREQ == 80) {   btab = btab_80;} else {   btab = btab_18;};#elsebtab = btab_18;#endif  switch (op) {    case OP_RXRDY :            /* Is there one byte in the RCVR FIFO? */            if(inw(base_addr + OFFSET_status) & STATUS_RDY)              return(1);            break;    case OP_RX :            return  inw(base_addr + OFFSET_rxbuff);	            case OP_TXRDY :            /* Check to see if XMIT FIFO is empty */            if((inw(base_addr + OFFSET_status) & STATUS_TXALMOSTFULL) == 0)	      return(1);	    break;    case OP_TX :	    return outw(base_addr + OFFSET_txbuff, ch);    case OP_INIT :	    /* make sure UART is taken out of reset */	    outw(base_addr + OFFSET_reset, 0xfffffffe);	    /* determine what clock frequency we're running at */#ifdef CLKFREQ	    if((CLKFREQ == 40) || (CLKFREQ == 80)) {		/* turn loopback off, select system clock */		outw(base_addr + OFFSET_config, 0x00000008);		}	    else {		/* turn loopback off, select brg clock */		outw(base_addr + OFFSET_config, 0x00000000);		}#else	    /* turn loopback off, select brg clock */	    outw(base_addr + OFFSET_config, 0x00000000);#endif	    /* reset these bits to zero - optional */            outw(base_addr + OFFSET_status, 0x00000000);	                 /* channel: 1 stopbit, no parity, 8 bits data, ignore cts,  */	    /* ignore dsr, ignore dcd                                   */	    outw(base_addr + OFFSET_channel, 0x000000e3);              	    /* set baud rate to default */	    outw(base_addr + OFFSET_divisor, btab[DEFRATE]);            /* take out of tx and rx halt */	    outw(base_addr + OFFSET_reset, 0x00000000);	    break;    case OP_BAUD :            brate = ch;	    /* check if given value is in table */	    if (brate > 24)	      return(1); /* baud rate too large */	    /* return if unsupported baud rate  */	    if (btab[brate] == -1) 	      return(1);	    /* set baud rate to given value */	    outw(base_addr + OFFSET_divisor, btab[brate]);	    	    break;	      case OP_CLKINIT :            break;         case OP_DELAY :	    break;            	case OP_BAUDRATES :		m = 1;		for (i=v=0;btab[i];i++) {			if (btab[i] != -1) v |= m;			m <<= 1;			}		return(v);		break;  	}  return(0);}#if 0#if 0	li	t1,0xb0008600	li	t0,0xfffe	sw	t0,16(t1)	sw	zero,0(t1)	sw	zero,24(t1)	li	t0,0xe3	sw	t0,64(t1)	li	t0,120 # 9600	sw	t0,8(t1)	sw	zero,16(t1)#endif#if 0	li	t1,0xb0008600   1:	lw	t0,24(t1)	and	t0,0x01000000	bne	t0,zero,1b	li	t0,0x41	sw	t0,40(t1)#endifdiagc(int c){while (inw(0xb0008600+24)&0x01000000);outw(0xb0008600+40,c);}diagh(Ulong v,int n){int d,shmt;diagc('[');for (shmt=28;n>0;n--,shmt-=4) {	d = (v>>shmt)&0xf;	if (d >= 10) diagc('a'+d-10);	else diagc('0'+d);	}diagc(']');}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -