📄 cobaltscc.c
字号:
/* * Filename: cobaltscc.c * * Description: Functions for supporting and testing serial I/O * * Author(s): Timothy Stonis * * Copyright 1997, Cobalt Microserver, Inc. */#include "z8530.h"#include "diagdefs.h"#include "serial.h"#include "asm/io.h"/* * Function prototypes */void InitSerialPort(unsigned char *);void RegisterDelay(void);void InitScc(void);/* * Function: RegisterDelay * * Description: A little delay since the SCC can't handle quick consecutive * accesses * In: none * Out: none */void RegisterDelay(void){ register int ctr; for(ctr=0;ctr<0x40;ctr++);}/* * Function: SccInit * * Description: Initialize all the SCC registers for 19200 baud, asynchronous, * 8 bit, 1 stop bit, no parity communication (Channel A) * * In: none * * Out: none */void InitScc(void){ /* Force hardware reset */ Write8530(kSCC_ChanA | kSCC_Command, R9 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, FHWRES); RegisterDelay(); /* x32 clock, 1 stop bit, no parity */ Write8530(kSCC_ChanA | kSCC_Command, R4 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, X16CLK | SB1); RegisterDelay(); /* Rx 8 bits, Rx disabled */ Write8530(kSCC_ChanA | kSCC_Command, R3 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, Rx8); RegisterDelay(); /* Tx 8 bits, DTR, RTS, Tx off */ Write8530(kSCC_ChanA | kSCC_Command, R5 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, Tx8 | DTR | RTS); RegisterDelay(); /* Int. Disabled */ Write8530(kSCC_ChanA | kSCC_Command, R9 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, 0x0); RegisterDelay(); /* NRZ */ Write8530(kSCC_ChanA | kSCC_Command, R10 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, NRZ); RegisterDelay(); /* Tx & Rx = BRG out, TRxC = BRG out */ Write8530(kSCC_ChanA | kSCC_Command, R11 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, TCBR | RCBR | TRxCBR | TRxCOI); RegisterDelay(); /* Time constant = 0x01 */ Write8530(kSCC_ChanA | kSCC_Command, R12 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, kSCC_115200 ); RegisterDelay(); /* Time constant high = 0x00 */ Write8530(kSCC_ChanA | kSCC_Command, R13 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, 0x00); RegisterDelay(); /* BRG in = ~RTxC, BRG off, loopback */ Write8530(kSCC_ChanA | kSCC_Command, R14 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, LOOPBAK | BRSRC); RegisterDelay();}/* * Function: EnableScc * * Description: Enable transmit and receive on SCC Channel A * In: none * Out: none */void EnableScc(void){ /* Enable BRG */ Write8530(kSCC_ChanA | kSCC_Command, R14 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, BRENABL | BRSRC); RegisterDelay(); /* Rx enable (Rx 8 bits) */ Write8530(kSCC_ChanA | kSCC_Command, R3 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, RxENABLE | Rx8); RegisterDelay(); /* Tx enable (Tx8, DTR, RTS) */ Write8530(kSCC_ChanA | kSCC_Command, R5 | NULLCODE); RegisterDelay(); Write8530(kSCC_ChanA, TxENAB | Tx8 | DTR | RTS); RegisterDelay();}/* * Function: SccOutb * * Description: Write a byte to the SCC (Channel A) and blink LED * In: Byte to send * Out: none */void SccOutb(unsigned char byte){ /* LED on.. */ Write8530(kSCC_ChanB | kSCC_Command, R5); RegisterDelay(); Write8530(kSCC_ChanB | kSCC_Command, RTS); RegisterDelay(); while ((Read8530(kSCC_ChanA) & Tx_BUF_EMP) == 0) RegisterDelay(); Write8530(kSCC_ChanA | kSCC_Direct, byte); RegisterDelay(); /* LED off.. */ Write8530(kSCC_ChanB | kSCC_Command, R9); RegisterDelay(); Write8530(kSCC_ChanB | kSCC_Command, CHRB); RegisterDelay();}/* * Function: SccInb * * Description: Read a byte from the SCC (Channel A) * In: Byte to send * Out: none */void SccInb(unsigned char *byte){ while ((Read8530(kSCC_ChanA) & Rx_CH_AV) == 0) RegisterDelay(); *byte = Read8530(kSCC_ChanA | kSCC_Direct); RegisterDelay();}/* * Function: SccWrite * * Description: Write a null terminated string to the SCC * In: C string * Out: none */void SccWrite(const unsigned char *string){ while((*string) != 0) { if (*string == 10) SccOutb((unsigned char) 13); SccOutb(*(string++)); }}/* * Function: InitSerialPort * * Description: Initialize the SCC and spit out the header message * In: Header message * Out: none */void InitSerialPort(unsigned char *msg){ InitScc(); EnableScc(); SccWrite(msg);}/* * Function: SccInbTimeout * * Description: Read a byte from the SCC (Channel A) with timeout * In: Byte to send * Out: Timeout status */unsigned char SccInbTimeout(unsigned char *byte, unsigned long timeout){ unsigned long ctr = 0; while ((Read8530(kSCC_ChanA) & Rx_CH_AV) == 0) { RegisterDelay(); if ((ctr++) > timeout) return 0xFF; } *byte = Read8530(kSCC_ChanA | kSCC_Direct); RegisterDelay(); return 0;}#include <linux/serial_reg.h>extern int serial_echo_init (int base);extern int serial_echo_print (const char *s);/* * this defines the address for the port to which printk echoing is done * when CONFIG_SERIAL_ECHO is defined */#define SERIAL_ECHO_PORT 0x1C800000 static int serial_echo_port = 0;#define serial_echo_outb(v,a) outb((v),(a)+serial_echo_port)#define serial_echo_inb(a) inb((a)+serial_echo_port)#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)/* Wait for transmitter & holding register to empty */#define WAIT_FOR_XMITR \ do { \ lsr = serial_echo_inb(UART_LSR); \ } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY)/* * These two functions abstract the actual communications with the * debug port. This is so we can change the underlying communications * mechanism without modifying the rest of the code. */intserial_echo_print(const char *s){ int lsr, ier; int i; if (!serial_echo_port) return 0; /* * First save the IER then disable the interrupts */ ier = serial_echo_inb(UART_IER); serial_echo_outb(0x00, UART_IER); /* * Now, do each character */ for (i = 0; *s; i++, s++) { WAIT_FOR_XMITR; /* Send the character out. */ serial_echo_outb(*s, UART_TX); /* if a LF, also do CR... */ if (*s == 10) { WAIT_FOR_XMITR; serial_echo_outb(13, UART_TX); } } /* * Finally, Wait for transmitter & holding register to empty * and restore the IER */ do { lsr = serial_echo_inb(UART_LSR); } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY); serial_echo_outb(ier, UART_IER); return 0;}intserial_echo_init(int base){ int comstat, hi, lo; serial_echo_port = base; /* * read the Divisor Latch */ comstat = serial_echo_inb(UART_LCR); serial_echo_outb(comstat | UART_LCR_DLAB, UART_LCR); hi = serial_echo_inb(UART_DLM); lo = serial_echo_inb(UART_DLL); serial_echo_outb(comstat, UART_LCR); /* * now do hardwired init */ serial_echo_outb(0x03, UART_LCR); /* No parity, 8 data bits, 1 stop */ serial_echo_outb(0x83, UART_LCR); /* Access divisor latch */ /* This is computed using: * * const BASE_BAUD = (18432000 / 16); * UART_DLM = (BASE_BAUD / baud_I_want) >> 8; * UART_DLL = (BASE_BAUD / baud_I_want) & 0xff; */ serial_echo_outb(0x00, UART_DLM); /* 115200 baud */ serial_echo_outb(0x0A, UART_DLL); serial_echo_outb(0x03, UART_LCR); /* Done with divisor */ /* * Prior to disabling interrupts, read the LSR and RBR * registers */ comstat = serial_echo_inb(UART_LSR); /* COM? LSR */ comstat = serial_echo_inb(UART_RX); /* COM? RBR */ serial_echo_outb(0x00, UART_IER); /* Disable all interrupts */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -