/****************************************/ /* MES/Copyleft Yukio Mituiwa,2005 */ /* */ /* 2008/8/1 first release */ /* */ /****************************************/ #include #include #include #include #ifdef _KERNEL_ #include "mes.h" #define device_main(arg1,arg2) init_sci(arg1, arg2) #endif #if defined(STR_71x) #include <71x_lib.h> #define SCINUM 4 #endif #if defined(__sh2__) #define SCINUM 4 #endif #if defined(__sh3__) || defined(__SH2A__) #define SCINUM 5 #endif #if defined(__SH4A__) #define SCINUM 6 #endif #define PARITY_NONE 0 #define PARITY_ODD 1 #define PARITY_EVEN 2 #define BUFSIZ 32 #define SMR *(sci[minor].smr) #define BRR *(sci[minor].brr) #define SCR *(sci[minor].scr) #define TDR *(sci[minor].tdr) #define SSR *(sci[minor].ssr) #define RDR *(sci[minor].rdr) #define SAR *(sci[minor].sar) #define DAR *(sci[minor].dar) #define DMATCR *(sci[minor].dmatcr) #define CHCR *(sci[minor].chcr) #define SMRW *(sci[minor].smr_w) #define SCRW *(sci[minor].scr_w) #define SSRW *(sci[minor].ssr_w) #define SCFDR *(sci[minor].scfdr) #define SCFCR *(sci[minor].scfcr) #define SCFCRW *(sci[minor].scfcr_w) #define SCLSR *(sci[minor].sclsr) #define FIFO sci[minor].fifo #define RBR 0 #define THR 0 #define IER 1 #define IIR 2 #define FCR 2 #define LCR 3 #define MCR 4 #define LSR 5 #define DLH 1 #define DLL 0 typedef volatile struct { unsigned char *base; unsigned int freq, speed; IOREG rx_bit, tx_bit; #if defined(__sh__) volatile unsigned char *smr; volatile unsigned char *brr; volatile unsigned char *scr; volatile unsigned char *tdr; volatile unsigned char *ssr; volatile unsigned char *rdr; volatile unsigned short *smr_w; volatile unsigned short *scr_w; volatile unsigned short *ssr_w; volatile unsigned short *sclsr; volatile unsigned short *scfcr_w; volatile unsigned char *scfcr; volatile unsigned short *scfdr; volatile unsigned int *sar; volatile unsigned int *dar; volatile unsigned int *dmatcr; volatile unsigned int *chcr; #endif unsigned int option; struct termios tm; unsigned char buf[BUFSIZ]; unsigned char rx_port, tx_port; unsigned char dmac, fifo; unsigned char buswidth; unsigned char wait; unsigned char usage; } SCIInfo; static SCIInfo *sci; static char chip; static int read_raw(int, char*, int); static int write_raw(int, char*, int); static int write_sci(int, char*, int); static int read_sci(int, char*, int); static int ioctl_sci_freq(int, int); static int ioctl_sci_speed(int, int); static int ioctl_sci_data(int, int); static int ioctl_sci_stop(int, int); static int ioctl_sci_parity(int, int); static void out(int, int, int); static int in(int, int); static int ajust_termios_speed(int); static void out(int minor, int addr, int data) { if(sci[minor].buswidth == 16) { sci[minor].base[addr * 2] = data; }else { sci[minor].base[addr] = data; } } static int in(int minor, int addr) { int data; if(sci[minor].buswidth == 16) { data = sci[minor].base[addr * 2]; } else { data = sci[minor].base[addr]; } return data; } static int open_sci(int minor, int option) { volatile int w; unsigned int base = 0; #if defined(STR_71x) UART_TypeDef *uart; #endif if(chip == CHIP_7763) { if(minor >= 2) return -1; } else { if(minor >= SCINUM) return -1; } if((chip == CHIP_7706 || chip == CHIP_7721 || chip == CHIP_7763) && minor >= 3 && sci[minor].base == 0) return -1; if(sci[minor].speed == 0) return -1; if(option == -1) return 0; sci[minor].option = option; if(sci[minor].usage == 0) { sci[minor].tm.c_iflag = 0; sci[minor].tm.c_oflag = 0; sci[minor].tm.c_cflag = ajust_termios_speed(minor) | CS8 | CLOCAL | CREAD; sci[minor].tm.c_lflag = 0; sci[minor].tm.c_line = 0; bzero(sci[minor].tm.c_cc, NCCS); sci[minor].usage = 1; } sio_control(minor, 'R', sci[minor].rx_port, sci[minor].rx_bit); sio_control(minor, 'T', sci[minor].tx_port, sci[minor].tx_bit); FIFO = 0; #if defined(__sh__) switch(chip) { case CHIP_7045: base = 0xffff81a0 + minor * 0x10; sci[minor].smr = (volatile unsigned char *)(base + 0); sci[minor].brr = (volatile unsigned char *)(base + 1); sci[minor].scr = (volatile unsigned char *)(base + 2); sci[minor].tdr = (volatile unsigned char *)(base + 3); sci[minor].ssr = (volatile unsigned char *)(base + 4); sci[minor].rdr = (volatile unsigned char *)(base + 5); base = 0xffff86c0 + sci[minor].dmac * 0x10; break; case CHIP_7085: base = 0xffffc000 + minor * 0x80; sci[minor].smr = (volatile unsigned char *)(base + 0); sci[minor].brr = (volatile unsigned char *)(base + 2); sci[minor].scr = (volatile unsigned char *)(base + 4); sci[minor].tdr = (volatile unsigned char *)(base + 6); sci[minor].ssr = (volatile unsigned char *)(base + 8); sci[minor].rdr = (volatile unsigned char *)(base + 10); if(minor == 3) { FIFO = 1; sci[minor].smr_w = (volatile unsigned short *)(base + 0); sci[minor].scr_w = (volatile unsigned short *)(base + 4); sci[minor].ssr_w = (volatile unsigned short *)(base + 8); sci[minor].scfcr_w = (volatile unsigned short *)(base + 12); sci[minor].sclsr = (volatile unsigned short *)(base + 18); sci[minor].scfdr = (volatile unsigned short *)(base + 14); } base = 0xffffeb20 + sci[minor].dmac * 0x10; break; case CHIP_7216: sci[minor].dmac = 0xff; base = 0xffff8000 + minor * 0x800; sci[minor].smr = (volatile unsigned char *)(base + 0); sci[minor].brr = (volatile unsigned char *)(base + 2); sci[minor].scr = (volatile unsigned char *)(base + 4); sci[minor].tdr = (volatile unsigned char *)(base + 6); sci[minor].ssr = (volatile unsigned char *)(base + 8); sci[minor].rdr = (volatile unsigned char *)(base + 10); if(minor == 3) { FIFO = 1; sci[minor].smr_w = (volatile unsigned short *)(base + 0); sci[minor].brr = (volatile unsigned char *)(base + 4); sci[minor].scr_w = (volatile unsigned short *)(base + 8); sci[minor].tdr = (volatile unsigned char *)(base + 12); sci[minor].ssr_w = (volatile unsigned short *)(base + 16); sci[minor].rdr = (volatile unsigned char *)(base + 20); sci[minor].scfcr_w = (volatile unsigned short *)(base + 24); sci[minor].scfdr = (volatile unsigned short *)(base + 28); sci[minor].sclsr = (volatile unsigned short *)(base + 36); } break; case CHIP_7706: sci[minor].dmac = 0xff; if(minor >= 3) { set_buswidth((int)sci[minor].base, sci[minor].buswidth, sci[minor].wait); FIFO = 2; } else if(minor == 0) { base = 0xfffffe80; sci[minor].smr = (volatile unsigned char *)(base + 0); sci[minor].brr = (volatile unsigned char *)(base + 2); sci[minor].scr = (volatile unsigned char *)(base + 4); sci[minor].tdr = (volatile unsigned char *)(base + 6); sci[minor].ssr = (volatile unsigned char *)(base + 8); sci[minor].rdr = (volatile unsigned char *)(base + 10); } else { FIFO = 1; base = 0xa4000130 + minor * 0x10; sci[minor].smr = (volatile unsigned char *)(base + 0); sci[minor].brr = (volatile unsigned char *)(base + 2); sci[minor].scr = (volatile unsigned char *)(base + 4); sci[minor].tdr = (volatile unsigned char *)(base + 6); sci[minor].ssr_w = (volatile unsigned short *)(base + 8); sci[minor].rdr = (volatile unsigned char *)(base + 10); sci[minor].scfcr = (volatile unsigned char *)(base + 12); sci[minor].scfdr = (volatile unsigned short *)(base + 14); } break; case CHIP_7721: sci[minor].dmac = 0xff; if(minor >= 2) { set_buswidth((int)sci[minor].base, sci[minor].buswidth, sci[minor].wait); FIFO = 2; } else { FIFO = 1; base = 0xa4430000 + minor * 0x8000; sci[minor].smr_w = (volatile unsigned short *)(base + 0); sci[minor].brr = (volatile unsigned char *)(base + 4); sci[minor].scr_w = (volatile unsigned short *)(base + 8); sci[minor].ssr_w = (volatile unsigned short *)(base + 20); sci[minor].scfcr_w = (volatile unsigned short *)(base + 24); sci[minor].scfdr = (volatile unsigned short *)(base + 28); sci[minor].tdr = (volatile unsigned char *)(base + 32); sci[minor].rdr = (volatile unsigned char *)(base + 36); } break; case CHIP_7763: sci[minor].dmac = 0xff; if(minor >= 2) { set_buswidth((int)sci[minor].base, sci[minor].buswidth, sci[minor].wait); FIFO = 2; } else { FIFO = 1; base = 0xffe00000 + minor * 0x8000; sci[minor].smr_w = (volatile unsigned short *)(base + 0); sci[minor].brr = (volatile unsigned char *)(base + 4); sci[minor].scr_w = (volatile unsigned short *)(base + 8); sci[minor].tdr = (volatile unsigned char *)(base + 12); sci[minor].ssr_w = (volatile unsigned short *)(base + 16); sci[minor].rdr = (volatile unsigned char *)(base + 20); sci[minor].scfcr_w = (volatile unsigned short *)(base + 24); } break; case CHIP_7730: sci[minor].dmac = 0xff; FIFO = 1; base = 0xffe00000 + minor * 0x10000; sci[minor].smr_w = (volatile unsigned short *)(base + 0); sci[minor].brr = (volatile unsigned char *)(base + 4); sci[minor].scr_w = (volatile unsigned short *)(base + 8); sci[minor].ssr_w = (volatile unsigned short *)(base + 16); sci[minor].scfcr_w = (volatile unsigned short *)(base + 24); sci[minor].scfdr = (volatile unsigned short *)(base + 28); sci[minor].tdr = (volatile unsigned char *)(base + 12); sci[minor].rdr = (volatile unsigned char *)(base + 20); break; } if(chip == CHIP_7045 || chip == CHIP_7085) { if(minor >= 2) sci[minor].dmac = 0xff; if(sci[minor].dmac > 3) sci[minor].dmac = 0xff; if(sci[minor].dmac != 0xff) { sci[minor].sar = (volatile unsigned int *)(base + 0); sci[minor].dar = (volatile unsigned int *)(base + 4); sci[minor].dmatcr = (volatile unsigned int *)(base + 8); sci[minor].chcr = (volatile unsigned int *)(base + 12); DAR = (int)(sci[minor].buf); DMATCR = BUFSIZ; SAR = (int)sci[minor].rdr; switch(minor) { case 0: CHCR = 0x00004d01; break; case 1: CHCR = 0x00004f01; break; } } } if(FIFO == 1 && (chip == CHIP_7085 || chip == CHIP_7216)) { SCLSR &= ~0x0001; SCRW = 0x0000; SCFCRW = 0x0006; SMRW = 0x0000; for(w = 0;w < 10000;w++); SCFCRW = 0x0000; SSRW = 0x0063; ioctl_sci_freq(minor, sci[minor].freq); ioctl_sci_speed(minor, sci[minor].speed); SCRW = 0x0030; } else if(FIFO == 1 && chip == CHIP_7706) { SCR = 0x00; SCFCR = 0x06; SMR = 0x00; for(w = 0;w < 10000;w++); SCFCR = 0x00; SSRW = 0x0063; ioctl_sci_freq(minor, sci[minor].freq); ioctl_sci_speed(minor, sci[minor].speed); SCR = 0x30; } else if(FIFO == 1 && (chip == CHIP_7721 || chip == CHIP_7763)) { SCRW = 0x0000; SCFCRW = 0x0006; SMRW = 0x0000; for(w = 0;w < 10000;w++); SCFCRW = 0x0000; SSRW = 0x0063; ioctl_sci_freq(minor, sci[minor].freq); ioctl_sci_speed(minor, sci[minor].speed); SCRW = 0x0030; } else if(FIFO == 2) { out(minor, LCR, 0x03); // Parity none/Stop 1bit/Data 8bit out(minor, MCR, 0x00); out(minor, IER, 0x00); // Interrupt none out(minor, FCR, 0xf7); ioctl_sci_freq(minor, sci[minor].freq); ioctl_sci_speed(minor, sci[minor].speed); out(minor, FCR, 0xf1); } else { SMR = 0; SCR = 0; for(w = 0;w < 1000;w++); w = SSR; SSR &= ~0x80; ioctl_sci_freq(minor, sci[minor].freq); ioctl_sci_speed(minor, sci[minor].speed); SCR |= 0x70; } #endif #if defined(STR_71x) uart = ((UART_TypeDef *)(APB1_BASE + 0x4000 + minor * 0x1000)); UART_Init(uart); UART_Config(uart, sci[minor].speed, UART_NO_PARITY, UART_1_StopBits, UARTM_8D); UART_FifoReset(uart, UART_RxFIFO); UART_FifoReset(uart, UART_TxFIFO); UART_OnOffConfig(uart, ENABLE); UART_RxConfig(uart, ENABLE); #endif return 0; } static int close_sci(int minor) { if(minor >= SCINUM) return -1; return 0; } static int write_raw(int minor, char *buffer, int size) { int i; i = 0; if(minor >= SCINUM) return -1; #if defined(__sh__) switch(FIFO) { case 0: for(i = 0;i < size;i++) { while(!(SSR & 0x80)); TDR = buffer[i]; SSR &= ~0x80; } while(!(SSR & 0x04)); break; case 1: if(chip == CHIP_7085 || chip == CHIP_7216) { if(SCLSR & 0x0001) SCLSR &= ~0x0001; } if(SSRW & 0x008c) SSRW &= ~0x008c; for(i = 0;i < size;i++) { while((SSRW & 0x20) == 0); TDR = buffer[i]; SSRW &= ~0x20; } break; case 2: for(i = 0;i < size;i++) { while((in(minor, LSR) & 0x20) == 0); out(minor, THR, buffer[i]); } break; } #endif return i; } static int read_raw(int minor, char *buffer, int _size) { int i, size, asize; #if defined(STR_71x) UART_TypeDef *uart; #endif if(minor >= SCINUM) return -1; #if defined(__sh__) switch(FIFO) { case 1: if(chip == CHIP_7085 || chip == CHIP_7216) { if(SCLSR & 0x0001) SCLSR &= ~0x0001; } if(SSRW & 0x008c) SSRW &= ~0x008c; for(i = 0;i < _size;i++) { if((SSRW & 0x02) == 0) break; buffer[i] = RDR; SSRW &= ~0x02; } size = i; return (size == 0 && (sci[minor].option & O_NDELAY) == 0) ? -2 : size; case 2: for(i = 0;i < _size;i++) { if((in(minor, LSR) & 0x01) == 0) break; buffer[i] = in(minor, RBR); } size = i; return (size == 0 && (sci[minor].option & O_NDELAY) == 0) ? -2 : size; } if(SSR & 0x38) { SSR &= ~0x38; return ((sci[minor].option & O_NDELAY) == 0) ? -2 : 0; } if(sci[minor].dmac == 0xff) { size = 0; if(SSR & 0x40) { buffer[size++] = RDR; SSR &= ~0x40; } } else { if(DMATCR == 0) { CHCR &= ~0x0003; DAR = (int)(sci[minor].buf); DMATCR = BUFSIZ; size = 0; if(SSR & 0x40) { buffer[size++] = RDR; SSR &= ~0x40; } } else { while(SSR & 0x40); CHCR &= ~0x0001; asize = BUFSIZ - DMATCR; size = (_size > asize) ? asize : _size; memcpy(buffer, (char*)(sci[minor].buf), size); for(i = size;i < asize;i++) sci[minor].buf[i - size] = sci[minor].buf[i]; DMATCR += size; DAR -= size; } CHCR |= 0x0001; } #endif return (size == 0 && (sci[minor].option & O_NDELAY) == 0) ? -2 : size; } static int write_sci(int minor, char *buffer, int size) { int i, ret; char c; if((sci[minor].option & O_NOCTTY) == 0) { for(i = 0;i < size;i++) { c = buffer[i]; if((sci[minor].tm.c_oflag & ONLRET) == 0 && c != '\r'){ if(sci[minor].tm.c_oflag & ONLCR && c == '\n') { write_raw(minor, "\r", 1); } if(sci[minor].tm.c_oflag & OCRNL && c == '\r') c = '\n'; write_raw(minor, &c, 1); } } ret = size; } else { ret = write_raw(minor, buffer, size); } return ret; } static int read_sci(int minor, char *buffer, int size) { int i, ret, n; char c; if((sci[minor].option & O_NOCTTY) == 0) { for(i = 0;i < size;i++) { ret = read_raw(minor, &c, 1); if(ret <= 0) break; if(sci[minor].tm.c_iflag & IGNCR && c == '\r') { i--; } else { if(sci[minor].tm.c_iflag & INLCR && c == '\n') c = '\r'; if(sci[minor].tm.c_iflag & ICRNL && c == '\r') c = '\n'; buffer[i] = c; if(sci[minor].tm.c_lflag & ECHO) write_sci(minor, &c, 1); } } if(ret >= 0 || i > 0) ret = i; } else { ret = read_raw(minor, buffer, size); } return ret; } static int seek_sci(int minor, int pos) { if(minor >= SCINUM) return -1; return 0; } static int ioctl_sci_freq(int minor, int freq) { if(minor >= SCINUM) return -1; sci[minor].freq = freq; return 0; } static int ioctl_sci_speed(int minor, int speed) { unsigned int i, x, y, b, s; unsigned char lcr; #if defined(STR_71x) UART_TypeDef *uart; #endif if(minor >= SCINUM) return -1; sci[minor].speed = speed; sci[minor].tm.c_cflag &= ~017; sci[minor].tm.c_cflag |= ajust_termios_speed(minor); #if defined(__sh__) if(FIFO == 2) { s = 16; x = sci[minor].freq * 10; y = s * speed; b = x / y + 5; b = b / 10; lcr = in(minor, LCR); out(minor, LCR, 0x80); out(minor, DLH, b >> 8); out(minor, DLL, b); out(minor, LCR, lcr); } else { s = 32; for(i = 0;i < 4;i++) { if(chip == CHIP_7721) { x = sci[minor].freq * 20; } else { x = sci[minor].freq * 10; } y = s * speed; b = x / y + 5; b = b / 10 - 1; if(b <= 255) break; s <<= 2; } if(i == 4) return -1; if((chip == CHIP_7085 || chip == CHIP_7216 || chip == CHIP_7721 || chip == CHIP_7763) && FIFO == 1) { SMRW &= ~0x03; SMRW |= i; } else { SMR &= ~0x03; SMR |= i; } BRR = b; } #endif #if defined(STR_71x) uart = ((UART_TypeDef *)(APB1_BASE + 0x4000 + minor * 0x1000)); UART_BaudRateConfig(uart, speed); #endif return 0; } static int ioctl_sci_data(int minor, int size) { unsigned char lcr; #if defined(STR_71x) UART_TypeDef *uart; #endif if(minor >= SCINUM) return -1; #if defined(__sh__) if(size < 5 || size > 8) return -1; sci[minor].tm.c_cflag &= ~CSIZE; switch(size){ case 5: sci[minor].tm.c_cflag |= CS5; break; case 6: sci[minor].tm.c_cflag |= CS6; break; case 7: sci[minor].tm.c_cflag |= CS7; break; case 8: sci[minor].tm.c_cflag |= CS8; break; } if(FIFO == 2) { lcr = in(minor, LCR); lcr &= ~0x03; switch(size) { case 6: lcr |= 0x01; break; case 7: lcr |= 0x02; break; case 8: lcr |= 0x03; break; } out(minor, LCR, lcr); } else { if(size < 7) return -1; if((chip == CHIP_7085 || chip == CHIP_7216 || chip == CHIP_7721 || chip == CHIP_7763) && FIFO == 1) { if(size == 8) SMRW &= ~0x40; if(size == 7) SMRW |= 0x40; } else { if(size == 8) SMR &= ~0x40; if(size == 7) SMR |= 0x40; } } #endif #if defined(STR_71x) if(size < 8 || size > 9) return -1; uart = ((UART_TypeDef *)(APB1_BASE + 0x4000 + minor * 0x1000)); switch(size) { case 8: UART_ModeConfig(uart, UARTM_8D); break; case 9: UART_ModeConfig(uart, UARTM_9D); break; } #endif return 0; } static int ioctl_sci_stop(int minor, int stop) { unsigned char lcr; #if defined(STR_71x) UART_TypeDef *uart; #endif if(minor >= SCINUM) return -1; switch(stop){ case 1: sci[minor].tm.c_cflag &= ~CSTOPB; break; case 2: sci[minor].tm.c_cflag |= CSTOPB; break; default: return -1; } #if defined(__sh__) if(FIFO == 2) { lcr = in(minor, LCR); if(stop == 1) lcr &= ~0x04; if(stop == 2) lcr |= 0x04; out(minor, LCR, lcr); } else { if((chip == CHIP_7085 || chip == CHIP_7216 || chip == CHIP_7721 || chip == CHIP_7763) && FIFO == 1) { if(stop == 1) SMRW &= ~0x08; if(stop == 2) SMRW |= 0x08; } else { if(stop == 1) SMR &= ~0x08; if(stop == 2) SMR |= 0x08; } } #endif #if defined(STR_71x) uart = ((UART_TypeDef *)(APB1_BASE + 0x4000 + minor * 0x1000)); UART_StopBitsConfig(uart, (stop == 1) ? UART_1_StopBits : UART_2_StopBits); #endif return 0; } static int ioctl_sci_parity(int minor, int parity) { unsigned char lcr; #if defined(STR_71x) UART_TypeDef *uart; #endif if(minor >= SCINUM) return -1; switch(parity) { case PARITY_NONE: sci[minor].tm.c_cflag &= ~(PARENB | PAODD); break; case PARITY_EVEN: sci[minor].tm.c_cflag |= PARENB; sci[minor].tm.c_cflag &= ~PAODD; break; case PARITY_ODD: sci[minor].tm.c_cflag |= (PARENB | PAODD); break; default: return -1; } #if defined(__sh__) if(FIFO == 2) { lcr = in(minor, LCR); switch(parity) { case PARITY_NONE: lcr &= ~0x20; break; case PARITY_ODD: lcr |= 0x20; lcr &= ~0x10; break; case PARITY_EVEN: lcr |= 0x30; break; } out(minor, LCR, lcr); } else { if((chip == CHIP_7085 || chip == CHIP_7216 || chip == CHIP_7721 || chip == CHIP_7763) && FIFO == 1) { switch(parity) { case PARITY_NONE: SMRW &= ~0x20; break; case PARITY_ODD: SMRW |= 0x20; SMRW &= ~0x10; break; case PARITY_EVEN: SMRW |= 0x30; break; } } else { switch(parity) { case PARITY_NONE: SMR &= ~0x20; break; case PARITY_ODD: SMR |= 0x20; SMR &= ~0x10; break; case PARITY_EVEN: SMR |= 0x30; break; } } } #endif #if defined(STR_71x) uart = ((UART_TypeDef *)(APB1_BASE + 0x4000 + minor * 0x1000)); switch(parity) { case PARITY_NONE: UART_ParityConfig(uart, UART_NO_PARITY); break; case PARITY_ODD: UART_ParityConfig(uart, UART_ODD_PARITY); break; case PARITY_EVEN: UART_ParityConfig(uart, UART_EVEN_PARITY); break; } #endif return 0; } static int ajust_termios_speed(int minor) { int tm_speed; if(sci[minor].speed < 130) { sci[minor].speed = 110; tm_speed = B110; } else if(sci[minor].speed < 175) { sci[minor].speed = 150; tm_speed = B150; } else if(sci[minor].speed < 250) { sci[minor].speed = 200; tm_speed = B200; } else if(sci[minor].speed < 450) { sci[minor].speed = 300; tm_speed = B300; } else if(sci[minor].speed < 900) { sci[minor].speed = 600; tm_speed = B600; } else if(sci[minor].speed < 1500) { sci[minor].speed = 1200; tm_speed = B1200; } else if(sci[minor].speed < 2100) { sci[minor].speed = 1800; tm_speed = B1800; } else if(sci[minor].speed < 3600) { sci[minor].speed = 2400; tm_speed = B2400; } else if(sci[minor].speed < 7200) { sci[minor].speed = 4800; tm_speed = B4800; } else if(sci[minor].speed < 14400) { sci[minor].speed = 9600; tm_speed = B9600; } else if(sci[minor].speed < 28800) { sci[minor].speed = 19200; tm_speed = B19200; } else if(sci[minor].speed < 48000) { sci[minor].speed = 38400; tm_speed = B38400; } else if(sci[minor].speed < 86400) { sci[minor].speed = 57600; tm_speed = B57600; } else if(sci[minor].speed < 172800) { sci[minor].speed = 115200; tm_speed = B115200; } else { sci[minor].speed = 230400; tm_speed = B230400; } return tm_speed; } static int ioctl_sci(int minor, int data, int op) { int ret, tm_speed; struct termios *tm; ret = 0; tm = (struct termios *)data; switch(op) { case DEV_ATTR: break; case DEV_INFO: break; case SCI_FREQ: ret = ioctl_sci_freq(minor, data); break; case SCI_SPEED: ret = ioctl_sci_speed(minor, data); break; case SCI_DATA: ret = ioctl_sci_data(minor, data); break; case SCI_STOP: ret = ioctl_sci_stop(minor, data); break; case SCI_PARITY_NONE: ret = ioctl_sci_parity(minor, PARITY_NONE); break; case SCI_PARITY_ODD: ret = ioctl_sci_parity(minor, PARITY_ODD); break; case SCI_PARITY_EVEN: ret = ioctl_sci_parity(minor, PARITY_EVEN); break; case SCI_XCGETA: tm->c_ispeed = 0; tm->c_ospeed = 0; tm->c_iflag = sci[minor].tm.c_iflag; tm->c_lflag = sci[minor].tm.c_lflag; tm->c_line = sci[minor].tm.c_line; tm->c_oflag = sci[minor].tm.c_oflag; tm->c_cflag = sci[minor].tm.c_cflag; break; case SCI_XCSETAF: case SCI_XCSETA: case SCI_XCSETAW: sci[minor].tm.c_iflag = tm->c_iflag; sci[minor].tm.c_lflag = tm->c_lflag; sci[minor].tm.c_line = tm->c_line; sci[minor].tm.c_oflag = tm->c_oflag; sci[minor].tm.c_cflag = tm->c_cflag; if(tm->c_cflag & 017) { tm_speed = tm->c_cflag & 017; switch(tm_speed) { case B110: ioctl_sci_speed(minor, 110); break; case B150: ioctl_sci_speed(minor, 150); break; case B200: ioctl_sci_speed(minor, 200); break; case B300: ioctl_sci_speed(minor, 300); break; case B600: ioctl_sci_speed(minor, 600); break; case B1200: ioctl_sci_speed(minor, 1200); break; case B1800: ioctl_sci_speed(minor, 1800); break; case B2400: ioctl_sci_speed(minor, 2400); break; case B4800: ioctl_sci_speed(minor, 4800); break; case B9600: ioctl_sci_speed(minor, 9600); break; case B19200: ioctl_sci_speed(minor, 19200); break; case B38400: ioctl_sci_speed(minor, 38400); break; case B57600: ioctl_sci_speed(minor, 57600); break; case B115200: ioctl_sci_speed(minor, 115200); break; case B230400: ioctl_sci_speed(minor, 230400); break; } } switch(tm->c_cflag & CSIZE) { case CS5: ioctl_sci_stop(minor, 5); break; case CS6: ioctl_sci_stop(minor, 6); break; case CS7: ioctl_sci_stop(minor, 7); break; case CS8: ioctl_sci_stop(minor, 8); break; } if(tm->c_cflag & CSTOPB) ioctl_sci_stop(minor, 2); else ioctl_sci_stop(minor, 1); if(tm->c_cflag & PARENB) { if(tm->c_cflag & PAODD) { ioctl_sci_parity(minor, PARITY_ODD); } else { ioctl_sci_parity(minor, PARITY_EVEN); } } else { ioctl_sci_parity(minor, PARITY_NONE); } break; default: ret = -1; } return ret; } static Functions func; int device_main(int argc, char **argv) { unsigned int minor; int n, p; n = mesver() >> 24; chip = n; minor = 0; sci = (SCIInfo*)malloc(sizeof(SCIInfo) * SCINUM); for(minor = 0;minor < SCINUM;minor++) { sci[minor].rx_port = 0; sci[minor].rx_bit = 0; sci[minor].tx_port = 0; sci[minor].tx_bit = 0; sci[minor].speed = 0; sci[minor].dmac = 0xff; sci[minor].base = 0; sci[minor].freq = 0; sci[minor].usage = 0; } for(n = 0;n < argc;n++) { if(memcmp(argv[n], "sci", 3) == 0) { minor = stoi(&argv[n][3]); if(minor >= SCINUM) minor = 0; } else if(memcmp(argv[n], "freq=", 5) == 0) { sci[minor].freq = stoi(&argv[n][5]); } else if(memcmp(argv[n], "baud=", 5) == 0) { sci[minor].speed = stoi(&argv[n][5]); } else if(memcmp(argv[n], "dmac=", 5) == 0) { sci[minor].dmac = stoi(&argv[n][5]); } else if(memcmp(argv[n], "rxd=", 4) == 0) { p = port2num(&argv[n][4]); if(p != -1) sci[minor].rx_port = p; p = port2bit(&argv[n][4]); if(p != -1) sci[minor].rx_bit = 1 << p; } else if(memcmp(argv[n], "txd=", 4) == 0) { p = port2num(&argv[n][4]); if(p != -1) sci[minor].tx_port = p; p = port2bit(&argv[n][4]); if(p != -1) sci[minor].tx_bit = 1 << p; } else if(memcmp(argv[n], "addr=", 5) == 0) { sci[minor].base = (char*)stoi(&argv[n][5]); } else if(memcmp(argv[n], "bussiz=", 7) == 0) { sci[minor].buswidth = stoi(&argv[n][7]); } else if(memcmp(argv[n], "wait=", 5) == 0) { sci[minor].wait = stoi(&argv[n][5]); } } func.write_dev = write_sci; func.read_dev = read_sci; func.open_dev = open_sci; func.close_dev = close_sci; func.seek_dev = seek_sci; func.ioctl_dev = ioctl_sci; func.poll_dev = 0; strcpy(&(func.name[0]), "com"); device_return(&func); }