📄 8253xutl.c
字号:
if (quot <= 0x400) { /* quot = [1, 0x400] -> (quot << 5) != 0 */ *truebaudp = ROUND_DIV(clk_speed, ((unsigned long) quot << 5)); quot--; ccr2tmp = SAB82532_CCR2_BDF; if ((quot & 0x200) != 0) { ccr2tmp |= SAB82532_CCR2_BR9; } if ((quot & 0x100) != 0) { ccr2tmp |=SAB82532_CCR2_BR8; } *ccr2 = ccr2tmp | (*ccr2 & ~(SAB82532_CCR2_BDF|SAB82532_CCR2_BR8|SAB82532_CCR2_BR9)); *bgr = (unsigned char) quot; } else { /* the baud rate is too small. */ return FALSE; } return TRUE;}/*************************************************************************** * sab_baud: Function to compute the best register value to achieve * a given baudrate. * * * Parameters : * port: The port being used (in only) * encbaud: 2* the baudrate. We use the * double value so as to support 134.5 (in only) * bgr Value of reg BGR for baudrate(output) * ccr2 Value of reg CCR2 for baudrate (output) * ccr4 Value of reg CCR4 for baudrate (output) * truebaud The actual baudrate achieved (output). * * * Return value : Return TRUE if the vaudrate can be set, FALSE otherwise * * Prerequisite : The various ports must have been initialized * * Remark : Stolen from the Aurora ase driver. * * Author : fw * * Revision : Oct 9 2000, creation ***************************************************************************/unsigned int sab8253x_baud(sab_port_t *port, unsigned long encbaud, unsigned char *bgr, unsigned char *ccr2, unsigned char *ccr4, unsigned long *truebaudp){ unsigned char bgr_std, bgr_enh, ccr2_std, ccr2_enh, ccr4_enh; unsigned int ok_std, ok_enh; unsigned long truebaud_std, truebaud_enh, truebaud,clkspeed; bgr_std = bgr_enh = 0; ccr2_std = ccr2_enh = 0; ccr4_enh = 0; /* * the port/chip/board structure will tell us: * 1) clock speed * 2) chip revision (to figure out if the enhanced method is * available. */ clkspeed = port->chip->c_cim ? port->chip->c_cim->ci_clkspeed : port->board->b_clkspeed; #ifdef NODEBUGGING printk("With clk speed %ld, baud rate = %ld\n",clkspeed, encbaud);#endif ok_std = sab8253x_baudstd(encbaud, clkspeed, &bgr_std, &ccr2_std, &truebaud_std);#ifdef NODEBUGGING printk("Std gives bgr = 0x%x, ccr2=0x%x for speed %ld\n",bgr_std,ccr2_std,truebaud_std);#endif if(port->chip->c_revision >= SAB82532_VSTR_VN_3_2) { ok_enh = sab8253x_baudenh(encbaud, clkspeed, &bgr_enh, &ccr2_enh, &truebaud_enh);#ifdef NODEBUGGING printk("Enh gives bgr = 0x%x, ccr2=0x%x for speed %ld\n",bgr_enh,ccr2_enh,truebaud_enh);#endif } else ok_enh = FALSE; /* * Did both methods return values? */ if (ok_std && ok_enh) { /* * Find the closest of the two. */ if (ABSDIF((truebaud_enh<<1), encbaud) < ABSDIF((truebaud_std<<1), encbaud)) { ok_std = FALSE; } else { ok_enh = FALSE; } } /* * Now return the values. */ if (ok_std || ok_enh) { truebaud = ok_std ? truebaud_std : truebaud_enh; /* * If the true baud rate is off by more than 5%, then * we don't support it. */ if (ROUND_DIV(ABSDIF((truebaud<<1), encbaud), encbaud) != 0) { /* * We're not even in the right ballpark. This * test is here to deal with overflow conditions. */ return FALSE; } else if (ROUND_DIV(ABSDIF((truebaud<<1), encbaud) * 100, encbaud) >= 5) { return FALSE; } *truebaudp = truebaud; if (ok_enh) { *ccr4 |= SAB82532_CCR4_EBRG; *ccr2 = ccr2_enh; *bgr = bgr_enh;#ifdef DEBUGGING printk("Enhanced Baud at %ld, ccr4 = 0x%x, ccr2 = 9x%x, bgr = 0x%x\n", truebaud,*ccr4,*ccr2,*bgr);#endif } else { *ccr4 &= ~SAB82532_CCR4_EBRG; *ccr2 = ccr2_std; *bgr = bgr_std;#ifdef DEBUGGING printk("Standard Baud at %ld, ccr4 = 0x%x, ccr2 = 9x%x, bgr = 0x%x\n", truebaud,*ccr4,*ccr2,*bgr);#endif } return TRUE; } else { return FALSE; }}int Sab8253xCountTransmit(SAB_PORT *port){ register RING_DESCRIPTOR *rd; register int total; register int count; unsigned long flags; RING_DESCRIPTOR *start; if(port->sabnext2.transmit == NULL) { return 0; } save_flags(flags); cli(); rd = port->sabnext2.transmit; start = rd; total = 0; while(1) { count = rd->Count; if((count & OWNER) == OWN_DRIVER) { break; } total += (count & ~OWNER); if(rd->sendcrc) { total += (4 - rd->crcindex); } rd = rd->VNext; if(rd == start) { break; } } restore_flags(flags); return total;}int Sab8253xCountTransmitDescriptors(SAB_PORT *port){ register RING_DESCRIPTOR *rd; register int total; register int count; unsigned long flags; RING_DESCRIPTOR *start; if(port->sabnext2.transmit == NULL) { return 0; } save_flags(flags); cli(); rd = port->sabnext2.transmit; start = rd; total = 0; while(1) { count = rd->Count; if((count & OWNER) == OWN_DRIVER) { break; } ++total; rd = rd->VNext; if(rd == start) { break; } } restore_flags(flags); return total;}int getccr0configS(struct sab_port *port){ return port->ccontrol.ccr0;}int getccr1configS(struct sab_port *port){ return port->ccontrol.ccr1;}int getccr2configS(struct sab_port *port){ return port->ccontrol.ccr2;}int getccr3configS(struct sab_port *port){ return port->ccontrol.ccr3;}int getccr4configS(struct sab_port *port){ return port->ccontrol.ccr4;}int getrlcrconfigS(struct sab_port *port){ return port->ccontrol.rlcr;}int getmodeS(struct sab_port *port){ return port->ccontrol.mode;}void sab8253x_init_lineS(struct sab_port *port){ unsigned char stat; if(port->chip->c_cim) { if(port->chip->c_cim->ci_type == CIM_SP502) { aura_sp502_program(port, SP502_OFF_MODE); } } /* * Wait for any commands or immediate characters */ sab8253x_cec_wait(port);#if 0 sab8253x_tec_wait(port); /* I have to think about this one * should I assume the line was * previously in async mode*/#endif /* * Clear the FIFO buffers. */ WRITEB(port, cmdr, SAB82532_CMDR_RHR); sab8253x_cec_wait(port); WRITEB(port,cmdr,SAB82532_CMDR_XRES); /* * Clear the interrupt registers. */ stat = READB(port, isr0); /* acks ints */ stat = READB(port, isr1); /* * Now, initialize the UART */ WRITEB(port, ccr0, 0); /* power-down */ WRITEB(port, ccr0, getccr0configS(port)); WRITEB(port, ccr1, getccr1configS(port)); WRITEB(port, ccr2, getccr2configS(port)); WRITEB(port, ccr3, getccr3configS(port)); WRITEB(port, ccr4, getccr4configS(port)); /* 32 byte receive fifo */ WRITEB(port, mode, getmodeS(port)); WRITEB(port, tic /* really rlcr */, getrlcrconfigS(port)); /* power-up */ switch(port->ccontrol.ccr4 & SAB82532_CCR4_RF02) { case SAB82532_CCR4_RF32: port->recv_fifo_size = 32; break; case SAB82532_CCR4_RF16: port->recv_fifo_size = 16; break; case SAB82532_CCR4_RF04: port->recv_fifo_size = 4; break; case SAB82532_CCR4_RF02: port->recv_fifo_size = 2; break; default: port->recv_fifo_size = 32; port->ccontrol.ccr4 &= ~SAB82532_CCR4_RF02; break; } if(port->ccontrol.ccr2 & SAB82532_CCR2_TOE) { RAISE(port, txclkdir); } else { LOWER(port, txclkdir); } SET_REG_BIT(port,ccr0,SAB82532_CCR0_PU); if(port->chip->c_cim) { if(port->chip->c_cim->ci_type == CIM_SP502) { aura_sp502_program(port, port->sigmode); } }}/* frees up all skbuffs currently *//* held by driver */void Sab8253xFreeAllFreeListSKBUFFS(SAB_PORT* priv) /* empty the skbuffer list *//* either on failed open *//* or on close*/{ struct sk_buff* skb; if(priv->sab8253xbuflist == NULL) { return; } DEBUGPRINT((KERN_ALERT "sab8253x: freeing %i skbuffs.\n", skb_queue_len(priv->sab8253xbuflist))); while(skb_queue_len(priv->sab8253xbuflist) > 0) { skb = skb_dequeue(priv->sab8253xbuflist); dev_kfree_skb_any(skb); } kfree(priv->sab8253xbuflist); priv->sab8253xbuflist = NULL;}int Sab8253xSetUpLists(SAB_PORT *priv){ if(priv->sab8253xbuflist) { if(priv->sab8253xc_rcvbuflist) { return 0; } else { return -1; } return 0; } else if(priv->sab8253xc_rcvbuflist) { return -1; } priv->sab8253xbuflist = (struct sk_buff_head*) kmalloc(sizeof(struct sk_buff_head), GFP_KERNEL); if(priv->sab8253xbuflist == NULL) { return -1; } priv->sab8253xc_rcvbuflist = (struct sk_buff_head*) kmalloc(sizeof(struct sk_buff_head), GFP_KERNEL); if(priv->sab8253xc_rcvbuflist == NULL) { kfree(priv->sab8253xbuflist); return -1; } skb_queue_head_init(priv->sab8253xbuflist); skb_queue_head_init(priv->sab8253xc_rcvbuflist); return 0;}/* sets up transmit ring and one receive sk_buff *//* set up transmit and receive sk_buff control structures */int Sab8253xInitDescriptors2(SAB_PORT *priv, int listsize, int rbufsize){ RING_DESCRIPTOR *desc; RING_DESCRIPTOR *xdesc; if(priv->dcontrol2.transmit != NULL) { if(priv->dcontrol2.receive != NULL) { return 0; } return -1; } else if(priv->dcontrol2.receive != NULL) { return -1; } priv->dcontrol2.transmit = (RING_DESCRIPTOR*) kmalloc(sizeof(RING_DESCRIPTOR) * listsize, GFP_KERNEL); /* dcontrol2 is an historical artifact from when the code talked to an intelligent controller */ if(priv->dcontrol2.transmit == NULL) { return -1; } priv->dcontrol2.receive = (RING_DESCRIPTOR*) kmalloc(sizeof(RING_DESCRIPTOR), GFP_KERNEL); /* only one receive sk_buffer */ if(priv->dcontrol2.receive == NULL) { kfree(priv->dcontrol2.transmit); priv->dcontrol2.transmit = NULL; return -1; } for(xdesc = priv->dcontrol2.transmit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -