?? synclink.c
字號(hào):
if ( UscVector ) (*UscIsrTable[UscVector])(info); else if ( (DmaVector&(BIT10|BIT9)) == BIT10) mgsl_isr_transmit_dma(info); else mgsl_isr_receive_dma(info); if ( info->isr_overflow ) { printk(KERN_ERR"%s(%d):%s isr overflow irq=%d\n", __FILE__,__LINE__,info->device_name, irq); usc_DisableMasterIrqBit(info); usc_DisableDmaInterrupts(info,DICR_MASTER); break; } } /* Request bottom half processing if there's something * for it to do and the bh is not already running */ if ( info->pending_bh && !info->bh_running && !info->bh_requested ) { if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):%s queueing bh task.\n", __FILE__,__LINE__,info->device_name); queue_task(&info->task, &tq_immediate); mark_bh(IMMEDIATE_BH); info->bh_requested = 1; } spin_unlock(&info->irq_spinlock); if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):mgsl_interrupt(%d)exit.\n", __FILE__,__LINE__,irq);} /* end of mgsl_interrupt() *//* startup() * * Initialize and start device. * * Arguments: info pointer to device instance data * Return Value: 0 if success, otherwise error code */static int startup(struct mgsl_struct * info){ int retval = 0; if ( debug_level >= DEBUG_LEVEL_INFO ) printk("%s(%d):mgsl_startup(%s)\n",__FILE__,__LINE__,info->device_name); if (info->flags & ASYNC_INITIALIZED) return 0; if (!info->xmit_buf) { /* allocate a page of memory for a transmit buffer */ info->xmit_buf = (unsigned char *)get_free_page(GFP_KERNEL); if (!info->xmit_buf) { printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n", __FILE__,__LINE__,info->device_name); return -ENOMEM; } } info->pending_bh = 0; init_timer(&info->tx_timer); info->tx_timer.data = (unsigned long)info; info->tx_timer.function = mgsl_tx_timeout; /* Allocate and claim adapter resources */ retval = mgsl_claim_resources(info); /* perform existance check and diagnostics */ if ( !retval ) retval = mgsl_adapter_test(info); if ( retval ) { if (capable(CAP_SYS_ADMIN) && info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); mgsl_release_resources(info); return retval; } /* program hardware for current parameters */ mgsl_change_params(info); if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); info->flags |= ASYNC_INITIALIZED; return 0; } /* end of startup() *//* shutdown() * * Called by mgsl_close() and mgsl_hangup() to shutdown hardware * * Arguments: info pointer to device instance data * Return Value: None */static void shutdown(struct mgsl_struct * info){ unsigned long flags; if (!(info->flags & ASYNC_INITIALIZED)) return; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgsl_shutdown(%s)\n", __FILE__,__LINE__, info->device_name ); /* clear status wait queue because status changes */ /* can't happen after shutting down the hardware */ wake_up_interruptible(&info->status_event_wait_q); wake_up_interruptible(&info->event_wait_q); del_timer(&info->tx_timer); if (info->xmit_buf) { free_page((unsigned long) info->xmit_buf); info->xmit_buf = 0; } spin_lock_irqsave(&info->irq_spinlock,flags); usc_DisableMasterIrqBit(info); usc_stop_receiver(info); usc_stop_transmitter(info); usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS + TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC ); usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE); /* Disable DMAEN (Port 7, Bit 14) */ /* This disconnects the DMA request signal from the ISA bus */ /* on the ISA adapter. This has no effect for the PCI adapter */ usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14)); /* Disable INTEN (Port 6, Bit12) */ /* This disconnects the IRQ request signal to the ISA bus */ /* on the ISA adapter. This has no effect for the PCI adapter */ usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) | BIT12)); if (!info->tty || info->tty->termios->c_cflag & HUPCL) { info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); usc_set_serial_signals(info); } spin_unlock_irqrestore(&info->irq_spinlock,flags); mgsl_release_resources(info); if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); info->flags &= ~ASYNC_INITIALIZED; } /* end of shutdown() */static void mgsl_program_hw(struct mgsl_struct *info){ unsigned long flags; spin_lock_irqsave(&info->irq_spinlock,flags); usc_stop_receiver(info); usc_stop_transmitter(info); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; if (info->params.mode == MGSL_MODE_HDLC || info->params.mode == MGSL_MODE_RAW || info->netcount) usc_set_sync_mode(info); else usc_set_async_mode(info); usc_set_serial_signals(info); info->dcd_chkcount = 0; info->cts_chkcount = 0; info->ri_chkcount = 0; info->dsr_chkcount = 0; usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI); usc_EnableInterrupts(info, IO_PIN); usc_get_serial_signals(info); if (info->netcount || info->tty->termios->c_cflag & CREAD) usc_start_receiver(info); spin_unlock_irqrestore(&info->irq_spinlock,flags);}/* Reconfigure adapter based on new parameters */static void mgsl_change_params(struct mgsl_struct *info){ unsigned cflag; int bits_per_char; if (!info->tty || !info->tty->termios) return; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgsl_change_params(%s)\n", __FILE__,__LINE__, info->device_name ); cflag = info->tty->termios->c_cflag; /* if B0 rate (hangup) specified then negate DTR and RTS */ /* otherwise assert DTR and RTS */ if (cflag & CBAUD) info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; else info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); /* byte size and parity */ switch (cflag & CSIZE) { case CS5: info->params.data_bits = 5; break; case CS6: info->params.data_bits = 6; break; case CS7: info->params.data_bits = 7; break; case CS8: info->params.data_bits = 8; break; /* Never happens, but GCC is too dumb to figure it out */ default: info->params.data_bits = 7; break; } if (cflag & CSTOPB) info->params.stop_bits = 2; else info->params.stop_bits = 1; info->params.parity = ASYNC_PARITY_NONE; if (cflag & PARENB) { if (cflag & PARODD) info->params.parity = ASYNC_PARITY_ODD; else info->params.parity = ASYNC_PARITY_EVEN;#ifdef CMSPAR if (cflag & CMSPAR) info->params.parity = ASYNC_PARITY_SPACE;#endif } /* calculate number of jiffies to transmit a full * FIFO (32 bytes) at specified data rate */ bits_per_char = info->params.data_bits + info->params.stop_bits + 1; /* if port data rate is set to 460800 or less then * allow tty settings to override, otherwise keep the * current data rate. */ if (info->params.data_rate <= 460800) info->params.data_rate = tty_get_baud_rate(info->tty); if ( info->params.data_rate ) { info->timeout = (32*HZ*bits_per_char) / info->params.data_rate; } info->timeout += HZ/50; /* Add .02 seconds of slop */ if (cflag & CRTSCTS) info->flags |= ASYNC_CTS_FLOW; else info->flags &= ~ASYNC_CTS_FLOW; if (cflag & CLOCAL) info->flags &= ~ASYNC_CHECK_CD; else info->flags |= ASYNC_CHECK_CD; /* process tty input control flags */ info->read_status_mask = RXSTATUS_OVERRUN; if (I_INPCK(info->tty)) info->read_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR; if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) info->read_status_mask |= RXSTATUS_BREAK_RECEIVED; if (I_IGNPAR(info->tty)) info->ignore_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR; if (I_IGNBRK(info->tty)) { info->ignore_status_mask |= RXSTATUS_BREAK_RECEIVED; /* If ignoring parity and break indicators, ignore * overruns too. (For real raw support). */ if (I_IGNPAR(info->tty)) info->ignore_status_mask |= RXSTATUS_OVERRUN; } mgsl_program_hw(info);} /* end of mgsl_change_params() *//* mgsl_put_char() * * Add a character to the transmit buffer. * * Arguments: tty pointer to tty information structure * ch character to add to transmit buffer * * Return Value: None */static void mgsl_put_char(struct tty_struct *tty, unsigned char ch){ struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; unsigned long flags; if ( debug_level >= DEBUG_LEVEL_INFO ) { printk( "%s(%d):mgsl_put_char(%d) on %s\n", __FILE__,__LINE__,ch,info->device_name); } if (mgsl_paranoia_check(info, tty->device, "mgsl_put_char")) return; if (!tty || !info->xmit_buf) return; spin_lock_irqsave(&info->irq_spinlock,flags); if ( (info->params.mode == MGSL_MODE_ASYNC ) || !info->tx_active ) { if (info->xmit_cnt < SERIAL_XMIT_SIZE - 1) { info->xmit_buf[info->xmit_head++] = ch; info->xmit_head &= SERIAL_XMIT_SIZE-1; info->xmit_cnt++; } } spin_unlock_irqrestore(&info->irq_spinlock,flags); } /* end of mgsl_put_char() *//* mgsl_flush_chars() * * Enable transmitter so remaining characters in the * transmit buffer are sent. * * Arguments: tty pointer to tty information structure * Return Value: None */static void mgsl_flush_chars(struct tty_struct *tty){ struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; unsigned long flags; if ( debug_level >= DEBUG_LEVEL_INFO ) printk( "%s(%d):mgsl_flush_chars() entry on %s xmit_cnt=%d\n", __FILE__,__LINE__,info->device_name,info->xmit_cnt); if (mgsl_paranoia_check(info, tty->device, "mgsl_flush_chars")) return; if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf) return; if ( debug_level >= DEBUG_LEVEL_INFO ) printk( "%s(%d):mgsl_flush_chars() entry on %s starting transmitter\n", __FILE__,__LINE__,info->device_name ); spin_lock_irqsave(&info->irq_spinlock,flags); if (!info->tx_active) { if ( (info->params.mode == MGSL_MODE_HDLC || info->params.mode == MGSL_MODE_RAW) && info->xmit_cnt ) { /* operating in synchronous (frame oriented) mode */ /* copy data from circular xmit_buf to */ /* transmit DMA buffer. */ mgsl_load_tx_dma_buffer(info, info->xmit_buf,info->xmit_cnt); } usc_start_transmitter(info); } spin_unlock_irqrestore(&info->irq_spinlock,flags); } /* end of mgsl_flush_chars() *//* mgsl_write() * * Send a block of data * * Arguments: * * tty pointer to tty information structure * from_user flag: 1 = from user process * buf pointer to buffer containing send data * count size of send data in bytes * * Return Value: number of characters written */static int mgsl_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count){ int c, ret = 0, err; struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; unsigned long flags; if ( debug_level >= DEBUG_LEVEL_INFO ) printk( "%s(%d):mgsl_write(%s) count=%d\n", __FILE__,__LINE__,info->device_name,count); if (mgsl_paranoia_check(info, tty->device, "mgsl_write")) goto cleanup; if (!tty || !info->xmit_buf || !tmp_buf) goto cleanup; if ( info->params.mode == MGSL_MODE_HDLC || info->params.mode == MGSL_MODE_RAW ) { /* operating in synchronous (frame oriented) mode */ /* operating in synchronous (frame oriented) mode */ if (info->tx_active) { if ( info->params.mode == MGSL_MODE_HDLC ) { ret = 0; goto cleanup; } /* transmitter is actively sending data - * if we have multiple transmit dma and * holding buffers, attempt to queue this * frame for transmission at a later time. */ if (info->tx_holding_count >= info->num_tx_holding_buffers ) { /* no tx holding buffers available */ ret = 0
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -