📄 moxa.c
字号:
ch->blocked_open = 0; ch->callout_termios = moxaCallout.init_termios; ch->normal_termios = moxaDriver.init_termios;#if (LINUX_VERSION_CODE < VERSION_CODE(2,4,0)) ch->open_wait = 0; ch->close_wait = 0;#else init_waitqueue_head(&ch->open_wait); init_waitqueue_head(&ch->close_wait);#endif } for ( i=0; i< MAX_BOARDS; i++ ) { moxa_boards[i].boardType = 0; moxa_boards[i].numPorts = 0; moxa_boards[i].baseAddr = 0; moxa_boards[i].busType = 0; moxa_boards[i].pciInfo.busNum = 0; moxa_boards[i].pciInfo.devNum = 0; } MoxaDriverInit(); printk("Tty devices major number = %d, callout devices major number = %d\n", ttymajor, calloutmajor); ret1 = 0; ret2 = 0; if ((ret1 = tty_register_driver(&moxaDriver))) { printk(KERN_ERR "Couldn't install MOXA Intellio family driver !\n"); } else if ((ret2 = tty_register_driver(&moxaCallout))) { tty_unregister_driver(&moxaDriver); printk(KERN_ERR "Couldn't install MOXA Intellio family callout driver !\n"); } if (ret1 || ret2) { return -1; } for (i = 0; i < MAX_PORTS; i++) { init_timer(&moxaEmptyTimer[i]); moxaEmptyTimer[i].function = check_xmit_empty; moxaEmptyTimer[i].data = (unsigned long) & moxaChannels[i]; moxaEmptyTimer_on[i] = 0; } init_timer(&moxaTimer); moxaTimer.function = moxa_poll; moxaTimer.expires = jiffies + (HZ / 50); moxaTimer_on = 1; add_timer(&moxaTimer); /* Find the boards defined in source code */ numBoards = 0; for (i = 0; i < MAX_BOARDS; i++) { if ((moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) || (moxa_isa_boards[i].boardType == MOXA_BOARD_C320_ISA)) { moxa_boards[numBoards].boardType = moxa_isa_boards[i].boardType; if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) moxa_boards[numBoards].numPorts = 8; else moxa_boards[numBoards].numPorts = moxa_isa_boards[i].numPorts; moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA; moxa_boards[numBoards].baseAddr = moxa_isa_boards[i].baseAddr; if (verbose) printk("Board %2d: %s board(baseAddr=%lx)\n", numBoards + 1, moxa_brdname[moxa_boards[numBoards].boardType - 1], moxa_boards[numBoards].baseAddr); numBoards++; } }/* Find the boards defined form module args. */#ifdef MODULE for (i = 0; i < MAX_BOARDS; i++) { if ((type[i] == MOXA_BOARD_C218_ISA) || (type[i] == MOXA_BOARD_C320_ISA)) { if (verbose) printk("Board %2d: %s board(baseAddr=%lx)\n", numBoards + 1, moxa_brdname[type[i] - 1], (unsigned long) baseaddr[i]); if (numBoards >= MAX_BOARDS) { if (verbose) printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS); continue; } moxa_boards[numBoards].boardType = type[i]; if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) moxa_boards[numBoards].numPorts = 8; else moxa_boards[numBoards].numPorts = numports[i]; moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA; moxa_boards[numBoards].baseAddr = baseaddr[i]; numBoards++; } }#endif/* start to finding PCI board here */#ifdef CONFIG_PCI#if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0)) if (pcibios_present()) {#else if (pci_present()) {#endif n = sizeof (moxa_pcibrds)/sizeof (moxa_pciinfo); index = 0; i = 0; while (i < n) { if (pcibios_find_device(moxa_pcibrds[i].vendor_id, moxa_pcibrds[i].device_id, index, &busnum, &devnum) != 0) { i++; index = 0; continue; } if (verbose) printk("Board %2d: %s board(BusNo=%d,DevNo=%d)\n", numBoards+1, moxa_brdname[moxa_pcibrds[i].board_type-1], busnum, devnum >> 3); index++; if ( numBoards >= MAX_BOARDS) { if (verbose) printk("More than %d MOXA Intellio family boards found. Board is ignored.",MAX_BOARDS); } else { moxa_get_PCI_conf(busnum,devnum, moxa_pcibrds[i].board_type, &moxa_boards[numBoards]); numBoards++; } } }#endif#if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0)) for ( i = 0; i < numBoards; i++) {#ifndef __alpha__ if (moxa_boards[i].baseAddr >= 0x100000) { moxaBaseAddr[i] = (unsigned long) ioremap((unsigned long)moxa_boards[i].baseAddr,0x4000); } else #endif moxaBaseAddr[i] = moxa_boards[i].baseAddr; }#else for ( i = 0; i < numBoards; i++) { moxaBaseAddr[i] = (unsigned long) ioremap((unsigned long)moxa_boards[i].baseAddr,0x4000); }#endif return(0);}#ifdef CONFIG_PCIstatic int moxa_get_PCI_conf(int busnum,int devnum,int board_type,moxa_board_conf *board){ unsigned int val; pcibios_read_config_dword(busnum,devnum,PCI_BASE_ADDRESS_2,&val); if (val == 0xffffffff) return (-1); else board->baseAddr = val & PCI_BASE_ADDRESS_MEM_MASK; board->boardType = board_type; switch (board_type) { case MOXA_BOARD_C218_ISA : case MOXA_BOARD_C218_PCI : board->numPorts = 8; break; case MOXA_BOARD_CP204J : board->numPorts = 4; break; default : board->numPorts = 0; break; } board->busType = MOXA_BUS_TYPE_PCI; board->pciInfo.busNum = busnum; board->pciInfo.devNum = devnum >> 3; return (0);}#endifstatic void do_moxa_softint(void *private_){ struct moxa_str *ch = (struct moxa_str *)private_; struct tty_struct *tty; if (ch && (tty = ch->tty)) {#if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0)) if ( clear_bit(MOXA_EVENT_HANGUP, &ch->event) ) {#else if ( test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event) ) {#endif tty_hangup(tty); /* FIXME: module removal race here - AKPM */ wake_up_interruptible(&ch->open_wait); ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE); } } MOD_DEC_USE_COUNT;} static int moxa_open(struct tty_struct *tty, struct file * filp){ struct moxa_str *ch; int port; int retval; unsigned long page; port = PORTNO(tty); if ( port == MAX_PORTS ) { MOD_INC_USE_COUNT; return(0); } if ( !MoxaPortIsValid(port) ) { tty->driver_data = NULL; return(-ENODEV); } down(&moxaBuffSem); if ( !moxaXmitBuff ) { page = get_free_page(GFP_KERNEL); if ( !page ) { up(&moxaBuffSem); return(-ENOMEM); } if ( moxaXmitBuff ) free_page(page); else moxaXmitBuff = (unsigned char *)page; } up(&moxaBuffSem); MOD_INC_USE_COUNT; ch = &moxaChannels[port]; ch->count++; tty->driver_data = ch; ch->tty = tty; if (ch->count == 1 && (ch->asyncflags & ASYNC_SPLIT_TERMIOS)) { if (tty->driver.subtype == SERIAL_TYPE_NORMAL) *tty->termios = ch->normal_termios; else *tty->termios = ch->callout_termios; } ch->session = current->session; ch->pgrp = current->pgrp; if (!(ch->asyncflags & ASYNC_INITIALIZED)) { ch->statusflags = 0; set_tty_param(tty); MoxaPortLineCtrl(ch->port, 1, 1); MoxaPortEnable(ch->port); ch->asyncflags |= ASYNC_INITIALIZED; } retval = block_till_ready(tty, filp, ch); moxa_unthrottle(tty); if (ch->type == PORT_16550A) { MoxaSetFifo(ch->port, 1); } else { MoxaSetFifo(ch->port, 0); } return (retval);}static void close_wait_until_sent(struct tty_struct *tty, signed long timeout){ long MoxaPortGetCurBaud(int port); int MoxaPortExtTxQueue(int port); int port; long baud; int tx_tout; long now; struct moxa_str *ch; port = PORTNO(tty); ch = (struct moxa_str*)tty->driver_data; now = 0; tx_tout = 0; now = jiffies; baud = MoxaPortGetCurBaud(port); if(!baud) baud = 9600; tx_tout = 16*HZ*10/baud; /* for 16 bytes FIFO */ tx_tout++; /* for safe */ do{ int len; current->state = TASK_INTERRUPTIBLE; len = MoxaPortExtTxQueue(port); if(len == 0){ break; } if (signal_pending(current)) break; if(timeout>0) if(jiffies-now > timeout) break; /* wait 16 bytes fifo time */ schedule_timeout(tx_tout); }while(1); current->state = TASK_RUNNING; if(tx_tout) schedule_timeout(tx_tout);} static void moxa_close(struct tty_struct *tty, struct file *filp){ struct moxa_str *ch; int port; port = PORTNO(tty); if (port == MAX_PORTS) { MOD_DEC_USE_COUNT; return; } if (!MoxaPortIsValid(port)) {#ifdef SERIAL_DEBUG_CLOSE printk("Invalid portno in moxa_close\n");#endif tty->driver_data = NULL; return; } if (tty->driver_data == NULL) { return; } if (tty_hung_up_p(filp)) { MOD_DEC_USE_COUNT; return; } ch = (struct moxa_str *) tty->driver_data; if ((tty->count == 1) && (ch->count != 1)) { printk("moxa_close: bad serial port count; tty->count is 1, " "ch->count is %d\n", ch->count); ch->count = 1; } if (--ch->count < 0) { printk("moxa_close: bad serial port count, minor=%d\n", MINOR(tty->device)); ch->count = 0; } if (ch->count) { MOD_DEC_USE_COUNT; return; } ch->asyncflags |= ASYNC_CLOSING; /* * Save the termios structure, since this port may have * separate termios for callout and dialin. */ if ( ch->asyncflags & ASYNC_NORMAL_ACTIVE ) ch->normal_termios = *tty->termios; if ( ch->asyncflags & ASYNC_CALLOUT_ACTIVE ) ch->callout_termios = *tty->termios;/* added by casper, 2/16/2000, for serial printer */ if ( ch->closing_wait != ASYNC_CLOSING_WAIT_NONE){ close_wait_until_sent(tty, ch->closing_wait); }/* */ if ( ch->asyncflags & ASYNC_INITIALIZED ) { setup_empty_event(tty);/* modified by casper, 2/16/2000, for serial printer */ close_wait_until_sent(tty, ch->closing_wait); //tty_wait_until_sent(tty, 30*HZ); /* 30 seconds timeout *//* */ moxaEmptyTimer_on[ch->port] = 0; del_timer(&moxaEmptyTimer[ch->port]); } shut_down(ch); MoxaPortFlushData(port, 2); if ( tty->driver.flush_buffer ) tty->driver.flush_buffer(tty); if ( tty->ldisc.flush_buffer ) tty->ldisc.flush_buffer(tty); tty->closing = 0; ch->event = 0; ch->tty = 0; /*********** delete by Linux 2.0.0 serial.c, why ???? ******* if ( tty->ldisc.num != ldiscs[N_TTY].num ) { if ( tty->ldisc.close ) (tty->ldisc.close)(tty); tty->ldisc = ldiscs[N_TTY]; tty->termios->c_line = N_TTY; if ( tty->ldisc.open ) (tty->ldisc.open)(tty); } ***************************************************************/ if ( ch->blocked_open ) { if ( ch->close_delay ) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(ch->close_delay); } wake_up_interruptible(&ch->open_wait); } ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&ch->close_wait); MOD_DEC_USE_COUNT;} #if (LINUX_VERSION_CODE > VERSION_CODE(2,1,0))static void mx_wait_until_sent(struct tty_struct *tty, int timeout){ long MoxaPortGetCurBaud(int port); int MoxaPortExtTxQueue(int port); int port; long baud; int tx_tout; long now; struct moxa_str *ch; port = PORTNO(tty); ch = (struct moxa_str*)tty->driver_data; now = 0; tx_tout = 0; now = jiffies; baud = MoxaPortGetCurBaud(port); if(!baud) baud = 9600; tx_tout = 16*HZ*10/baud; /* for 16 bytes FIFO */ tx_tout++; /* for safe */ do{ int len; current->state = TASK_INTERRUPTIBLE; len = MoxaPortExtTxQueue(port); if(len == 0){ break; } if (signal_pending(current)) break; if(timeout>0) if(jiffies-now > timeout) break; /* wait 16 bytes fifo time */ schedule_timeout(tx_tout); }while(1); current->state = TASK_RUNNING; if(tx_tout) schedule_timeout(tx_tout);} #endif static int moxa_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count){ struct moxa_str *ch; int len, port; unsigned long flags; unsigned char *temp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -