From: Stuart M. <Stu...@st...> - 2000-06-15 15:55:53
|
Folks Attached is a patch which adds support for multiple SCI and SCIF's. This allows you to use both the serial ports at the same time, and select which serial port you want to use for a console at boot time. On processors which have two serial ports: SCI : ttyS0 SCIF : ttyS1 so if you want to use the SCIF as a console, add a command line option along the lines of: console=ttyS1,38400 Similarly /dev/console will be bound to whichever serial port was selected on the command line (as long as /dev/console is major 5, minor 1). Before you leap to install this patch, there is one thing I must point out. I've not been able to test this on anything other than a 7750, so I'd appreciate it if someone could check this out on an SH3. All comments welcome. Stuart Index: include/asm-sh/io.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/io.h,v retrieving revision 1.4 diff -c -r1.4 io.h *** include/asm-sh/io.h 2000/05/07 23:31:59 1.4 --- include/asm-sh/io.h 2000/06/15 15:43:18 *************** *** 85,93 **** #define isa_memcpy_toio(a,b,c) \ memcpy((void *)(sh_isa_slot((unsigned long)(a))),(b),(c)) - #define ctrl_in(addr) *(addr) - #define ctrl_out(data,addr) *(addr) = (data) - extern __inline__ unsigned long ctrl_inb(unsigned long addr) { return *(volatile unsigned char*)addr; --- 85,90 ---- Index: arch/sh/config.in =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/config.in,v retrieving revision 1.8 diff -c -r1.8 config.in *** arch/sh/config.in 2000/06/14 09:35:58 1.8 --- arch/sh/config.in 2000/06/15 15:43:20 *************** *** 167,177 **** fi tristate 'Serial support' CONFIG_SERIAL - if [ "$CONFIG_SERIAL" = "y" -o "$CONFIG_SERIAL" = "m" ]; then - choice 'Serial interface type' \ - "SCI CONFIG_SH_SCI_SERIAL \ - SCIF CONFIG_SH_SCIF_SERIAL" - fi if [ "$CONFIG_SERIAL" = "y" ]; then bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE fi --- 167,172 ---- Index: drivers/char/sh-sci.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/drivers/char/sh-sci.c,v retrieving revision 1.9 diff -c -r1.9 sh-sci.c *** drivers/char/sh-sci.c 2000/06/14 09:38:30 1.9 --- drivers/char/sh-sci.c 2000/06/15 15:43:23 *************** *** 5,10 **** --- 5,11 ---- * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) * Copyright (C) 1999, 2000 Niibe Yutaka * Copyright (C) 2000 Sugioka Toshinobu + * Modified to support multiple serial ports. Stuart Menefy (May 2000). * * TTY code is based on sx.c (Specialix SX driver) by: * *************** *** 50,62 **** #endif #include "sh-sci.h" - struct sci_port sci_ports[1]; - #ifdef CONFIG_SERIAL_CONSOLE static struct console sercons; #endif /* Function prototypes */ static void sci_disable_tx_interrupts(void *ptr); static void sci_enable_tx_interrupts(void *ptr); static void sci_disable_rx_interrupts(void *ptr); --- 51,65 ---- #endif #include "sh-sci.h" #ifdef CONFIG_SERIAL_CONSOLE static struct console sercons; + static struct sci_port* sercons_port; + static int sercons_baud; #endif /* Function prototypes */ + static void sci_init_pins_sci(struct sci_port* port, unsigned int cflag); + static void sci_init_pins_scif(struct sci_port* port, unsigned int cflag); static void sci_disable_tx_interrupts(void *ptr); static void sci_enable_tx_interrupts(void *ptr); static void sci_disable_rx_interrupts(void *ptr); *************** *** 71,79 **** static struct tty_driver sci_driver, sci_callout_driver; ! #define SCI_NPORTS 1 static struct tty_struct *sci_table[SCI_NPORTS] = { NULL, }; ! static struct termios *sci_termios[2]; /* nomal, locked */ int sci_refcount; int sci_debug = 0; --- 74,83 ---- static struct tty_driver sci_driver, sci_callout_driver; ! static struct sci_port sci_ports[SCI_NPORTS] = SCI_INIT; static struct tty_struct *sci_table[SCI_NPORTS] = { NULL, }; ! static struct termios *sci_termios[SCI_NPORTS]; ! static struct termios *sci_termios_locked[SCI_NPORTS]; int sci_refcount; int sci_debug = 0; *************** *** 96,101 **** --- 100,162 ---- NULL }; + #if defined(SCI_ONLY) || defined(SCI_AND_SCIF) + static void sci_init_pins_sci(struct sci_port* port, unsigned int cflag) + { + } + #endif + + #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF) + #if defined(__sh3__) + /* For SH7709, SH7709A, SH7729 */ + static void sci_init_pins_scif(struct sci_port* port, unsigned int cflag) + { + unsigned int fcr_val = 0; + + { + unsigned short data; + + /* We need to set SCPCR to enable RTS/CTS */ + data = ctrl_inw(SCPCR); + /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/ + ctrl_outw(data&0x0fcf, SCPCR); + } + if (cflag & CRTSCTS) + fcr_val |= SCFCR_MCE; + else { + unsigned short data; + + /* We need to set SCPCR to enable RTS/CTS */ + data = ctrl_inw(SCPCR); + /* Clear out SCP7MD1,0, SCP4MD1,0, + Set SCP6MD1,0 = {01} (output) */ + ctrl_outw((data&0x0fcf)|0x1000, SCPCR); + + data = ctrl_inb(SCPDR); + /* Set /RTS2 (bit6) = 0 */ + ctrl_outb(SCPDR, data&0xbf); + } + sci_out(port, SCFCR, fcr_val); + } + + #else + + /* For SH7750 */ + static void sci_init_pins_scif(struct sci_port* port, unsigned int cflag) + { + unsigned int fcr_val = 0; + + if (cflag & CRTSCTS) { + fcr_val |= SCFCR_MCE; + } else { + ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */ + } + sci_out(port, SCFCR, fcr_val); + } + + #endif + #endif /* SCIF_ONLY || SCI_AND_SCIF */ + static void sci_setsignals(struct sci_port *port, int dtr, int rts) { /* This routine is used for seting signals of: DTR, DCD, CTS/RTS */ *************** *** 120,126 **** */ } ! static void sci_set_baud(int baud) { int t; --- 181,187 ---- */ } ! static void sci_set_baud(struct sci_port *port, int baud) { int t; *************** *** 151,189 **** } if (t > 0) { ! /* sci_setsignals (port, 1, -1); */ if(t >= 256) { ! ctrl_out((ctrl_in(SCSMR) & ~3) | 1, SCSMR); t >>= 2; } ! ctrl_outb(t, SCBRR); ! ctrl_outw(0xa400, RFCR); /* Refresh counter clear */ ! while (ctrl_inw(RFCR) < WAIT_RFCR_COUNTER) ! ; } else { ! /* sci_setsignals (port, 0, -1); */ } } ! static void sci_set_termios_cflag(int cflag, int baud) { ! unsigned short status; ! unsigned short smr_val; ! #if defined(CONFIG_SH_SCIF_SERIAL) ! unsigned short fcr_val=6; /* TFRST=1, RFRST=1 */ ! #endif do ! status = ctrl_in(SC_SR); ! while (!(status & SCI_TEND)); ! ctrl_out(0x00, SCSCR); /* TE=0, RE=0, CKE1=0 */ ! #if defined(CONFIG_SH_SCIF_SERIAL) ! ctrl_out(fcr_val, SCFCR); ! fcr_val = 0; ! #endif ! smr_val = ctrl_in(SCSMR) & 3; if ((cflag & CSIZE) == CS7) smr_val |= 0x40; if (cflag & PARENB) --- 212,245 ---- } if (t > 0) { ! sci_setsignals (port, 1, -1); if(t >= 256) { ! sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1); t >>= 2; } ! sci_out(port, SCBRR, t); ! udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */ } else { ! sci_setsignals (port, 0, -1); } } ! static void sci_set_termios_cflag(struct sci_port *port, int cflag, int baud) { ! unsigned int status; ! unsigned int smr_val; do ! status = sci_in(port, SCxSR); ! while (!(status & SCxSR_TEND(port))); ! sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ ! ! if (port->type == PORT_SCIF) { ! sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); ! } ! smr_val = sci_in(port, SCSMR) & 3; if ((cflag & CSIZE) == CS7) smr_val |= 0x40; if (cflag & PARENB) *************** *** 192,234 **** smr_val |= 0x10; if (cflag & CSTOPB) smr_val |= 0x08; ! ctrl_out(smr_val, SCSMR); ! ! #if defined(CONFIG_SH_SCIF_SERIAL) ! #if defined(__sh3__) ! { /* For SH7709, SH7709A, SH7729 */ ! unsigned short data; ! ! /* We need to set SCPCR to enable RTS/CTS */ ! data = ctrl_inw(SCPCR); ! /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/ ! ctrl_outw(data&0x0fcf, SCPCR); ! } ! #endif ! if (cflag & CRTSCTS) ! fcr_val |= 0x08; ! else { ! #if defined(__sh3__) ! unsigned short data; ! ! /* We need to set SCPCR to enable RTS/CTS */ ! data = ctrl_inw(SCPCR); ! /* Clear out SCP7MD1,0, SCP4MD1,0, ! Set SCP6MD1,0 = {01} (output) */ ! ctrl_outw((data&0x0fcf)|0x1000, SCPCR); ! data = ctrl_inb(SCPDR); ! /* Set /RTS2 (bit6) = 0 */ ! ctrl_outb(data&0xbf, SCPDR); ! #elif defined(__SH4__) ! ctrl_outw(0x0080, SCSPTR); /* Set RTS = 1 */ ! #endif ! } ! ctrl_out(fcr_val, SCFCR); ! #endif ! sci_set_baud(baud); ! ctrl_out(SCSCR_INIT, SCSCR); /* TIE=0,RIE=0,TE=1,RE=1 */ } static int sci_set_real_termios(void *ptr) --- 248,259 ---- smr_val |= 0x10; if (cflag & CSTOPB) smr_val |= 0x08; ! sci_out(port, SCSMR, smr_val); ! port->init_pins(port, cflag); ! sci_set_baud(port, baud); ! sci_out(port, SCSCR, SCSCR_INIT(port)); } static int sci_set_real_termios(void *ptr) *************** *** 237,243 **** if (port->old_cflag != port->gs.tty->termios->c_cflag) { port->old_cflag = port->gs.tty->termios->c_cflag; ! sci_set_termios_cflag(port->old_cflag, port->gs.baud); sci_enable_rx_interrupts(port); } --- 262,268 ---- if (port->old_cflag != port->gs.tty->termios->c_cflag) { port->old_cflag = port->gs.tty->termios->c_cflag; ! sci_set_termios_cflag(port, port->old_cflag, port->gs.baud); sci_enable_rx_interrupts(port); } *************** *** 273,299 **** unsigned short ctrl; unsigned char c; ! status = ctrl_in(SC_SR); ! if (!(status & SCI_TD_E)) { save_and_cli(flags); ! ctrl = ctrl_in(SCSCR); if (port->gs.xmit_cnt == 0) { ctrl &= ~SCI_CTRL_FLAGS_TIE; port->gs.flags &= ~GS_TX_INTEN; } else ctrl |= SCI_CTRL_FLAGS_TIE; ! ctrl_out(ctrl, SCSCR); restore_flags(flags); return; } while (1) { count = port->gs.xmit_cnt; ! #if defined(CONFIG_SH_SCIF_SERIAL) ! txroom = 16 - (ctrl_inw(SCFDR)>>8); ! #else ! txroom = (ctrl_in(SC_SR)&SCI_TD_E)?1:0; ! #endif if (count > txroom) count = txroom; --- 298,324 ---- unsigned short ctrl; unsigned char c; ! status = sci_in(port, SCxSR); ! if (!(status & SCxSR_TDxE(port))) { save_and_cli(flags); ! ctrl = sci_in(port, SCSCR); if (port->gs.xmit_cnt == 0) { ctrl &= ~SCI_CTRL_FLAGS_TIE; port->gs.flags &= ~GS_TX_INTEN; } else ctrl |= SCI_CTRL_FLAGS_TIE; ! sci_out(port, SCSCR, ctrl); restore_flags(flags); return; } while (1) { count = port->gs.xmit_cnt; ! if (port->type == PORT_SCIF) { ! txroom = 16 - (sci_in(port, SCFDR)>>8); ! } else { ! txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0; ! } if (count > txroom) count = txroom; *************** *** 307,315 **** for (i=0; i<count; i++) { c = port->gs.xmit_buf[port->gs.xmit_tail + i]; ! ctrl_outb(c, SC_TDR); } ! ctrl_out(SCI_TD_E_CLEAR, SC_SR); /* Update the kernel buffer end */ port->gs.xmit_tail = (port->gs.xmit_tail + count) & (SERIAL_XMIT_SIZE-1); --- 332,340 ---- for (i=0; i<count; i++) { c = port->gs.xmit_buf[port->gs.xmit_tail + i]; ! sci_out(port, SCxTDR, c); } ! sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); /* Update the kernel buffer end */ port->gs.xmit_tail = (port->gs.xmit_tail + count) & (SERIAL_XMIT_SIZE-1); *************** *** 327,344 **** } save_and_cli(flags); ! ctrl = ctrl_in(SCSCR); if (port->gs.xmit_cnt == 0) { ctrl &= ~SCI_CTRL_FLAGS_TIE; port->gs.flags &= ~GS_TX_INTEN; } else { ! #if defined(CONFIG_SH_SCIF_SERIAL) ! ctrl_in(SC_SR); /* Dummy read */ ! ctrl_out(SCI_TD_E_CLEAR, SC_SR); ! #endif ctrl |= SCI_CTRL_FLAGS_TIE; } ! ctrl_out(ctrl, SCSCR); restore_flags(flags); } --- 352,369 ---- } save_and_cli(flags); ! ctrl = sci_in(port, SCSCR); if (port->gs.xmit_cnt == 0) { ctrl &= ~SCI_CTRL_FLAGS_TIE; port->gs.flags &= ~GS_TX_INTEN; } else { ! if (port->type == PORT_SCIF) { ! sci_in(port, SCxSR); /* Dummy read */ ! sci_out(port, SCxSR, SCIF_TDFE); ! } ctrl |= SCI_CTRL_FLAGS_TIE; } ! sci_out(port, SCSCR, ctrl); restore_flags(flags); } *************** *** 349,365 **** int copied=0; unsigned short status; ! status = ctrl_in(SC_SR); ! if (!(status & SCI_RD_F)) return; tty = port->gs.tty; while (1) { ! #if defined(CONFIG_SH_SCIF_SERIAL) ! count = ctrl_inw(SCFDR)&0x001f; ! #else ! count = (ctrl_in(SC_SR)&SCI_RD_F)?1:0; ! #endif /* Don't copy more bytes than there is room for in the buffer */ if (tty->flip.count + count > TTY_FLIPBUF_SIZE) --- 374,390 ---- int copied=0; unsigned short status; ! status = sci_in(port, SCxSR); ! if (!(status & SCxSR_RDxF(port))) return; tty = port->gs.tty; while (1) { ! if (port->type == PORT_SCIF) { ! count = sci_in(port, SCFDR)&0x001f; ! } else { ! count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0; ! } /* Don't copy more bytes than there is room for in the buffer */ if (tty->flip.count + count > TTY_FLIPBUF_SIZE) *************** *** 370,378 **** break; for (i=0; i<count; i++) ! tty->flip.char_buf_ptr[i] = ctrl_inb(SC_RDR); ! ctrl_in(SC_SR); /* dummy read */ ! ctrl_out(SCI_RDRF_CLEAR, SC_SR); memset(tty->flip.flag_buf_ptr, TTY_NORMAL, count); --- 395,403 ---- break; for (i=0; i<count; i++) ! tty->flip.char_buf_ptr[i] = sci_in(port, SCxRDR); ! sci_in(port, SCxSR); /* dummy read */ ! sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); memset(tty->flip.flag_buf_ptr, TTY_NORMAL, count); *************** *** 392,407 **** static void sci_rx_interrupt(int irq, void *ptr, struct pt_regs *regs) { struct sci_port *port = ptr; - unsigned long flags; if (port->gs.flags & GS_ACTIVE) if (!(port->gs.flags & SCI_RX_THROTTLE)) { sci_receive_chars(port); return; } ! save_and_cli(flags); ! ctrl_out(ctrl_in(SCSCR) & ~SCI_CTRL_FLAGS_RIE, SCSCR); ! restore_flags(flags); } static void sci_tx_interrupt(int irq, void *ptr, struct pt_regs *regs) --- 417,429 ---- static void sci_rx_interrupt(int irq, void *ptr, struct pt_regs *regs) { struct sci_port *port = ptr; if (port->gs.flags & GS_ACTIVE) if (!(port->gs.flags & SCI_RX_THROTTLE)) { sci_receive_chars(port); return; } ! sci_disable_rx_interrupts(port); } static void sci_tx_interrupt(int irq, void *ptr, struct pt_regs *regs) *************** *** 411,429 **** if (port->gs.flags & GS_ACTIVE) sci_transmit_chars(port); else { ! unsigned long flags; ! ! save_and_cli(flags); ! ctrl_out(ctrl_in(SCSCR) & ~SCI_CTRL_FLAGS_TIE, SCSCR); ! restore_flags(flags); } } static void sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs) { /* Handle errors */ ! if (ctrl_in(SC_SR) & SCI_ERRORS) ! ctrl_out(SCI_ERROR_CLEAR, SC_SR); /* Kick the transmission */ sci_tx_interrupt(irq, ptr, regs); --- 433,449 ---- if (port->gs.flags & GS_ACTIVE) sci_transmit_chars(port); else { ! sci_disable_tx_interrupts(port); } } static void sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs) { + struct sci_port *port = ptr; + /* Handle errors */ ! if (sci_in(port, SCxSR) & SCxSR_ERRORS(port)) ! sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); /* Kick the transmission */ sci_tx_interrupt(irq, ptr, regs); *************** *** 436,449 **** static void sci_disable_tx_interrupts(void *ptr) { unsigned long flags; unsigned short ctrl; /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ save_and_cli(flags); ! ctrl = ctrl_in(SCSCR); ctrl &= ~SCI_CTRL_FLAGS_TIE; ! ctrl_out(ctrl, SCSCR); restore_flags(flags); } --- 456,470 ---- static void sci_disable_tx_interrupts(void *ptr) { + struct sci_port *port = ptr; unsigned long flags; unsigned short ctrl; /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ save_and_cli(flags); ! ctrl = sci_in(port, SCSCR); ctrl &= ~SCI_CTRL_FLAGS_TIE; ! sci_out(port, SCSCR, ctrl); restore_flags(flags); } *************** *** 451,484 **** { struct sci_port *port = ptr; ! disable_irq(SCI_TXI_IRQ); sci_transmit_chars(port); ! enable_irq(SCI_TXI_IRQ); } static void sci_disable_rx_interrupts(void * ptr) { unsigned long flags; unsigned short ctrl; /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ save_and_cli(flags); ! ctrl = ctrl_in(SCSCR); ctrl &= ~SCI_CTRL_FLAGS_RIE; ! ctrl_out(ctrl, SCSCR); restore_flags(flags); } static void sci_enable_rx_interrupts(void * ptr) { unsigned long flags; unsigned short ctrl; /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ save_and_cli(flags); ! ctrl = ctrl_in(SCSCR); ctrl |= SCI_CTRL_FLAGS_RIE; ! ctrl_out(ctrl, SCSCR); restore_flags(flags); } --- 472,507 ---- { struct sci_port *port = ptr; ! disable_irq(port->irqs[SCIx_TXI_IRQ]); sci_transmit_chars(port); ! enable_irq(port->irqs[SCIx_TXI_IRQ]); } static void sci_disable_rx_interrupts(void * ptr) { + struct sci_port *port = ptr; unsigned long flags; unsigned short ctrl; /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ save_and_cli(flags); ! ctrl = sci_in(port, SCSCR); ctrl &= ~SCI_CTRL_FLAGS_RIE; ! sci_out(port, SCSCR, ctrl); restore_flags(flags); } static void sci_enable_rx_interrupts(void * ptr) { + struct sci_port *port = ptr; unsigned long flags; unsigned short ctrl; /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ save_and_cli(flags); ! ctrl = sci_in(port, SCSCR); ctrl |= SCI_CTRL_FLAGS_RIE; ! sci_out(port, SCSCR, ctrl); restore_flags(flags); } *************** *** 490,500 **** static int sci_chars_in_buffer(void * ptr) { ! #if defined(CONFIG_SH_SCIF_SERIAL) ! return (ctrl_inw(SCFDR) >> 8) + ((ctrl_in(SC_SR) & SCI_TEND)? 0: 1); ! #else ! return (ctrl_in(SC_SR) & SCI_TEND)? 0: 1; ! #endif } static void sci_shutdown_port(void * ptr) --- 513,525 ---- static int sci_chars_in_buffer(void * ptr) { ! struct sci_port *port = ptr; ! ! if (port->type == PORT_SCIF) { ! return (sci_in(port, SCFDR) >> 8) + ((sci_in(port, SCxSR) & SCxSR_TEND(port))? 0: 1); ! } else { ! return (sci_in(port, SCxSR) & SCxSR_TEND(port))? 0: 1; ! } } static void sci_shutdown_port(void * ptr) *************** *** 527,539 **** port->gs.tty = tty; port->gs.count++; - #ifdef CONFIG_SERIAL_CONSOLE - if (sercons.cflag && sercons.index == line) { - tty->termios->c_cflag = sercons.cflag; - sercons.cflag = 0; - } - #endif - /* * Start up serial port */ --- 552,557 ---- *************** *** 566,571 **** --- 584,598 ---- sci_set_real_termios(port); } + #ifdef CONFIG_SERIAL_CONSOLE + if (sercons.cflag && sercons.index == line) { + tty->termios->c_cflag = sercons.cflag; + port->gs.baud = sercons_baud; + sercons.cflag = 0; + sci_set_real_termios(port); + } + #endif + sci_enable_rx_interrupts(port); port->gs.session = current->session; *************** *** 680,685 **** --- 707,731 ---- return; } + #ifdef CONFIG_PROC_FS + static int sci_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) + { + int i; + struct sci_port *port; + int len = 0; + + len += sprintf(page, "serinfo:1.0\n"); + for (i = 0; i < SCI_NPORTS && len < 4000; i++) { + port = &sci_ports[i]; + len += sprintf(page+len, "%d: uart:%s address: %08x\n", i, + (port->type == PORT_SCI) ? "SCI" : "SCIF", + port->base); + } + return len; + } + #endif + /* ********************************************************************** * * Here are the initialization routines. * * ********************************************************************** */ *************** *** 695,701 **** sci_driver.name = "ttyS"; sci_driver.major = TTY_MAJOR; sci_driver.minor_start = SCI_MINOR_START; ! sci_driver.num = 1; sci_driver.type = TTY_DRIVER_TYPE_SERIAL; sci_driver.subtype = SERIAL_TYPE_NORMAL; sci_driver.init_termios = tty_std_termios; --- 741,747 ---- sci_driver.name = "ttyS"; sci_driver.major = TTY_MAJOR; sci_driver.minor_start = SCI_MINOR_START; ! sci_driver.num = SCI_NPORTS; sci_driver.type = TTY_DRIVER_TYPE_SERIAL; sci_driver.subtype = SERIAL_TYPE_NORMAL; sci_driver.init_termios = tty_std_termios; *************** *** 704,712 **** sci_driver.flags = TTY_DRIVER_REAL_RAW; sci_driver.refcount = &sci_refcount; sci_driver.table = sci_table; ! sci_driver.termios = &sci_termios[0]; ! sci_driver.termios_locked = &sci_termios[1]; ! sci_termios[0] = sci_termios[1] = NULL; sci_driver.open = sci_open; sci_driver.close = gs_close; --- 750,757 ---- sci_driver.flags = TTY_DRIVER_REAL_RAW; sci_driver.refcount = &sci_refcount; sci_driver.table = sci_table; ! sci_driver.termios = sci_termios; ! sci_driver.termios_locked = sci_termios_locked; sci_driver.open = sci_open; sci_driver.close = gs_close; *************** *** 723,733 **** --- 768,782 ---- sci_driver.stop = gs_stop; sci_driver.start = gs_start; sci_driver.hangup = gs_hangup; + #ifdef CONFIG_PROC_FS + sci_driver.read_proc = sci_read_proc; + #endif sci_callout_driver = sci_driver; sci_callout_driver.name = "cua"; sci_callout_driver.major = TTYAUX_MAJOR; sci_callout_driver.subtype = SERIAL_TYPE_CALLOUT; + sci_callout_driver.read_proc = NULL; if ((error = tty_register_driver(&sci_driver))) { printk(KERN_ERR "sci: Couldn't register SCI driver, error = %d\n", *************** *** 741,756 **** return 1; } ! port = &sci_ports[0]; ! port->gs.callout_termios = tty_std_termios; ! port->gs.normal_termios = tty_std_termios; ! port->gs.magic = SCI_MAGIC; ! port->gs.close_delay = HZ/2; ! port->gs.closing_wait = 30 * HZ; ! port->gs.rd = &sci_real_driver; ! init_waitqueue_head(&port->gs.open_wait); ! init_waitqueue_head(&port->gs.close_wait); ! port->old_cflag = 0; return 0; } --- 790,806 ---- return 1; } ! for (port = &sci_ports[0]; port < &sci_ports[SCI_NPORTS]; port++) { ! port->gs.callout_termios = sci_callout_driver.init_termios; ! port->gs.normal_termios = sci_driver.init_termios; ! port->gs.magic = SCI_MAGIC; ! port->gs.close_delay = HZ/2; ! port->gs.closing_wait = 30 * HZ; ! port->gs.rd = &sci_real_driver; ! init_waitqueue_head(&port->gs.open_wait); ! init_waitqueue_head(&port->gs.close_wait); ! port->old_cflag = 0; ! } return 0; } *************** *** 759,784 **** { struct sci_port *port; int i; ! ! for (i=SCI_ERI_IRQ; i<SCI_IRQ_END; i++) ! set_ipr_data(i, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); ! ! port = &sci_ports[0]; ! ! if (request_irq(SCI_ERI_IRQ, sci_er_interrupt, SA_INTERRUPT, ! "serial", port)) { ! printk(KERN_ERR "sci: Cannot allocate error irq.\n"); ! return -ENODEV; ! } ! if (request_irq(SCI_RXI_IRQ, sci_rx_interrupt, SA_INTERRUPT, ! "serial", port)) { ! printk(KERN_ERR "sci: Cannot allocate rx irq.\n"); ! return -ENODEV; ! } ! if (request_irq(SCI_TXI_IRQ, sci_tx_interrupt, SA_INTERRUPT, ! "serial", port)) { ! printk(KERN_ERR "sci: Cannot allocate tx irq.\n"); ! return -ENODEV; } /* XXX: How about BRI interrupt?? */ --- 809,828 ---- { struct sci_port *port; int i; ! void (*handlers[3])(int irq, void *ptr, struct pt_regs *regs) = { ! sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt ! }; ! ! for (port = &sci_ports[0]; port < &sci_ports[SCI_NPORTS]; port++) { ! for (i=0; i<3; i++) { ! set_ipr_data(port->irqs[i], port->intc_addr, port->intc_pos, SCI_PRIORITY); ! ! if (request_irq(port->irqs[i], handlers[i], SA_INTERRUPT, ! "serial", port)) { ! printk(KERN_ERR "sci: Cannot allocate irq.\n"); ! return -ENODEV; ! } ! } } /* XXX: How about BRI interrupt?? */ *************** *** 825,833 **** if (in_gdb == 1) { in_gdb = 0; ! get_char(); ! put_char('\r'); ! put_char('\n'); } } #endif --- 869,877 ---- if (in_gdb == 1) { in_gdb = 0; ! get_char(sercons_port); ! put_char(sercons_port, '\r'); ! put_char(sercons_port, '\n'); } } #endif *************** *** 839,845 **** static void serial_console_write(struct console *co, const char *s, unsigned count) { ! put_string(s, count); } /* --- 883,889 ---- static void serial_console_write(struct console *co, const char *s, unsigned count) { ! put_string(sercons_port, s, count); } /* *************** *** 870,875 **** --- 914,921 ---- int cflag = CREAD | HUPCL | CLOCAL; char *s; + sercons_port = &sci_ports[co->index]; + if (options) { baud = simple_strtoul(options, NULL, 10); s = options; *************** *** 918,926 **** cflag |= PARENB; break; } co->cflag = cflag; ! sci_set_termios_cflag(cflag, baud); return 0; } --- 964,975 ---- cflag |= PARENB; break; } + co->cflag = cflag; + sercons_baud = baud; ! sci_set_termios_cflag(sercons_port, cflag, baud); ! sercons_port->old_cflag = cflag; return 0; } Index: drivers/char/sh-sci.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/drivers/char/sh-sci.h,v retrieving revision 1.8 diff -c -r1.8 sh-sci.h *** drivers/char/sh-sci.h 2000/06/14 09:37:54 1.8 --- drivers/char/sh-sci.h 2000/06/15 15:43:26 *************** *** 5,152 **** * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) * Copyright (C) 1999, 2000 Niibe Yutaka * Copyright (C) 2000 Greg Banks * */ #include <linux/config.h> ! #if defined(CONFIG_SH_SCI_SERIAL) ! #if defined(__sh3__) ! #define SCSMR (volatile unsigned char *)0xfffffe80 ! #define SCBRR 0xfffffe82 ! #define SCSCR (volatile unsigned char *)0xfffffe84 ! #define SC_TDR 0xfffffe86 ! #define SC_SR (volatile unsigned char *)0xfffffe88 ! #define SC_RDR 0xfffffe8a ! #define SCSPTR 0xffffff7c ! #elif defined(__SH4__) ! #define SCSMR (volatile unsigned char *)0xffe00000 ! #define SCBRR 0xffe00004 ! #define SCSCR (volatile unsigned char *)0xffe00008 ! #define SC_TDR 0xffe0000c ! #define SC_SR (volatile unsigned char *)0xffe00010 ! #define SC_RDR 0xffe00014 ! #define SCSPTR 0xffe0001c #endif - - #define SCSCR_INIT 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ ! #define SCI_TD_E 0x80 ! #define SCI_RD_F 0x40 ! #define SCI_ORER 0x20 ! #define SCI_FER 0x10 ! #define SCI_PER 0x08 ! #define SCI_TEND 0x04 #define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER) - #define SCI_TD_E_CLEAR 0x78 - #define SCI_RDRF_CLEAR 0xbc - #define SCI_ERROR_CLEAR 0xc4 - - #define SCI_CTRL_FLAGS_TIE 0x80 - #define SCI_CTRL_FLAGS_RIE 0x40 - #define SCI_CTRL_FLAGS_TE 0x20 - #define SCI_CTRL_FLAGS_RE 0x10 - /* TEIE=0x04 */ - #define SCI_CTRL_FLAGS_CKE1 0x02 - #define SCI_CTRL_FLAGS_CKE0 0x01 - - #define SCI_ERI_IRQ 23 - #define SCI_RXI_IRQ 24 - #define SCI_TXI_IRQ 25 - #define SCI_TEI_IRQ 26 - #define SCI_IRQ_END 27 ! #define SCI_IPR_ADDR INTC_IPRB ! #define SCI_IPR_POS 1 #endif - - #if defined(CONFIG_SH_SCIF_SERIAL) - #if defined(__sh3__) - #define SCSMR (volatile unsigned char *)0xA4000150 - #define SCBRR 0xA4000152 - #define SCSCR (volatile unsigned char *)0xA4000154 - #define SC_TDR 0xA4000156 - #define SC_SR (volatile unsigned short *)0xA4000158 - #define SC_RDR 0xA400015A - #define SCFCR (volatile unsigned char *)0xA400015C - #define SCFDR 0xA400015E - - #undef SCSPTR /* SH7709 doesn't have SCSPTR */ - #define SCPCR 0xA4000116 /* Instead, it has SCPCR and SCPDR */ - #define SCPDR 0xA4000136 - #undef SCLSR - - #define SCSCR_INIT 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ - /* 0x33 when external clock is used */ - #define SCI_IPR_ADDR INTC_IPRE - #define SCI_IPR_POS 1 - - #elif defined(__SH4__) - #define SCSMR (volatile unsigned short *)0xFFE80000 - #define SCBRR 0xFFE80004 - #define SCSCR (volatile unsigned short *)0xFFE80008 - #define SC_TDR 0xFFE8000C - #define SC_SR (volatile unsigned short *)0xFFE80010 - #define SC_RDR 0xFFE80014 - #define SCFCR (volatile unsigned short *)0xFFE80018 - #define SCFDR 0xFFE8001C - #define SCSPTR 0xFFE80020 - #define SCLSR 0xFFE80024 - - #define SCSCR_INIT 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ - #define SCI_IPR_ADDR INTC_IPRC - #define SCI_IPR_POS 1 ! #endif - #define SCI_ER 0x0080 - #define SCI_TEND 0x0040 - #define SCI_TD_E 0x0020 - #define SCI_BRK 0x0010 - #define SCI_FER 0x0008 - #define SCI_PER 0x0004 - #define SCI_RD_F 0x0002 - #define SCI_DR 0x0001 - - #define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ER | SCI_BRK) - #define SCI_TD_E_CLEAR 0x00df - #define SCI_TEND_CLEAR 0x00bf - #define SCI_RDRF_CLEAR 0x00fc - #define SCI_ERROR_CLEAR 0x0063 - - #define SCI_CTRL_FLAGS_TIE 0x80 - #define SCI_CTRL_FLAGS_RIE 0x40 - #define SCI_CTRL_FLAGS_TE 0x20 - #define SCI_CTRL_FLAGS_RE 0x10 - #define SCI_CTRL_FLAGS_REIE 0x08 - #define SCI_CTRL_FLAGS_CKE1 0x02 - - #if defined(__sh3__) - #define SCI_ERI_IRQ 56 - #define SCI_RXI_IRQ 57 - #define SCI_BRI_IRQ 58 - #define SCI_TXI_IRQ 59 - #define SCI_IRQ_END 60 - #elif defined(__SH4__) - #define SCI_ERI_IRQ 40 - #define SCI_RXI_IRQ 41 - #define SCI_BRI_IRQ 42 - #define SCI_TXI_IRQ 43 - #define SCI_IRQ_END 44 - #endif - #endif - - #if defined(__sh3__) - #define RFCR 0xffffff74 - #elif defined(__SH4__) - #define RFCR 0xFF800028 - #endif - #define SCI_PRIORITY 3 #define SCI_MINOR_START 64 #define SCI_RX_THROTTLE 0x0000001 #define O_OTHER(tty) \ ((O_OLCUC(tty)) ||\ (O_ONLCR(tty)) ||\ --- 5,138 ---- * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) * Copyright (C) 1999, 2000 Niibe Yutaka * Copyright (C) 2000 Greg Banks + * Modified to support multiple serial ports. Stuart Menefy (May 2000). * */ #include <linux/config.h> ! /* Values for sci_port->type */ ! #define PORT_SCI 0 ! #define PORT_SCIF 1 ! ! /* Offsets into the sci_port->irqs array */ ! #define SCIx_ERI_IRQ 0 ! #define SCIx_RXI_IRQ 1 ! #define SCIx_TXI_IRQ 2 ! ! /* ERI, RXI, TXI, INTC reg, INTC pos */ ! #define SCI_IRQS { 23, 24, 25 }, INTC_IPRB, 1 ! #define SH3_SCIF_IRQS { 56, 57, 59 }, INTC_IPRE, 1 ! #define SH4_SCIF_IRQS { 40, 41, 43 }, INTC_IPRC, 1 ! ! #if defined(CONFIG_CPU_SUBTYPE_SH7708) ! # define SCI_NPORTS 1 ! # define SCI_INIT { \ ! { {}, PORT_SCI, 0xfffffe80, SCI_IRQS, sci_init_pins_sci } \ ! } ! # define SCSPTR 0xffffff7c /* 8 bit */ ! # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ ! # define SCI_ONLY ! #elif defined(CONFIG_CPU_SUBTYPE_SH7709) ! # define SCI_NPORTS 2 ! # define SCI_INIT { \ ! { {}, PORT_SCI, 0xfffffe80, SCI_IRQS, sci_init_pins_sci }, \ ! { {}, PORT_SCIF, 0xA4000150, SH3_SCIF_IRQS, sci_init_pins_scif } \ ! } ! # define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */ ! # define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */ ! # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ ! # define SCI_AND_SCIF ! #elif defined(CONFIG_CPU_SUBTYPE_SH7750) ! # define SCI_NPORTS 2 ! # define SCI_INIT { \ ! { {}, PORT_SCI, 0xffe00000, SCI_IRQS, sci_init_pins_sci }, \ ! { {}, PORT_SCIF, 0xFFE80000, SH4_SCIF_IRQS, sci_init_pins_scif } \ ! } ! # define SCSPTR1 0xffe0001c /* 8 bit SCI */ ! # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ ! # define SCLSR2 0xFFE80024 /* 16 bit SCIF */ ! # define SCSCR_INIT(port) (((port)->type == PORT_SCI) ? \ ! 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \ ! 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ ) ! # define SCI_AND_SCIF ! #else ! # error CPU subtype not defined #endif ! /* SCSCR */ ! #define SCI_CTRL_FLAGS_TIE 0x80 /* all */ ! #define SCI_CTRL_FLAGS_RIE 0x40 /* all */ ! #define SCI_CTRL_FLAGS_TE 0x20 /* all */ ! #define SCI_CTRL_FLAGS_RE 0x10 /* all */ ! /* SCI_CTRL_FLAGS_REIE 0x08 * 7750 SCIF */ ! /* SCI_CTRL_FLAGS_MPIE 0x08 * 7708 SCI, 7709 SCI, 7750 SCI */ ! /* SCI_CTRL_FLAGS_TEIE 0x04 * 7708 SCI, 7709 SCI, 7750 SCI */ ! /* SCI_CTRL_FLAGS_CKE1 0x02 * all */ ! /* SCI_CTRL_FLAGS_CKE0 0x01 * 7708 SCI, 7709 SCI/SCIF, 7750 SCI */ ! ! /* SCxSR SCI */ ! #define SCI_TDRE 0x80 /* 7708 SCI, 7709 SCI, 7750 SCI */ ! #define SCI_RDRF 0x40 /* 7708 SCI, 7709 SCI, 7750 SCI */ ! #define SCI_ORER 0x20 /* 7708 SCI, 7709 SCI, 7750 SCI */ ! #define SCI_FER 0x10 /* 7708 SCI, 7709 SCI, 7750 SCI */ ! #define SCI_PER 0x08 /* 7708 SCI, 7709 SCI, 7750 SCI */ ! #define SCI_TEND 0x04 /* 7708 SCI, 7709 SCI, 7750 SCI */ ! /* SCI_MPB 0x02 * 7708 SCI, 7709 SCI, 7750 SCI */ ! /* SCI_MPBT 0x01 * 7708 SCI, 7709 SCI, 7750 SCI */ #define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER) ! /* SCxSR SCIF */ ! #define SCIF_ER 0x0080 /* 7709 SCIF, 7750 SCIF */ ! #define SCIF_TEND 0x0040 /* 7709 SCIF, 7750 SCIF */ ! #define SCIF_TDFE 0x0020 /* 7709 SCIF, 7750 SCIF */ ! #define SCIF_BRK 0x0010 /* 7709 SCIF, 7750 SCIF */ ! #define SCIF_FER 0x0008 /* 7709 SCIF, 7750 SCIF */ ! #define SCIF_PER 0x0004 /* 7709 SCIF, 7750 SCIF */ ! #define SCIF_RDF 0x0002 /* 7709 SCIF, 7750 SCIF */ ! #define SCIF_DR 0x0001 /* 7709 SCIF, 7750 SCIF */ ! ! #define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK) ! ! #if defined(SCI_ONLY) ! # define SCxSR_TEND(port) SCI_TEND ! # define SCxSR_ERRORS(port) SCI_ERRORS ! # define SCxSR_RDxF(port) SCI_RDRF ! # define SCxSR_TDxE(port) SCI_TDRE ! # define SCxSR_RDxF_CLEAR(port) 0xbc ! # define SCxSR_ERROR_CLEAR(port) 0xc4 ! # define SCxSR_TDxE_CLEAR(port) 0x78 ! #elif defined(SCIF_ONLY) ! # define SCxSR_TEND(port) SCIF_TEND ! # define SCxSR_ERRORS(port) SCIF_ERRORS ! # define SCxSR_RDxF(port) SCIF_RDF ! # define SCxSR_TDxE(port) SCIF_TDFE ! # define SCxSR_RDxF_CLEAR(port) 0x00fc ! # define SCxSR_ERROR_CLEAR(port) 0x0063 ! # define SCxSR_TDxE_CLEAR(port) 0x00df ! #else ! # define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND) ! # define SCxSR_ERRORS(port) (((port)->type == PORT_SCI) ? SCI_ERRORS : SCIF_ERRORS) ! # define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF) ! # define SCxSR_TDxE(port) (((port)->type == PORT_SCI) ? SCI_TDRE : SCIF_TDFE) ! # define SCxSR_RDxF_CLEAR(port) (((port)->type == PORT_SCI) ? 0xbc : 0x00fc) ! # define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0063) ! # define SCxSR_TDxE_CLEAR(port) (((port)->type == PORT_SCI) ? 0x78 : 0x00df) #endif ! /* SCFCR */ ! #define SCFCR_RFRST 0x0002 ! #define SCFCR_TFRST 0x0004 ! #define SCFCR_MCE 0x0008 #define SCI_PRIORITY 3 #define SCI_MINOR_START 64 + + /* Generic serial flags */ #define SCI_RX_THROTTLE 0x0000001 + /* generic serial tty */ #define O_OTHER(tty) \ ((O_OLCUC(tty)) ||\ (O_ONLCR(tty)) ||\ *************** *** 171,185 **** #define SCI_MAGIC 0xbabeface - #ifdef GENERIC_SERIAL_H struct sci_port { struct gs_port gs; unsigned int old_cflag; }; #endif ! #define WAIT_RFCR_COUNTER 200 /* * Values for the BitRate Register (SCBRR) * --- 157,244 ---- #define SCI_MAGIC 0xbabeface struct sci_port { struct gs_port gs; + int type; + unsigned int base; + unsigned char irqs[3]; /* ERI, RXI, TXI */ + unsigned int intc_addr, intc_pos; + void (*init_pins)(struct sci_port* port, unsigned int cflag); unsigned int old_cflag; }; + + #define SCI_IN(size, offset) \ + unsigned int addr = port->base + (offset); \ + if ((size) == 8) { \ + return ctrl_inb(addr); \ + } else { \ + return ctrl_inw(addr); \ + } + #define SCI_OUT(size, offset, value) \ + unsigned int addr = port->base + (offset); \ + if ((size) == 8) { \ + ctrl_outb(value, addr); \ + } else { \ + ctrl_outw(value, addr); \ + } + + #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ + static inline unsigned int sci_##name##_in(struct sci_port* port) \ + { \ + if (port->type == PORT_SCI) { \ + SCI_IN(sci_size, sci_offset) \ + } else { \ + SCI_IN(scif_size, scif_offset); \ + } \ + } \ + static inline void sci_##name##_out(struct sci_port* port, unsigned int value) \ + { \ + if (port->type == PORT_SCI) { \ + SCI_OUT(sci_size, sci_offset, value) \ + } else { \ + SCI_OUT(scif_size, scif_offset, value); \ + } \ + } + + #define CPU_SCIF_FNS(name, scif_offset, scif_size) \ + static inline unsigned int sci_##name##_in(struct sci_port* port) \ + { \ + SCI_IN(scif_size, scif_offset); \ + } \ + static inline void sci_##name##_out(struct sci_port* port, unsigned int value) \ + { \ + SCI_OUT(scif_size, scif_offset, value); \ + } + + #ifdef __sh3__ + #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ + sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ + CPU_SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh3_scif_offset, sh3_scif_size) + #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ + CPU_SCIF_FNS(name, sh3_scif_offset, sh3_scif_size) + #else + #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ + sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ + CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size) + #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ + CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) #endif + + /* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 */ + /* name off sz off sz off sz off sz */ + SCIx_FNS(SCSMR, 0x00, 8, 0x00, 8, 0x00, 8, 0x00, 16) + SCIx_FNS(SCBRR, 0x02, 8, 0x04, 8, 0x02, 8, 0x04, 8) + SCIx_FNS(SCSCR, 0x04, 8, 0x08, 8, 0x04, 8, 0x08, 16) + SCIx_FNS(SCxTDR, 0x06, 8, 0x0c, 8, 0x06, 8, 0x0C, 8) + SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16) + SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8) + SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16) + SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) ! #define sci_in(port, reg) sci_##reg##_in(port) ! #define sci_out(port, reg, value) sci_##reg##_out(port, value) + /* * Values for the BitRate Register (SCBRR) * *************** *** 228,234 **** } #endif ! static __inline__ void put_char(char c) { unsigned long flags; unsigned short status; --- 287,293 ---- } #endif ! static __inline__ void put_char(struct sci_port *port, char c) { unsigned long flags; unsigned short status; *************** *** 236,273 **** save_and_cli(flags); do ! status = ctrl_in(SC_SR); ! while (!(status & SCI_TD_E)); ! ! ctrl_outb(c, SC_TDR); ! ctrl_in(SC_SR); /* Dummy read */ ! ctrl_out(SCI_TD_E_CLEAR, SC_SR); restore_flags(flags); } ! static __inline__ void handle_error(void) { /* Clear error flags */ ! ctrl_out(SCI_ERROR_CLEAR, SC_SR); } ! static __inline__ int get_char(void) { unsigned long flags; unsigned short status; int c; save_and_cli(flags); ! do { ! status = ctrl_in(SC_SR); ! if (status & SCI_ERRORS) { ! handle_error(); continue; } ! } while (!(status & SCI_RD_F)); ! c = ctrl_inb(SC_RDR); ! ctrl_in(SC_SR); /* Dummy read */ ! ctrl_out(SCI_RDRF_CLEAR, SC_SR); restore_flags(flags); return c; --- 295,332 ---- save_and_cli(flags); do ! status = sci_in(port, SCxSR); ! while (!(status & SCxSR_TDxE(port))); ! ! sci_out(port, SCxTDR, c); ! sci_in(port, SCxSR); /* Dummy read */ ! sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); restore_flags(flags); } ! static __inline__ void handle_error(struct sci_port *port) { /* Clear error flags */ ! sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); } ! static __inline__ int get_char(struct sci_port *port) { unsigned long flags; unsigned short status; int c; save_and_cli(flags); ! do { ! status = sci_in(port, SCxSR); ! if (status & SCxSR_ERRORS(port)) { ! handle_error(port); continue; } ! } while (!(status & SCxSR_RDxF(port))); ! c = sci_in(port, SCxRDR); ! sci_in(port, SCxSR); /* Dummy read */ ! sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); restore_flags(flags); return c; *************** *** 278,284 **** * This routine does not wait for a positive acknowledge. */ ! static __inline__ void put_string(const char *buffer, int count) { int i; const unsigned char *p = buffer; --- 337,344 ---- * This routine does not wait for a positive acknowledge. */ ! static __inline__ void put_string(struct sci_port *port, ! const char *buffer, int count) { int i; const unsigned char *p = buffer; *************** *** 289,296 **** /* $<packet info>#<checksum>. */ do { unsigned char c; ! put_char('$'); ! put_char('O'); /* 'O'utput to console */ checksum = 'O'; for (i=0; i<count; i++) { /* Don't use run length encoding */ --- 349,356 ---- /* $<packet info>#<checksum>. */ do { unsigned char c; ! put_char(port, '$'); ! put_char(port, 'O'); /* 'O'utput to console */ checksum = 'O'; for (i=0; i<count; i++) { /* Don't use run length encoding */ *************** *** 299,317 **** c = *p++; h = highhex(c); l = lowhex(c); ! put_char(h); ! put_char(l); checksum += h + l; } ! put_char('#'); ! put_char(highhex(checksum)); ! put_char(lowhex(checksum)); ! } while (get_char() != '+'); } else #endif for (i=0; i<count; i++) { if (*p == 10) ! put_char('\r'); ! put_char(*p++); } } --- 359,377 ---- c = *p++; h = highhex(c); l = lowhex(c); ! put_char(port, h); ! put_char(port, l); checksum += h + l; } ! put_char(port, '#'); ! put_char(port, highhex(checksum)); ! put_char(port, lowhex(checksum)); ! } while (get_char(port) != '+'); } else #endif for (i=0; i<count; i++) { if (*p == 10) ! put_char(port, '\r'); ! put_char(port, *p++); } } |