⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cyclades.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
                         */                        outch = info->xmit_buf[info->xmit_tail];                        if( outch ){                            info->xmit_cnt--;                            info->xmit_tail = (info->xmit_tail + 1)                                                      & (SERIAL_XMIT_SIZE - 1);                            cy_writeb((u_long)base_addr+(CyTDR<<index), outch);                        }else{                            if(char_count > 1){                                info->xmit_cnt--;                                info->xmit_tail = (info->xmit_tail + 1)						      & (SERIAL_XMIT_SIZE - 1);                                cy_writeb((u_long)base_addr+(CyTDR<<index), 					  outch);                                cy_writeb((u_long)base_addr+(CyTDR<<index), 0);                                char_count--;                            }else{                            }                        }                    }        txdone:                    if (info->xmit_cnt < WAKEUP_CHARS) {                        cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);                    }        txend:                    /* end of service */                    cy_writeb((u_long)base_addr+(CyTIR<<index), 			      (save_xir & 0x3f));                    cy_writeb((u_long)base_addr+(CyCAR<<index), (save_car));                }                if (status & CySRModem) {        /* modem interrupt */                    /* determine the channel & change to that context */                    save_xir = (u_char) cy_readb(base_addr+(CyMIR<<index));                    channel = (u_short ) (save_xir & CyIRChannel);                    info = &cy_port[channel + chip * 4		                           + cinfo->first_line];                    info->last_active = jiffies;                    save_car = cy_readb(base_addr+(CyCAR<<index));                    cy_writeb((u_long)base_addr+(CyCAR<<index), save_xir);                    mdm_change = cy_readb(base_addr+(CyMISR<<index));                    mdm_status = cy_readb(base_addr+(CyMSVR1<<index));                    if(info->tty == 0){/* no place for data, ignore it*/                        ;                    }else{                        if((mdm_change & CyDCD)                        && (info->flags & ASYNC_CHECK_CD)){                            if(mdm_status & CyDCD){                                cy_sched_event(info,				    Cy_EVENT_OPEN_WAKEUP);                            }else if(!((info->flags			                & ASYNC_CALLOUT_ACTIVE)				 &&(info->flags				    & ASYNC_CALLOUT_NOHUP))){                                cy_sched_event(info,				    Cy_EVENT_HANGUP);                            }                        }                        if((mdm_change & CyCTS)                        && (info->flags & ASYNC_CTS_FLOW)){                            if(info->tty->hw_stopped){                                if(mdm_status & CyCTS){                                    /* cy_start isn't used				         because... !!! */                                    info->tty->hw_stopped = 0;                                  cy_writeb((u_long)base_addr+(CySRER<<index),                                       cy_readb(base_addr+(CySRER<<index)) |                                        CyTxMpty);                                    cy_sched_event(info,				        Cy_EVENT_WRITE_WAKEUP);                                }                            }else{                                if(!(mdm_status & CyCTS)){                                    /* cy_stop isn't used				         because ... !!! */                                    info->tty->hw_stopped = 1;                                  cy_writeb((u_long)base_addr+(CySRER<<index),                                       cy_readb(base_addr+(CySRER<<index)) &                                        ~CyTxMpty);                                }                            }                        }                        if(mdm_status & CyDSR){                        }                        if(mdm_status & CyRI){                        }                    }                    /* end of service */                    cy_writeb((u_long)base_addr+(CyMIR<<index), 			      (save_xir & 0x3f));                    cy_writeb((u_long)base_addr+(CyCAR<<index), save_car);                }            }          /* end while status != 0 */        }            /* end loop for chips... */    } while(had_work);   /* clear interrupts */   cy_writeb((u_long)card_base_addr + (Cy_ClrIntr<<index), 0);                                /* Cy_ClrIntr is 0x1800 */} /* cyy_interrupt *//***********************************************************//********* End of block of Cyclom-Y specific code **********//******** Start of block of Cyclades-Z specific code *********//***********************************************************/static intcyz_fetch_msg( struct cyclades_card *cinfo,	    uclong *channel, ucchar *cmd, uclong *param){  struct FIRM_ID *firm_id;  struct ZFW_CTRL *zfw_ctrl;  struct BOARD_CTRL *board_ctrl;  unsigned long loc_doorbell;    firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);    if (!ISZLOADED(*cinfo)){	return (-1);    }    zfw_ctrl = (struct ZFW_CTRL *)	       (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));    board_ctrl = &zfw_ctrl->board_ctrl;    loc_doorbell = cy_readl(&((struct RUNTIME_9060 *)                     (cinfo->ctl_addr))->loc_doorbell);    if (loc_doorbell){	*cmd = (char)(0xff & loc_doorbell);	*channel = cy_readl(&board_ctrl->fwcmd_channel);	*param = (uclong)cy_readl(&board_ctrl->fwcmd_param);	cy_writel(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->loc_doorbell,                  0xffffffff);	return 1;    }    return 0;} /* cyz_fetch_msg */static intcyz_issue_cmd( struct cyclades_card *cinfo,	    uclong channel, ucchar cmd, uclong param){  struct FIRM_ID *firm_id;  struct ZFW_CTRL *zfw_ctrl;  struct BOARD_CTRL *board_ctrl;  volatile uclong *pci_doorbell;  int index;    firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);    if (!ISZLOADED(*cinfo)){	return (-1);    }    zfw_ctrl = (struct ZFW_CTRL *)	       (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));    board_ctrl = &zfw_ctrl->board_ctrl;    index = 0;    pci_doorbell = (uclong *)(&((struct RUNTIME_9060 *)                               (cinfo->ctl_addr))->pci_doorbell);    while( (cy_readl(pci_doorbell) & 0xff) != 0){        if (index++ == 1000){            return(-1);        }	udelay(50L);    }    cy_writel((u_long)&board_ctrl->hcmd_channel, channel);    cy_writel((u_long)&board_ctrl->hcmd_param , param);    cy_writel((u_long)pci_doorbell, (long)cmd);    return(0);} /* cyz_issue_cmd */#if 0static intcyz_update_channel( struct cyclades_card *cinfo,	    u_long channel, u_char mode, u_char cmd){   struct FIRM_ID *firm_id =      (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);  struct ZFW_CTRL *zfw_ctrl;  struct CH_CTRL *ch_ctrl;    if (!ISZLOADED(*cinfo)){	return (-1);    }    zfw_ctrl = (struct ZFW_CTRL *)	       (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));    ch_ctrl = zfw_ctrl->ch_ctrl;    cy_writel(&ch_ctrl[channel].op_mode, (uclong)mode);    return cyz_issue_cmd(cinfo, channel, cmd, 0L);} /* cyz_update_channel */#endifstatic voidcyz_interrupt(int irq, void *dev_id, struct pt_regs *regs){} /* cyz_interrupt */static voidcyz_poll(unsigned long arg){  static volatile struct FIRM_ID *firm_id;  static volatile struct ZFW_CTRL *zfw_ctrl;  static volatile struct BOARD_CTRL *board_ctrl;  static volatile struct CH_CTRL *ch_ctrl;  static volatile struct BUF_CTRL *buf_ctrl;  struct cyclades_card *cinfo;  struct cyclades_port *info;  struct tty_struct *tty;  int card, port;  int char_count;#ifdef BLOCKMOVE  int small_count;#endif  char data;  uclong channel;  ucchar cmd;  uclong param;  uclong hw_ver, fw_ver;  volatile uclong tx_put, tx_get, tx_bufsize;  volatile uclong rx_put, rx_get, rx_bufsize;    cyz_timerlist.expires = jiffies + (HZ);    for (card = 0 ; card < NR_CARDS ; card++){	cinfo = &cy_card[card];	if (!IS_CYC_Z(*cinfo)) continue;	firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);        if (!ISZLOADED(*cinfo)) {	    cinfo->inact_ctrl = 0;	    continue;	}	zfw_ctrl = (struct ZFW_CTRL *)	           (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));	board_ctrl = &(zfw_ctrl->board_ctrl);	fw_ver = cy_readl(&board_ctrl->fw_version);	hw_ver = cy_readl(&((struct RUNTIME_9060 *)                            (cinfo->ctl_addr))->mail_box_0);	/* Enables the firmware inactivity control */	if ((fw_ver > 0x00000310L) && (!cinfo->inact_ctrl)) {	    param = cyz_issue_cmd( &cy_card[card], 0L, C_CM_TINACT, 0L);	    cinfo->inact_ctrl = 1;	}	while(cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1){	    char_count = 0;	    info = &cy_port[ channel + cinfo->first_line ];            if((tty = info->tty) == 0) continue;	    ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);	    buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);	    info->jiffies[0] = jiffies;	    switch(cmd){	    case C_CM_PR_ERROR:		tty->flip.count++;		*tty->flip.flag_buf_ptr++ = TTY_PARITY;		*tty->flip.char_buf_ptr++ = 0;		char_count++;	        break;	    case C_CM_FR_ERROR:		tty->flip.count++;		*tty->flip.flag_buf_ptr++ = TTY_FRAME;		*tty->flip.char_buf_ptr++ = 0;		char_count++;	        break;	    case C_CM_RXBRK:		tty->flip.count++;		*tty->flip.flag_buf_ptr++ = TTY_BREAK;		*tty->flip.char_buf_ptr++ = 0;		char_count++;	        break;	    case C_CM_MDCD:		if (info->flags & ASYNC_CHECK_CD){		    if ((fw_ver > 241 ?                           ((u_long)param) :                           cy_readl(&ch_ctrl[channel].rs_status)) & C_RS_DCD) {			cy_sched_event(info,			    Cy_EVENT_OPEN_WAKEUP);		    }else if(!((info->flags				& ASYNC_CALLOUT_ACTIVE)			 &&(info->flags			    & ASYNC_CALLOUT_NOHUP))){			cy_sched_event(info,			    Cy_EVENT_HANGUP);		    }		}	        break;	    case C_CM_MCTS:		if (info->flags & ASYNC_CTS_FLOW) {		    if(info->tty->hw_stopped){			if( cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD){			    /* cy_start isn't used because... 			       HW flow is handled by the board */			    cy_sched_event(info,				Cy_EVENT_WRITE_WAKEUP);			}		    }else{			if(!(cy_readl(&ch_ctrl[channel].rs_status) & C_RS_CTS)){			    /* cy_stop isn't used because 			       HW flow is handled by the board */			}		    }		}	        break;	    case C_CM_MRI:	        break;	    case C_CM_MDSR:	        break;#ifdef Z_WAKE	    case C_CM_IOCTLW:		cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);	        break;#endif	    case C_CM_FATAL:		/* should do something with this !!! */	        break;	    }	    if(char_count){		queue_task(&tty->flip.tqueue, &tq_timer);	    }	}	for (port = 0; port < cy_readl(&board_ctrl->n_channel); port++){	    info = &cy_port[ port + cinfo->first_line ];            tty = info->tty;	    ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);	    buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);/* Removed due to compilation problems in Alpha systems *///	    if ((char_count = CHARS_IN_BUF(buf_ctrl))){	    rx_get = cy_readl(&buf_ctrl->rx_get);	    rx_put = cy_readl(&buf_ctrl->rx_put);	    rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);	    if (rx_put >= rx_get)	    	char_count = rx_put - rx_get;	    else	    	char_count = rx_put - rx_get + rx_bufsize;	    if ( char_count ){		info->last_active = jiffies;		info->jiffies[1] = jiffies;#ifdef CY_ENABLE_MO

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -