📄 8253xsyn.c
字号:
sab8253x_change_speedS(port); port->flags |= FLAG8253X_INITIALIZED; port->receive_chars = sab8253x_receive_charsS; port->transmit_chars = sab8253x_transmit_charsS; port->check_status = sab8253x_check_statusS; port->receive_test = (SAB82532_ISR0_RME | SAB82532_ISR0_RFO | SAB82532_ISR0_RPF); port->transmit_test = (SAB82532_ISR1_ALLS | SAB82532_ISR1_RDO | SAB82532_ISR1_XPR | SAB82532_ISR1_XDU | SAB82532_ISR1_CSC); port->check_status_test = (SAB82532_ISR1_CSC); /*((port->ccontrol.ccr2 & SAB82532_CCR2_TOE) ? 0 : SAB82532_ISR0_CDSC));*/ restore_flags(flags); return 0; errout: restore_flags(flags); return retval;}static void sab8253x_shutdownS(struct sab_port *port){ unsigned long flags; if (!(port->flags & FLAG8253X_INITIALIZED)) { return; } save_flags(flags); cli(); /* Disable interrupts */ /* * clear delta_msr_wait queue to avoid mem leaks: we may free the irq * here so the queue might never be waken up */ wake_up_interruptible(&port->delta_msr_wait); if (port->xmit_buf) { port->xmit_buf = 0; }#ifdef XCONFIG_SERIAL_CONSOLE if (port->is_console) { port->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR | /*SAB82532_IMR0_TIME |*/ SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC; WRITEB(port,imr0,port->interrupt_mask0); port->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS | SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN | SAB82532_IMR1_CSC | SAB82532_IMR1_XON | SAB82532_IMR1_XPR; WRITEB(port,imr1,port->interrupt_mask1); if (port->tty) { set_bit(TTY_IO_ERROR, &port->tty->flags); } port->flags &= ~FLAG8253X_INITIALIZED; restore_flags(flags); return; }#endif /* Disable Interrupts */ port->interrupt_mask0 = 0xff; WRITEB(port, imr0, port->interrupt_mask0); port->interrupt_mask1 = 0xff; WRITEB(port, imr1, port->interrupt_mask1); if (!port->tty || (port->tty->termios->c_cflag & HUPCL)) { LOWER(port,rts); LOWER(port,dtr); } /* Disable Receiver */ CLEAR_REG_BIT(port,mode,SAB82532_MODE_RAC); /* Power Down */ CLEAR_REG_BIT(port,ccr0,SAB82532_CCR0_PU); if (port->tty) { set_bit(TTY_IO_ERROR, &port->tty->flags); } port->flags &= ~FLAG8253X_INITIALIZED; restore_flags(flags);}int sab8253x_writeS(struct tty_struct * tty, int from_user, const unsigned char *buf, int count){ struct sab_port *port = (struct sab_port *)tty->driver_data; struct sk_buff *skb; int truelength = 0; int do_queue = 1; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_write")) { return 0; } if(count == 0) { return 0; } if(port->active2.transmit == NULL) { return 0; } if((port->active2.transmit->Count & OWNER) == OWN_SAB) { sab8253x_start_txS(port); /* no descriptor slot */ return 0; } #ifndef FREEININTERRUPT skb = port->active2.transmit->HostVaddr; /* current slot value */ if(port->buffergreedy == 0) /* are we avoiding buffer free's */ { /* no */ if((skb != NULL) || /* not OWN_SAB from above */ (port->active2.transmit->crcindex != 0)) { register RING_DESCRIPTOR *freeme; freeme = port->active2.transmit; do { if((freeme->crcindex == 0) && (freeme->HostVaddr == NULL)) { break; } if(freeme->HostVaddr) { skb_unlink((struct sk_buff*)freeme->HostVaddr); dev_kfree_skb_any((struct sk_buff*)freeme->HostVaddr); freeme->HostVaddr = NULL; } freeme->sendcrc = 0; freeme->crcindex = 0; freeme = (RING_DESCRIPTOR*) freeme->VNext; } while((freeme->Count & OWNER) != OWN_SAB); } skb = NULL; /* buffer was freed */ } if(skb != NULL) /* potentially useful */ { truelength = (skb->end - skb->head); if(truelength >= count) { skb->data = skb->head; /* this buffer is already queued */ skb->tail = skb->head; do_queue = 0; } else { skb_unlink(skb); dev_kfree_skb_any(skb); skb = NULL; port->active2.transmit->HostVaddr = NULL; } } /* in all cases the following is allowed */ port->active2.transmit->sendcrc = 0; port->active2.transmit->crcindex = 0;#endif if(skb == NULL) { if(port->DoingInterrupt) { skb = alloc_skb(count, GFP_ATOMIC); } else { skb = alloc_skb(count, GFP_KERNEL); } } if(skb == NULL) { printk(KERN_ALERT "sab8253xs: no skbuffs available.\n"); return 0; } if(from_user) { copy_from_user(skb->data, buf, count); } else { memcpy(skb->data, buf, count); } skb->tail = (skb->data + count); skb->data_len = count; skb->len = count; if(do_queue) { skb_queue_head(port->sab8253xbuflist, skb); } port->active2.transmit->HostVaddr = skb; port->active2.transmit->sendcrc = 0; port->active2.transmit->crcindex = 0; port->active2.transmit->Count = (OWN_SAB|count); port->active2.transmit = port->active2.transmit->VNext; sab8253x_start_txS(port); return count;}void sab8253x_throttleS(struct tty_struct * tty){ struct sab_port *port = (struct sab_port *)tty->driver_data; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_throttleS")) { return; } if (!tty) { return; } if (I_IXOFF(tty)) { sab8253x_send_xcharS(tty, STOP_CHAR(tty)); }}void sab8253x_unthrottleS(struct tty_struct * tty){ struct sab_port *port = (struct sab_port *)tty->driver_data; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_unthrottle")) { return; } if (!tty) { return; } if (I_IXOFF(tty)) { sab8253x_send_xcharS(tty, START_CHAR(tty)); }}void sab8253x_send_xcharS(struct tty_struct *tty, char ch){ struct sab_port *port = (struct sab_port *)tty->driver_data; unsigned long flags; int stopped; int hw_stopped; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_send_xcharS")) { return; } if (!tty) { return; } if(port->sabnext2.transmit == NULL) { return; } save_flags(flags); cli(); if((port->sabnext2.transmit->Count & OWNER) == OWN_SAB) /* may overwrite a character * -- but putting subsequent * XONs or XOFFs later in the * stream could cause problems * with the XON and XOFF protocol */ { port->sabnext2.transmit->sendcrc = 1; port->sabnext2.transmit->crcindex = 3; port->sabnext2.transmit->crc = (ch << 24); /* LITTLE ENDIAN */ restore_flags(flags); } else { restore_flags(flags); sab8253x_writeS(tty, 0, &ch, 1); } stopped = tty->stopped; hw_stopped = tty->hw_stopped; tty->stopped = 0; tty->hw_stopped = 0; sab8253x_start_txS(port); tty->stopped = stopped; tty->hw_stopped = hw_stopped;}void sab8253x_breakS(struct tty_struct *tty, int break_state){ struct sab_port *port = (struct sab_port *) tty->driver_data; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_breakS")) { return; } /* can't break in sync mode */}void sab8253x_closeS(struct tty_struct *tty, struct file * filp){ struct sab_port *port = (struct sab_port *)tty->driver_data; unsigned long flags; MOD_DEC_USE_COUNT; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_closeS")) { return; } if(port->open_type == OPEN_SYNC_NET) { /* port->tty field should already be NULL */ return; } save_flags(flags); cli(); --(port->count); if (tty_hung_up_p(filp)) { if(port->count == 0) /* I think the reason for the weirdness relates to freeing of structures in the tty driver */ { port->open_type = OPEN_NOT; } else if(port->count < 0) { printk(KERN_ALERT "XX20: port->count went negative.\n"); port->count = 0; port->open_type = OPEN_NOT; } restore_flags(flags); return; } #if 0 if ((tty->count == 1) && (port->count != 0)) { /* * Uh, oh. tty->count is 1, which means that the tty * structure will be freed. port->count should always * be one in these conditions. If it's greater than * one, we've got real problems, since it means the * serial port won't be shutdown. */ printk("sab8253x_close: bad serial port count; tty->count is 1," " port->count is %d\n", port->count); port->count = 0; }#endif if (port->count < 0) { printk(KERN_ALERT "sab8253x_close: bad serial port count for ttys%d: %d\n", port->line, port->count); port->count = 0; } if (port->count) { restore_flags(flags); return; } port->flags |= FLAG8253X_CLOSING; /* * Save the termios structure, since this port may have * separate termios for callout and dialin. */ if (port->flags & FLAG8253X_NORMAL_ACTIVE) { port->normal_termios = *tty->termios; } if (port->flags & FLAG8253X_CALLOUT_ACTIVE) { port->callout_termios = *tty->termios; } /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; if (port->closing_wait != SAB8253X_CLOSING_WAIT_NONE) { tty_wait_until_sent(tty, port->closing_wait); } /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and turn off * the receiver. */ #if 0 port->interrupt_mask0 |= SAB82532_IMR0_TCD; /* not needed for sync */#endif WRITEB(port,imr0,port->interrupt_mask0); CLEAR_REG_BIT(port, mode, SAB82532_MODE_RAC); /* turn off receiver */ if (port->flags & FLAG8253X_INITIALIZED) { /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially * important if there is a transmit FIFO! */ sab8253x_wait_until_sent(tty, port->timeout); } sab8253x_shutdownS(port); Sab8253xCleanUpTransceiveN(port); if (tty->driver.flush_buffer) { tty->driver.flush_buffer(tty); } if (tty->ldisc.flush_buffer) { tty->ldisc.flush_buffer(tty); } tty->closing = 0; port->event = 0; port->tty = 0; if (port->blocked_open) { if (port->close_delay) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(port->close_delay); } wake_up_interruptible(&port->open_wait); } port->flags &= ~(FLAG8253X_NORMAL_ACTIVE|FLAG8253X_CALLOUT_ACTIVE| FLAG8253X_CLOSING); wake_up_interruptible(&port->close_wait); port->open_type = OPEN_NOT; restore_flags(flags);}void sab8253x_hangupS(struct tty_struct *tty){ struct sab_port * port = (struct sab_port *)tty->driver_data; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_hangupS")) { return; } #ifdef XCONFIG_SERIAL_CONSOLE if (port->is_console) { return; }#endif sab8253x_flush_buffer(tty); if(port) { sab8253x_shutdownS(port); Sab8253xCleanUpTransceiveN(port); port->event = 0; port->flags &= ~(FLAG8253X_NORMAL_ACTIVE|FLAG8253X_CALLOUT_ACTIVE); port->tty = 0; wake_up_interruptible(&port->open_wait); }}int sab8253x_openS(struct tty_struct *tty, struct file * filp){ struct sab_port *port; int retval, line; int counter; unsigned long flags; MOD_INC_USE_COUNT; line = MINOR(tty->device) - tty->driver.minor_start; for(counter = 0, port = AuraPortRoot; (counter < line) && (port != NULL); ++counter) { port = port->next; } if (!port) { printk(KERN_ALERT "sab8253x_openS: can't find structure for line %d\n", line); return -ENODEV; } save_flags(flags); /* Need to protect port->tty element */ cli(); if(port->tty == 0) { port->tty = tty; tty->flip.tqueue.routine = sab8253x_flush_to_ldiscS; } tty->driver_data = port; if(port->function != FUNCTION_NR) { ++(port->count); restore_flags(flags); return -ENODEV; /* only allowed if there are no restrictions on the port */ } if(port->open_type == OPEN_SYNC_NET) { port->tty = NULL; /* Don't bother with open counting here but make sure the tty field is NULL*/ restore_flags(flags); return -EBUSY; } restore_flags(flags); if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_openS")) { ++(port->count); return -ENODEV; } #ifdef DEBUG_OPEN printk("sab8253x_open %s%d, count = %d\n", tty->driver.name, port->line, port->count);#endif /* * If the port is in the middle of closing, bail out now. */ if (tty_hung_up_p(filp) || (port->flags & FLAG8253X_CLOSING)) { if (port->flags & FLAG8253X_CLOSING) { interruptible_sleep_on(&port->close_wait); }#ifdef SERIAL_DO_RESTART ++(port->count); return ((port->flags & FLAG8253X_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);#else ++(port->count); return -EAGAIN;#endif } if(port->flags & FLAG8253X_NORMAL_ACTIVE) { if(port->open_type == OPEN_ASYNC) { ++(port->count); return -EBUSY; /* can't reopen in sync mode */ } } if(port->open_type > OPEN_SYNC) /* can reopen a SYNC_TTY */ { return -EBUSY; } if(Sab8253xSetUpLists(port)) { ++(port->count); return -ENODEV; } if(Sab8253xInitDescriptors2(port, sab8253xs_listsize, sab8253xs_rbufsize)) { ++(port->count); return -ENODEV; } retval = sab8253x_startupS(port); if (retval) { ++(port->count); return retval; /* does not check channel mode */ } retval = sab8253x_block_til_ready(tty, filp, port); /* checks channel mode */ ++(port->count); if (retval) { return retval; } port->tty = tty; /* may change here once through the block */ /* because now the port belongs to an new tty */ tty->flip.tqueue.routine = sab8253x_flush_to_ldiscS; if(Sab8253xSetUpLists(port)) { return -ENODEV; } if(Sab8253xInitDescriptors2(port, sab8253xs_listsize, sab8253xs_rbufsize)) { Sab8253xCleanUpTransceiveN(port); /* the network functions should be okay -- only difference */ /* is the crc32 that is appended */ return -ENODEV; } /* * Start up serial port */ retval = sab8253x_startupS(port); /* in case cu was running the first time * the function was called*/ if (retval) { return retval; /* does not check channel mode */ } if ((port->count == 1) && (port->flags & FLAG8253X_SPLIT_TERMIOS)) { if (tty->driver.subtype == SERIAL_TYPE_NORMAL) { *tty->termios = port->normal_termios; } else { *tty->termios = port->callout_termios; } sab8253x_change_speedS(port); } #ifdef XCONFIG_SERIAL_CONSOLE if (sab8253x_console.cflag && sab8253x_console.index == line) { tty->termios->c_cflag = sab8253x_console.cflag; sab8253x_console.cflag = 0; change_speed(port); }#endif port->session = current->session; port->pgrp = current->pgrp; port->open_type = OPEN_SYNC; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -