📄 cyclades.c
字号:
*/ 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, ¶m) == 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 + -