📄 ul_cps1.c
字号:
while(!uld_atomic_test_dfl(udrv,KWTKILL) && !fatal_err){ uld_kwt_confirm(udrv); while(!ul_usb_tx_fifo_full(&tx_fifo)){ /* when free Tx slot */ /* Initiate sending of message from the prep_bll queue */ if(!(tx_mes=udrv->con_message=udrv->prep_bll.first)) break; /* printudrvbll(udrv); */ ul_bll_move_mes(&udrv->work_bll,tx_mes); LOG_MESSAGES(KERN_INFO "ul_usb: KWT processing message\n"); if(!++ustamp) ustamp=1; /* send frames of message */ for(frame=tx_mes;frame;frame=UL_BLK_HEAD(frame).next){ ret=ul_usb_ps1_send_frame(udrv, frame, ustamp); if(ret<0) { usb_clear_halt(dev, usb_sndbulkpipe(dev, udrv->ul_usb_outpipe_nr)); UL_BLK_HEAD(tx_mes).flg|=UL_BFL_FAIL; ul_bll_move_mes(&udrv->proc_bll,tx_mes); SCHEDULE_BH(udrv); /* ulan_do_bh(udrv); */ tx_mes=udrv->con_message=NULL; break; } /* Message has no more frames */ if(!(UL_BLK_HEAD(frame).flg&UL_BFL_TAIL)|| (UL_BLK_HEAD(frame).next==NULL)){ tx_fifo.slot[tx_fifo.idxin].ustamp=ustamp; tx_fifo.slot[tx_fifo.idxin].msg=tx_mes; tx_fifo.idxin=ul_usb_tx_fifo_incidx(&tx_fifo,tx_fifo.idxin); #ifdef FOR_LINUX_KERNEL tx_sta_time=jiffies; #endif /* FOR_LINUX_KERNEL */ ul_usb_tx_fifo_print(&tx_fifo); } } } UL_MB(); in_urb_st=*(volatile unsigned *)&(udrv->ul_usb_in_urb_st); UL_MB(); if(in_urb_st==2) { UL_MB(); LOG_IRQ(KERN_CRIT "ul_usb : received head URB (d:%d,s:%d,c:%X,f:%X,l:%d) stmp %d\n", in_buf[0],in_buf[1],in_buf[2],in_buf[3], in_buf[6]+0x100*in_buf[7],in_buf[4]); if(in_buf[3]&(U2UBFL_PROC|U2UBFL_FAIL)){ tx_mes=NULL; ul_usb_tx_fifo_print(&tx_fifo); if(!ul_usb_tx_fifo_empty(&tx_fifo)){ if(in_buf[4]==tx_fifo.slot[tx_fifo.idxout].ustamp){ tx_mes=tx_fifo.slot[tx_fifo.idxout].msg; }else{ i=ul_usb_tx_fifo_incidx(&tx_fifo,tx_fifo.idxout); while((i!=tx_fifo.idxout)&&(tx_fifo.slot[i].msg!=NULL)){ if(in_buf[4]==tx_fifo.slot[i].ustamp){ do{ tx_mes=tx_fifo.slot[tx_fifo.idxout].msg; UL_BLK_HEAD(tx_mes).flg|=UL_BFL_FAIL; ul_bll_move_mes(&udrv->proc_bll,tx_mes); tx_fifo.slot[tx_fifo.idxout].msg=NULL; tx_fifo.idxout=ul_usb_tx_fifo_incidx(&tx_fifo,tx_fifo.idxout); }while(tx_fifo.idxout!=i); SCHEDULE_BH(udrv); tx_mes=tx_fifo.slot[tx_fifo.idxout].msg; } i=ul_usb_tx_fifo_incidx(&tx_fifo,i); } if(!tx_mes){ LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: incorrect ustamp of returned message\n"); }else{ LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: some lost ustamp messages\n"); } } }else{ LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: tx_mes for returned message\n"); } if(!tx_mes){ usb_clear_halt(dev, usb_rcvbulkpipe(dev, udrv->ul_usb_inpipe_nr)); }else{ if(tail_frame&&(UL_BLK_HEAD(tx_mes).flg&UL_BFL_TAIL)){ frame=tail_frame; LOG_MESSAGES("ul_usb_ps1_thread: tail receiption\n"); }else{ frame=tx_mes; } if(in_buf[3]&U2UBFL_FAIL){ UL_BLK_HEAD(tx_mes).flg|=UL_BFL_FAIL; }else if(in_buf[3]&U2UBFL_REC) { if(!(UL_BLK_HEAD(frame).flg&UL_BFL_REC)){ UL_BLK_HEAD(tx_mes).flg|=UL_BFL_FAIL; LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: tail rec mitchmatch\n"); }else{ len=in_buf[6]+in_buf[7]*0x100; UL_BLK_HEAD(frame).dadr=in_buf[0]; UL_BLK_HEAD(frame).sadr=in_buf[1]; UL_BLK_HEAD(frame).cmd=in_buf[2]; UL_BLK_HEAD(frame).len=len; ret=ul_usb_ps1_receive_data(udrv, frame, len); if(ret<0) { UL_BLK_HEAD(tx_mes).flg|=UL_BFL_FAIL; LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: tail receive problem\n"); } } } if((in_buf[3]&U2UBFL_TAIL)&&(UL_BLK_HEAD(frame).flg&UL_BFL_TAIL) &&!(UL_BLK_HEAD(tx_mes).flg&UL_BFL_FAIL)){ tail_frame=UL_BLK_HEAD(frame).next; LOG_MESSAGES("ul_usb_ps1_thread: preparing for tail receive\n"); }else{ if(UL_BLK_HEAD(tx_mes).flg&UL_BFL_M2IN || UL_BLK_HEAD(tx_mes).flg&UL_BFL_FAIL || UL_BLK_HEAD(tx_mes).dadr==udrv->my_adr || !UL_BLK_HEAD(tx_mes).dadr){ ul_bll_move_mes(&udrv->proc_bll,tx_mes); SCHEDULE_BH(udrv); /* ulan_do_bh(udrv); */ }else{ ul_bll_free_mes(tx_mes); } tx_mes=NULL; tail_frame=NULL; tx_fifo.slot[tx_fifo.idxout].msg=NULL; tx_fifo.idxout=ul_usb_tx_fifo_incidx(&tx_fifo,tx_fifo.idxout); ul_usb_tx_fifo_print(&tx_fifo); } } } else { LOG_MESSAGES("uLan : begin of receive message\n"); i=0; /* if(in_buf[3]&U2UBFL_TAIL ) i|=UL_BFL_TAIL; */ /* if(in_buf[3]&U2UBFL_REC) i|=UL_BFL_REC; */ rx_mes=ul_new_frame_head(udrv,in_buf[0]/*dadr*/,in_buf[1]/*sadr*/, in_buf[2]/*cmd*/, i/*flg*/); if(rx_mes==NULL){ LOG_FAILS(KERN_ERR "uLan : NO memory for receive\n"); usb_clear_halt(dev, usb_rcvbulkpipe(dev, udrv->ul_usb_inpipe_nr)); }else{ ul_bll_ins(&udrv->work_bll,rx_mes); len=in_buf[6]+in_buf[7]*0x100; ret=ul_usb_ps1_receive_data(udrv, rx_mes, len); if(ret<0) { LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: message receive problem\n"); ul_bll_free_mes(rx_mes); }else{ UL_BLK_HEAD(rx_mes).len=len; UL_BLK_HEAD(rx_mes).stamp=ul_gen_stamp(); ul_bll_move_mes(&udrv->proc_bll,rx_mes); } rx_mes=NULL; SCHEDULE_BH(udrv); /* ulan_do_bh(udrv); */ /* printudrvbll(udrv); */ } } } if(in_urb_st!=1) { #ifdef FOR_LINUX_KERNEL ret=16-udrv->ul_usb_in_urb_st; if((ret==-ENODEV)||(ret==-EILSEQ)||(ret==-EPROTO)){ LOG_FATAL(KERN_INFO "ul_usb: usb2ulan device problem detected\n"); fatal_err=1; continue; } #endif /* FOR_LINUX_KERNEL */ *(volatile unsigned *)&(udrv->ul_usb_in_urb_st)=1; UL_MB(); if(uld_atomic_test_dfl(udrv,KWTKILL)) break; LOG_IRQ(KERN_INFO "ul_usb: submitting URB\n"); #ifdef FOR_LINUX_KERNEL usb_fill_bulk_urb (in_urb, dev, usb_rcvbulkpipe(dev, udrv->ul_usb_inpipe_nr), (void*)in_buf, 8, ul_usb_ps1_complete_in, udrv); ret=kc_usb_submit_urb(in_urb, GFP_KERNEL); if (ret==-EPIPE) { usb_clear_halt(dev, usb_rcvbulkpipe(dev, udrv->ul_usb_inpipe_nr)); ret=kc_usb_submit_urb(in_urb, GFP_KERNEL); } if(ret<0) { LOG_FATAL(KERN_INFO "ul_usb: KWT usb_submit_urb fatal error %d\n",ret); fatal_err=1; } #else _usb_fill_bulk_urb (in_urb, dev, usb_rcvbulkpipe(dev, udrv->ul_usb_inpipe_nr), (void*)in_buf, 8); ret=_usb_submit_urb(dev,in_urb, NULL,ul_usb_ps1_complete_in,udrv,&in_irp); if ( !NT_SUCCESS(ret)) { LOG_FATAL(KERN_INFO "ul_usb: KWT usb_submit_urb fatal error %d\n",ret); fatal_err=1; } #endif /* FOR_LINUX_KERNEL */ } else { LOG_IRQ(KERN_INFO "ul_usb: KWT sleeping\n"); uld_kwt_wait(udrv); LOG_IRQ(KERN_INFO "ul_usb: KWT wakeup\n"); } } /* Set converter parameters */ ret=usb_control_msg(dev, usb_rcvctrlpipe(dev,0), VENDOR_STOP_ULAN, USB_TYPE_VENDOR, /*value*/ 0, /*index*/ 0, NULL, 0, ULD_HZ); if(ret<0) { LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: KWT usb_control_msg error %d returned\n",ret); fatal_err=1; } ul_usb_tx_fifo_print(&tx_fifo); while(!ul_usb_tx_fifo_empty(&tx_fifo)){// ul_bll_free_mes(tx_fifo.slot[tx_fifo.idxout].msg); tx_mes=tx_fifo.slot[tx_fifo.idxout].msg; UL_BLK_HEAD(tx_mes).flg|=UL_BFL_FAIL; ul_bll_move_mes(&udrv->proc_bll,tx_mes); tx_fifo.slot[tx_fifo.idxout].msg=NULL; tx_fifo.idxout=ul_usb_tx_fifo_incidx(&tx_fifo,tx_fifo.idxout); } if(in_urb) { #ifdef FOR_LINUX_KERNEL #if (LINUX_VERSION_CODE >= VERSION(2,6,9)) usb_kill_urb(in_urb); #else usb_unlink_urb(in_urb); #endif usb_free_urb(in_urb); #else if (in_irp) IoCancelIrp( in_irp); FREE( in_urb); #endif /* FOR_LINUX_KERNEL */ } #ifdef FOR_LINUX_KERNEL lock_kernel(); #endif /* FOR_LINUX_KERNEL */ LOG_IRQ(KERN_INFO "ul_usb: KWT finished\n"); uld_kwt_set_stopped(udrv); #ifdef FOR_LINUX_KERNEL unlock_kernel(); #else PsTerminateSystemThread( STATUS_SUCCESS); #endif /* FOR_LINUX_KERNEL */ return 0;}/*** Wake up worker thread ***/int ul_usb_ps1_stroke(ul_drv *udrv){ uld_kwt_wake(udrv); return 0;}/*** Control functions of chip driver ***/int ul_usb_ps1_cctrl(ul_drv *udrv, int ctrl_fnc, int param){ switch (ctrl_fnc) { case UL_CC_PINIT: /* initialize ports (parameter baud)*/ { return 0; }; case UL_CC_PDONE: /* deinitialize ports */ { return 0; }; case UL_CC_RQIRQ: /* request IRQ handling - kernel worker thread*/ { if(uld_kwt_test_and_set_prepared(udrv)) { LOG_IRQ("ul_usb_ps1_cctrl: KWT already running\n"); return 0; }; uld_atomic_clear_dfl(udrv,KWTKILL); #ifdef FOR_LINUX_KERNEL if(kernel_thread(ul_usb_ps1_thread, udrv, #if (LINUX_VERSION_CODE < VERSION(2,5,41)) CLONE_FS | CLONE_FILES | CLONE_SIGNAL #else /* 2.5.41 */ CLONE_KERNEL #endif /* 2.5.41 */ )<0){ LOG_FATAL(KERN_CRIT "ul_usb_ps1_cctrl: Cannot fork KWT thread!!!\n"); /*uld_atomic_clear_dfl(udrv,KWTRUN);*/ uld_kwt_set_stopped(udrv); return UL_RC_EKWT; } #endif /*FOR_LINUX_KERNEL*/ #ifdef _WIN32 { NTSTATUS ntStatus; ntStatus = PsCreateSystemThread( &udrv->kwt, THREAD_ALL_ACCESS, NULL, NULL, NULL, ul_usb_ps1_thread, udrv); if (!NT_SUCCESS(ntStatus)) { LOG_FATAL(KERN_CRIT "ul_usb_ps1_cctrl: Cannot fork KWT thread!!!\n"); /*uld_atomic_clear_dfl(udrv,KWTRUN);*/ uld_kwt_set_stopped(udrv); return UL_RC_EKWT; } } #endif /* _WIN32 */ LOG_IRQ("ul_usb_ps1_cctrl: KWT forked\n"); return 0; }; case UL_CC_FREEIRQ: /* release IRQ handling - kernel worker thread*/ { if(!uld_kwt_is_running(udrv)) { LOG_IRQ("ul_usb_ps1_cctrl: KWT already stopped\n"); return 0; }; uld_kwt_kill(udrv); uld_kwt_wait_stopped(udrv); LOG_IRQ("ul_usb_ps1_cctrl: KWT stopped\n"); return 0; }; }; return UL_RC_ENOFNC;};/*** Petr Smolik's USB2ULAN version 1 initialize ***/int ul_usb_ps1_init(ul_drv *udrv, int port, int irq, int baud, long baudbase, int options){ udrv->chip_options=options; if(!baud) baud=19200; udrv->baud_val=baud; if(!baudbase) baudbase=57600; udrv->baud_base=baudbase; udrv->baud_div=(udrv->baud_base+baud/2)/baud; udrv->port=port; udrv->irq=0; udrv->fnc_recch=NULL; udrv->fnc_sndch=NULL; udrv->fnc_wait=NULL; udrv->fnc_pool=NULL; udrv->fnc_connect=NULL; udrv->fnc_cctrl=&ul_usb_ps1_cctrl; udrv->fnc_stroke=&ul_usb_ps1_stroke; udrv->ul_usb_max_pkt_size=8; /* <= U2U_PKT_BUF_SIZE */ udrv->ul_usb_max_msg_inpr=ul_usb_msg_inpr; if(!udrv->ul_usb_max_msg_inpr) udrv->ul_usb_max_msg_inpr=1; /* <= U2U_MAX_MSG_INPR */ udrv->ul_usb_outpipe_nr=1; /* OUT pipe number */ udrv->ul_usb_inpipe_nr=1; /* IN pipe number */ return 0;};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -