📄 8253xutl.c
字号:
xdesc < &priv->dcontrol2.transmit[listsize - 1]; xdesc = &xdesc[1]) /* set up transmit descriptors */ { xdesc->HostVaddr = NULL; xdesc->VNext = &xdesc[1]; xdesc->Count = 0 | OWN_DRIVER; xdesc->crc = 0; xdesc->sendcrc = 0; xdesc->crcindex = 0; } xdesc->HostVaddr = NULL; xdesc->VNext = priv->dcontrol2.transmit; /* circular list */ xdesc->Count = 0 | OWN_DRIVER; xdesc->crc = 0; xdesc->sendcrc = 0; xdesc->crcindex = 0; desc = priv->dcontrol2.receive; /* only need one descriptor for receive */ desc->HostVaddr = NULL; desc->VNext = &desc[0]; desc = priv->dcontrol2.receive; desc->HostVaddr = dev_alloc_skb(rbufsize); if(desc->HostVaddr == NULL) { printk(KERN_ALERT "Unable to allocate skb_buffers (rx 0).\n"); printk(KERN_ALERT "Driver initialization failed.\n"); kfree(priv->dcontrol2.transmit); kfree(priv->dcontrol2.receive); priv->dcontrol2.transmit = NULL; /* get rid of descriptor ring */ priv->dcontrol2.receive = NULL; /* get rid of descriptor */ /* probably should do some deallocation of sk_buffs*/ /* but will take place in the open */ return -1; } skb_queue_head(priv->sab8253xbuflist, (struct sk_buff*) desc->HostVaddr); desc->Count = rbufsize|OWN_SAB; /* belongs to int handler */ desc->crc = 0; desc->sendcrc = 0; desc->crcindex = 0; /* setup the various pointers */ priv->active2 = priv->dcontrol2; /* insert new skbuff */ priv->sabnext2 = priv->dcontrol2; /* transmit from here */ return 0;}/* loads program, waits for PPC *//* and completes initialization*/void Sab8253xCleanUpTransceiveN(SAB_PORT* priv){ Sab8253xFreeAllFreeListSKBUFFS(priv); Sab8253xFreeAllReceiveListSKBUFFS(priv); /* these are also cleaned up in the module cleanup routine */ /* should probably only be done here */ if(priv->dcontrol2.receive) { kfree(priv->dcontrol2.receive); priv->dcontrol2.receive = NULL; } if(priv->dcontrol2.transmit) { kfree(priv->dcontrol2.transmit); priv->dcontrol2.transmit = NULL; } priv->active2 = priv->dcontrol2; priv->sabnext2 = priv->dcontrol2; }void Sab8253xFreeAllReceiveListSKBUFFS(SAB_PORT* priv) /* empty the skbuffer list *//* either on failed open *//* or on close*/{ struct sk_buff* skb; if(priv->sab8253xc_rcvbuflist == NULL) { return; } DEBUGPRINT((KERN_ALERT "sab8253x: freeing %i skbuffs.\n", skb_queue_len(priv->sab8253xc_rcvbuflist))); while(skb_queue_len(priv->sab8253xc_rcvbuflist) > 0) { skb = skb_dequeue(priv->sab8253xc_rcvbuflist); dev_kfree_skb_any(skb); } kfree(priv->sab8253xc_rcvbuflist); priv->sab8253xc_rcvbuflist = NULL;}/* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */void sab8253x_change_speedN(struct sab_port *port){ unsigned long flags; unsigned char ccr2=0, ccr4=0, ebrg=0; int bits = 8; #ifdef DEBUGGING printk("Change speed! ");#endif if(!sab8253x_baud(port, (port->baud)*2, &ebrg, &ccr2, &ccr4, &(port->baud))) { printk("Aurora Warning. baudrate %ld could not be set! Using 115200", port->baud); port->baud = 115200; sab8253x_baud(port, (port->baud*2), &ebrg, &ccr2, &ccr4, &(port->baud)); } if (port->baud) { port->timeout = (port->xmit_fifo_size * HZ * bits) / port->baud; port->cec_timeout = port->tec_timeout >> 2; } else { port->timeout = 0; port->cec_timeout = SAB8253X_MAX_CEC_DELAY; } port->timeout += HZ / 50; /* Add .02 seconds of slop */ save_flags(flags); cli(); sab8253x_cec_wait(port); WRITEB(port, bgr, ebrg); WRITEB(port, ccr2, READB(port, ccr2) & ~(0xc0)); /* clear out current baud rage */ WRITEB(port, ccr2, READB(port, ccr2) | ccr2); WRITEB(port, ccr4, (READB(port,ccr4) & ~SAB82532_CCR4_EBRG) | ccr4); if (port->flags & FLAG8253X_CTS_FLOW) { WRITEB(port, mode, READB(port,mode) & ~(SAB82532_MODE_RTS)); port->interrupt_mask1 &= ~(SAB82532_IMR1_CSC); WRITEB(port, imr1, port->interrupt_mask1); } else { WRITEB(port, mode, READB(port,mode) | SAB82532_MODE_RTS); port->interrupt_mask1 |= SAB82532_IMR1_CSC; WRITEB(port, imr1, port->interrupt_mask1); } WRITEB(port, mode, READB(port, mode) | SAB82532_MODE_RAC); restore_flags(flags);}void sab8253x_shutdownN(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); /* Disable Interrupts */ port->interrupt_mask0 = 0xff; WRITEB(port, imr0, port->interrupt_mask0); port->interrupt_mask1 = 0xff; WRITEB(port, imr1, port->interrupt_mask1); 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); port->flags &= ~FLAG8253X_INITIALIZED; restore_flags(flags);}int sab8253x_block_til_ready(struct tty_struct *tty, struct file * filp, struct sab_port *port){ DECLARE_WAITQUEUE(wait, current); int retval; int do_clocal = 0; unsigned long flags; /* * If the device is in the middle of being closed, then block * until it's done, and then try again. */ if (tty_hung_up_p(filp) || (port->flags & FLAG8253X_CLOSING)) { if (port->flags & FLAG8253X_CLOSING) { interruptible_sleep_on(&port->close_wait); /* finish up previous close */ }#ifdef SERIAL_DO_RESTART if (port->flags & FLAG8253X_HUP_NOTIFY) { return -EAGAIN; } else { return -ERESTARTSYS; }#else return -EAGAIN;#endif } /* * If this is a callout device, then just make sure the normal * device isn't being used. */ if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { if (port->flags & FLAG8253X_NORMAL_ACTIVE) { return -EBUSY; /* async, sync tty or network driver active */ } if ((port->flags & FLAG8253X_CALLOUT_ACTIVE) && (port->flags & FLAG8253X_SESSION_LOCKOUT) && (port->session != current->session)) { return -EBUSY; } if ((port->flags & FLAG8253X_CALLOUT_ACTIVE) && (port->flags & FLAG8253X_PGRP_LOCKOUT) && (port->pgrp != current->pgrp)) { return -EBUSY; } port->flags |= FLAG8253X_CALLOUT_ACTIVE; /* doing a callout */ return 0; } /* sort out async vs sync tty, not call out */ /* * If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { if (port->flags & FLAG8253X_CALLOUT_ACTIVE) { return -EBUSY; } port->flags |= FLAG8253X_NORMAL_ACTIVE; return 0; } if (port->flags & FLAG8253X_CALLOUT_ACTIVE) { if (port->normal_termios.c_cflag & CLOCAL) { do_clocal = 1; } } else if (tty->termios->c_cflag & CLOCAL) { do_clocal = 1; } /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in * this loop, port->count is dropped by one, so that * sab8253x_close() knows when to free things. We restore it upon * exit, either normal or abnormal. */ /* The port decrement logic is probably */ /* broken -- hence if def'd out -- it does*/ retval = 0; add_wait_queue(&port->open_wait, &wait); /* starts the wait but does not block here */ port->blocked_open++; while (1) { save_flags(flags); cli(); if (!(port->flags & FLAG8253X_CALLOUT_ACTIVE) && (tty->termios->c_cflag & CBAUD)) { RAISE(port, dtr); RAISE(port, rts); /* maybe not correct for sync */ /* * ??? Why changing the mode here? * port->regs->rw.mode |= SAB82532_MODE_FRTS; * port->regs->rw.mode &= ~(SAB82532_MODE_RTS); */ } restore_flags(flags); current->state = TASK_INTERRUPTIBLE; if (tty_hung_up_p(filp) || !(port->flags & FLAG8253X_INITIALIZED)) {#ifdef SERIAL_DO_RESTART if (port->flags & FLAG8253X_HUP_NOTIFY) { retval = -EAGAIN; } else { retval = -ERESTARTSYS; }#else retval = -EAGAIN;#endif break; } if (!(port->flags & FLAG8253X_CALLOUT_ACTIVE) && !(port->flags & FLAG8253X_CLOSING) && (do_clocal || ISON(port,dcd))) { break; }#ifdef DEBUG_OPEN printk("sab8253x_block_til_ready:2 flags = 0x%x\n",port->flags);#endif if (signal_pending(current)) { retval = -ERESTARTSYS; break; }#ifdef DEBUG_OPEN printk("sab8253x_block_til_ready blocking: ttyS%d, count = %d, flags = %x, clocal = %d, vstr = %02x\n", port->line, port->count, port->flags, do_clocal, READB(port,vstr));#endif schedule(); } current->state = TASK_RUNNING; remove_wait_queue(&port->open_wait, &wait); port->blocked_open--;#ifdef DEBUG_OPEN printk("sab8253x_block_til_ready after blocking: ttys%d, count = %d\n", port->line, port->count);#endif if (retval) { return retval; } port->flags |= FLAG8253X_NORMAL_ACTIVE; return 0;}/* * sab8253x_wait_until_sent() --- wait until the transmitter is empty */void sab8253x_wait_until_sent(struct tty_struct *tty, int timeout){ struct sab_port *port = (struct sab_port *)tty->driver_data; unsigned long orig_jiffies, char_time; if (sab8253x_serial_paranoia_check(port,tty->device,"sab8253x_wait_until_sent")) { return; } orig_jiffies = jiffies; /* * Set the check interval to be 1/5 of the estimated time to * send a single character, and make it at least 1. The check * interval should also be less than the timeout. * * Note: we have to use pretty tight timings here to satisfy * the NIST-PCTS. */ char_time = (port->timeout - HZ/50) / port->xmit_fifo_size; char_time = char_time / 5; if (char_time == 0) { char_time = 1; } if (timeout) { char_time = MIN(char_time, timeout); } while ((Sab8253xCountTransmit(port) > 0) || !port->all_sent) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(char_time); if (signal_pending(current)) { break; } if (timeout && time_after(jiffies, orig_jiffies + timeout)) { break; } }}void sab8253x_flush_buffer(struct tty_struct *tty){ struct sab_port *port = (struct sab_port *)tty->driver_data; unsigned long flags; register RING_DESCRIPTOR *freeme; if(sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_flush_buffer")) { return; } if(port->sabnext2.transmit == NULL) { return; } save_flags(flags); cli(); /* need to turn off ints because mucking with sabnext2 */#ifndef FREEININTERRUPT freeme = port->active2.transmit; do /* just go all around */ { 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->Count = OWN_DRIVER; freeme = (RING_DESCRIPTOR*) freeme->VNext; } while(freeme != port->active2.transmit);#else /* buffers only from sabnext2.transmit to active2.transmit */ while((port->sabnext2.transmit->Count & OWNER) == OWN_SAB) /* clear out stuff waiting to be transmitted */ { freeme = port->sabnext2.transmit; 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->Count = OWN_DRIVER; port->sabnext2.transmit = freeme->VNext; }#endif port->sabnext2.transmit = port->active2.transmit; /* should already be equal to be sure */ sab8253x_cec_wait(port); WRITEB(port,cmdr,SAB82532_CMDR_XRES); restore_flags(flags); wake_up_interruptible(&tty->write_wait); /* wake up tty driver */ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { (*tty->ldisc.write_wakeup)(tty); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -