專利名稱::綜合業(yè)務(wù)數(shù)字網(wǎng)通信的逆多路傳送系統(tǒng)的制作方法本申請要求1998年6月12日提交的名稱“ISDN通信接口的基于狀態(tài)的連接技術(shù)”的美國臨時申請60/089,172、1998年8月18日提交的名稱“逆多路傳送系統(tǒng)”的美國臨時申請60/096,971、及1999年6月9日提交的名稱“ISDN通信的逆多路傳送系統(tǒng)”的U.S.S.N____,(快遞郵件標簽EE77615410US)的優(yōu)先權(quán)。通過引用將上述申請的內(nèi)容結(jié)合在此。本發(fā)明涉及ISDN通信,更具體地,涉及處理與生成“逆多路傳送的”ISDN流。本發(fā)明可應(yīng)用在網(wǎng)絡(luò)接口卡或連接到ISDN通信線路上的其它裝置。為了方便,此后將這些卡與其它裝置統(tǒng)稱為網(wǎng)絡(luò)接口卡或NIC。如通常所知,能將ISDN網(wǎng)絡(luò)配置成在各包含多條數(shù)據(jù)信道的多條ISDN線路上傳送單一數(shù)據(jù)流。這是對電視會議及需要比單一ISDN信道所提供的更大帶寬的其它數(shù)據(jù)密集型應(yīng)用的有利之處。然而,在多信道ISDN通信中出現(xiàn)問題,因為在各自的線路上的傳輸會主要由于這些線路所建立的通信路徑中的判別而互相相對延時。此外,在網(wǎng)絡(luò)上起動多個呼叫的實踐通常導(dǎo)致信道呈現(xiàn)為“交叉的”。從而,例如在網(wǎng)絡(luò)一端上定義為“信道1”的信道可能在另一端上呈現(xiàn)為“信道3”,反之亦然。圖1中示出這些困難。其中,在ISDN網(wǎng)絡(luò)的一側(cè)上將包括模型1、2與3的測試數(shù)據(jù)輸入到各自的信道中。這些數(shù)據(jù)在通過網(wǎng)絡(luò)的路徑上既延時又交叉。具體地,在所示的示例中,網(wǎng)絡(luò)設(shè)置導(dǎo)致標記為5與6的兩條信道上的數(shù)據(jù)出現(xiàn)交叉,從而一個節(jié)點傳輸?shù)哪P汀?11111112222222233333333”接收為“222222221111111133333333”。在傳輸延時中,又導(dǎo)致在信道6上原始發(fā)送的模型“1”相對于其它信道位移兩個時隙9。如不補償信道間延時及信道交叉,多信道ISDN通信將是實際上不可能的。例如,如果表示一個圖像如視頻會議參加者的圖像的數(shù)據(jù)是在圖1中所示的信道上傳輸?shù)?,所示的效果會?dǎo)致接收端上的歪曲。為了解決這些問題,已研制了稱作“逆多路傳送”(有時稱作“接合(bonding)”,它是特定類型的逆多路傳輸)的技術(shù)。這是重構(gòu)或聚集通過多條ISDN信道傳輸?shù)臄?shù)據(jù)的過程。它通常是按照一組國際協(xié)議實現(xiàn)的,這些協(xié)議詳述在網(wǎng)絡(luò)端點上的設(shè)備(諸如NIC)如何互相發(fā)信號來開放信道及為了鑒別信道間延時與信道交叉的目的互相“訓(xùn)練”。訓(xùn)練的實現(xiàn)傳統(tǒng)上需要數(shù)字信號處理器與緩沖器的復(fù)雜配置。利用它們來生成從網(wǎng)絡(luò)的各端傳輸?shù)挠?xùn)練模型并且分析它們來確定克服信道間延時與交叉的必要參數(shù)。一旦完成了訓(xùn)練,便利用這些參數(shù)來重新排序與校準在通話期間交換的數(shù)據(jù)。雖然傳統(tǒng)的逆多路傳送系統(tǒng)提供精確的數(shù)據(jù)重新校準及重新排序,但它們實現(xiàn)起來是昂貴的。除了高速、高功率數(shù)字信號處理器,傳統(tǒng)的逆多路傳送技術(shù)的實現(xiàn)需要大量快速程序存儲器(例如32Kbyte或以上)及數(shù)據(jù)存儲器(例如120Kbyte)用于緩沖存儲進入及外出(outgoing)數(shù)據(jù)流。這些部件能極大地增加用在ISDN網(wǎng)絡(luò)的終端端上的網(wǎng)絡(luò)接口卡或其它設(shè)備的成本。有鑒于此,本發(fā)明的目的為提供用于ISDN通信的改進的方法與裝置。本發(fā)明更具體的目的為提供用于處理逆多路傳送(或接合)的ISDN數(shù)據(jù)及用于生成這些數(shù)據(jù)的改進的方法與裝置。本發(fā)明的更進一步的目的為提供能用傳統(tǒng)的部件實現(xiàn)的方法與裝置而不過度消耗財政資源、操作能力、或印刷板“不動產(chǎn)”。發(fā)明概述本發(fā)明一方面通過提供對從多條ISDN信道接收的數(shù)據(jù)提供改進的逆多路傳送的網(wǎng)絡(luò)接口卡(或其它ISDN接口設(shè)備)來解決上述需求。NIC將從信道接收的訓(xùn)練數(shù)據(jù)存儲進不同的相應(yīng)緩沖器中,并通過比較這些緩沖器中與該數(shù)據(jù)關(guān)聯(lián)的數(shù)值計數(shù)的相對位置來確定信道間延時。訓(xùn)練之后,NIC利用分配給信道的輸出指針及與延時一致的偏移將通話數(shù)據(jù)聚集到單一的流或存儲區(qū)中。在相關(guān)方面中,本發(fā)明提供上述NIC,它將從各自的信道中的訓(xùn)練數(shù)據(jù)中導(dǎo)出的幀計數(shù)或其它順序數(shù)據(jù)存儲到緩沖器中。通過比較包含在緩沖器的對應(yīng)位置中的計數(shù)確定信道間延時。例如,如果幀計數(shù)15存儲在與信道1關(guān)聯(lián)的緩沖器的地址10上,而幀計數(shù)17存儲在與信道2關(guān)聯(lián)的緩沖器的同一地址上,按照本發(fā)明這一方面的NIC將確定信道間延時為2,即17—15。根據(jù)這一確定,將緩沖器的輸出指針偏移2來保證在通話數(shù)據(jù)的隨后聚集(即逆多路傳送)期間正確的校準。在本發(fā)明的較佳方面中,上述NIC通過比較包含在它們各自的進入(ingoing)指針上或附近的緩沖器中的計數(shù)來確定信道間延時。為了確定延時,將指針本身的值之間的差考慮進去。從而,接上面的示例,如果值15存儲在與信道1關(guān)聯(lián)的緩沖器的呼入(incoming)指針上,值18存儲在與信道2關(guān)聯(lián)的緩沖器中的呼入指針上,信道1的進入指針的值為10而信道2的呼入指針的值為11,則按照本發(fā)明的這一方面的NIC將確定信道間延時為2,即(18—15)—(11—10)。本發(fā)明的其它方面提供上述NIC,它利用傳統(tǒng)通信微處理器的串行通信控制器(“SCC”)跟蹤緩沖器指針,將數(shù)據(jù)存儲到緩沖器中及從緩沖器中檢索數(shù)據(jù)。按照本發(fā)明的另一方面的上述NIC為了補償信道交叉而重新排序數(shù)據(jù)。NIC通過諸如與幀計數(shù)一起檢驗存儲在緩沖器中的信道數(shù)據(jù)來確定是否出現(xiàn)這種交叉。通過以補償任何檢測到的交叉的序列從緩沖器中輸出數(shù)據(jù)來進行重新排序。例如,如果在信道2中接收到預(yù)期在信道3中的訓(xùn)練數(shù)據(jù)并將其存儲在其相關(guān)緩沖器中,而在信道3中接收到預(yù)期在信道2中的數(shù)據(jù)并將其存儲在其相關(guān)緩沖器中,按照本發(fā)明這一方面的NIC在從信道2的緩沖器輸出數(shù)據(jù)之前先從信道3的緩沖器輸出數(shù)據(jù)。作為替代,該NIC能從緩沖器3輸出數(shù)據(jù)到否則與信道2關(guān)聯(lián)的聚集存儲區(qū)中,反之亦然。按照本發(fā)明的另一方面,為了保證寫入將落在長字或其它要求的邊界上,上述NIC延遲到信道緩沖器的寫入。從而,由NIC接收并在它的內(nèi)部總線上傳輸了一定的時鐘周期的字節(jié)數(shù)據(jù)的緩沖被延遲了一到三個幀。這保證寫入到具有這一限制的設(shè)備的緩沖器內(nèi)要求的邊界上。本發(fā)明的又另一方面提供包含用于與ISDN線路交換信號的S/T接口芯片或其它設(shè)備的上述類型的NIC。該NIC能進一步包含確定線路接口與維護上述信道緩沖器的通信微處理器之間的各數(shù)據(jù)信道的路由的現(xiàn)場可編程的門陣列(FPGA)。這一FPGA能進一步在緩沖器與NIC位于其中的主機之間傳送數(shù)據(jù)。本發(fā)明的又另一方面提供對應(yīng)于上述操作的逆多路傳送ISDN數(shù)據(jù)的方法。已提供了這一簡明概述以便快速理解本發(fā)明的特性。在下面的詳細描述及附圖中,本發(fā)明及其各方面的更完整的理解是顯而易見的。附圖簡述通過參照附圖可以獲得本發(fā)明的更完整的理解,其中圖1描繪帶有用本發(fā)明校正的類型的信道交叉及信道間延時的多信道ISDN通信;圖2描繪按照本發(fā)明的較佳實施例的NIC的體系結(jié)構(gòu);圖3描繪使圖2的NIC能進行與主機的并行與串行數(shù)據(jù)傳送的現(xiàn)場可編程的門陣列(FPGA);圖4描繪配置成在ISDN線路與NIC的處理器之間以及在NIC與主機之間實行串行數(shù)據(jù)傳送的圖3的FPGA;圖5為展示在圖4中所示的配置的IDL總線上的數(shù)據(jù)的定時與路由選擇的表;圖6示出圖2的NIC的內(nèi)部時分多路傳送總線上的ISDN數(shù)據(jù)傳送的定時;圖7示出用在傳統(tǒng)逆多路傳送過程中的訓(xùn)練模型;圖8—12示出為了實現(xiàn)逆多路傳送而在圖2的NIC中如何使用緩沖器與指針;圖9示出圖8的緩沖器,其中第一緩沖器填充有數(shù)據(jù);圖10示出圖8的緩沖器,其中二個緩沖器都填充有數(shù)據(jù);圖11示出比圖10中所示的稍晚的時間點上的圖8的緩沖器;圖12示出在從其中輸出數(shù)據(jù)期間的圖8的緩沖器;圖13抽象地描繪從圖8的緩沖器輸出數(shù)據(jù)到輸出緩沖器;圖14示出在NIC的處理器上執(zhí)行的實現(xiàn)按照本發(fā)明的接合的軟件任務(wù);圖15示出用在本發(fā)明的較佳實現(xiàn)中的傳輸與接收緩沖器;以及圖16示出用在本發(fā)明的另一實現(xiàn)中的傳輸與接收緩沖器。1.概述圖2為按照本發(fā)明的一個實施例的網(wǎng)絡(luò)接口卡(“NIC”)的高層框圖。所示的卡20提供ISDN網(wǎng)絡(luò)與諸如電視會議設(shè)備或其它裝置等主機之間的接口。本發(fā)明不限于用在這一范圍中,可包含在各式各樣的不同環(huán)境中。可將卡20安裝成與主機總線、電源與其它電路直接物理與電連接,但是最好將它“馱載”在另一電路板上(諸如ISA或PCI板),后者本身與主機直接連接。NIC20包含通過它與主機交換數(shù)據(jù)及控制信號的接口29。這一接口最好包含能在NIC20與主機之間能進行并行數(shù)據(jù)傳送與串行數(shù)據(jù)傳送的導(dǎo)線。所示的NIC20還包含用于與對應(yīng)的基本速率接口(“BRI”)ISDN線路接口的三個S/T接口設(shè)備25、26與27??筛鶕?jù)需要提供更多或更少的這種設(shè)備。S/T接口25、26與27最好是符合ANSIT1.601-1992的標準電路設(shè)備??捎糜谶@一目的的芯片的實例為MotorotaMC145574。各S/T接口設(shè)備端接對應(yīng)的ISDN線路25a、26a與27a,并在該線路與NIC之間傳遞數(shù)據(jù)。關(guān)于這一點,各ISDN線路包含兩條承載(或B)信道及單一數(shù)據(jù)(或D)信道。B信道通常在NIC與ISDN網(wǎng)絡(luò)節(jié)點之間攜帶視頻、音頻及其它信號。D信道在NIC與控制ISDN線路的任何事物(如電話公司)之間攜帶線路建立及其它“管理”數(shù)據(jù)。S/T接口25—27各包含支持向/自NIC的數(shù)據(jù)(諸如視頻、HDLC與透明)傳送TDM的串行接口,具體地為2.048MbpsIDL總線35。當(dāng)然,熟悉本技術(shù)的人員理解本發(fā)明不依賴于NIC內(nèi)使用的總線(IDL或其它)的特定類型。S/T接口包含一或多個內(nèi)部緩沖器(未示出),能將它們配置成響應(yīng)來自處理器28的命令諸如用總線35臨時存儲與傳送數(shù)據(jù)。各S/T接口芯片還包含用于接口到SCP總線37上的串行控制端口(“SCP”)總線接口。SCP總線37提供關(guān)于NIC從其接收數(shù)據(jù)的ISDN線路的數(shù)目及其它事物的信息給處理器28上的SCP40。然后將這一信息提供給處理器的SCC—41(32信道全雙工SCC),然后后者相應(yīng)地調(diào)節(jié)其處理(如連接)。最后,S/T接口包含用于驅(qū)動中斷到處理器28上的中斷針腳。雖然其它類型的處理器也可采用,處理器28最好是在25MHz上操作的MotorotaMC68MH360微處理器。處理器28包含SCC41、SCP端口40、及中斷控制器42等。SCC41接收來自IDL總線35的多達32個信道的ISDN數(shù)據(jù),并相應(yīng)地處理這些數(shù)據(jù),例如在其上執(zhí)行逆多路傳送(即接合)。SCP端口40接收來自S/T接口的關(guān)于連接在其上的ISDN線路的數(shù)據(jù),并提供該數(shù)據(jù)給處理器。中斷控制器42接收來自上述S/T接口以及對FPGA的中斷。處理器28也可包含用于存儲ISDN及其它數(shù)據(jù)的一或多個內(nèi)部RAM高速緩沖存儲器(未示出)。存儲器31在本發(fā)明的較佳實施例中包括DRAM。處理器28利用這一存儲器來緩存在ISDN線路與主機之間傳送的數(shù)據(jù)以及存儲供處理器28執(zhí)行的指令。在本發(fā)明的較佳實施例中存儲器30包括1Mbyte快速EEPROM。這一存儲器也存儲供處理器28執(zhí)行的指令,如主機代碼。參見圖3,F(xiàn)PGA32由配置成例如響應(yīng)從處理器28接收的命令來實現(xiàn)在S/T接口芯片與主機接口29的串行或并行部分之間的接合的或不接合的ISDN數(shù)據(jù)的傳送的可編程的邏輯門構(gòu)成。虛線右邊的FPGA的部分32a在S/T接口與處理器28之間傳送ISDND信道數(shù)據(jù),同時在這些接口與主機接口29的串行信道之間直接(在不接合傳送的情況中)或間接通過處理器28(在接合傳送的情況中)路由B信道數(shù)據(jù)。下面在節(jié)2中描述這一點。虛線左邊的FPGA32的部分32b在處理器28與主機接口29的并行信道之間傳送接合與不接合的B信道數(shù)據(jù)兩者。下面在節(jié)3中描述這一點。2.與主機的串行傳送圖4示出配置成在S/T接口芯片25—27與主機接口29的串行部分之間路由ISDN數(shù)據(jù)的FPGA32。在這一點上,微處理器28將FPGA32配置成仿真時變多路傳送器65、66與67。簡言之,多路傳送器(Mux)65通過IDL總線37將在IDL總線35上接收的ISDN數(shù)據(jù)傳輸?shù)教幚砥?8。這里,數(shù)據(jù)可以是以傳統(tǒng)方式或最好是以下面節(jié)4中所描述的方式接合的(即逆多路傳送的)。然后沿IDL總線37將接合的數(shù)據(jù)傳輸回多路傳送器67,從那里通過IDL總線36將數(shù)據(jù)傳輸?shù)街鳈C(或承載器卡)70。類似地,多路傳送器65從IDL總線36將傳輸?shù)臄?shù)據(jù)路由到處理器28。數(shù)據(jù)可以在那里接合,然后沿IDL總線37傳輸回多路傳送器66,從那里將數(shù)據(jù)傳輸?shù)絀SDN線路。在NIC并不采用接合的情況中,沿IDL總線35從S/T接口將不接合的數(shù)據(jù)直接傳輸?shù)蕉嗦穫魉推?7,從那里通過IDL總線36將其直接傳輸?shù)街鳈C70。類似地,不接合的數(shù)據(jù)可通過IDL總線36從主機70直接傳輸?shù)蕉嗦穫魉推?6,從那里將其路由到ISDN線路。在示出的NIC中,時變多路傳送器65、66與67的配置是受處理器按照所要求的IDL總線路由選擇控制的,后者又取決于是否執(zhí)行接合。這又受從主機接收的命令支配。當(dāng)然,可將這一信息“硬編碼”在NIC,或由其控制。圖5為詳細示出何時何地多路傳送器65、66或67在NIC的IDL總線中選擇數(shù)據(jù)路由的表。表中的列標識這些總線。從而,例如將總線35的傳輸與接收方標識為“來自BRI的Rc”及“到BRI的Tx”。表中的行表示時隙。這可從NIC(這里稱作“磚塊(brick)”)和從主機(這里稱作“承載體”)兩方面來看。如用行向比較指示與下面說明的,NIC時隙3與主機時隙19相同;NIC時隙4與主機時隙20;以此類推。表中的指示L1,L2與L3分別標識ISDN線路1、2與3、指示B1、B2與D分別指稱一條線路的第一B信道、第二B信道與D信道。Rc與Tx指示信道的接收與傳輸模型。從而,例如指示L1DRc指稱接收的ISDN線路1的D信道數(shù)據(jù)。在轉(zhuǎn)向圖5的實質(zhì)以前,應(yīng)理解所示的NIC利用S/T接口芯片25、26與27的緩沖存儲能力以便以最佳的序列輸出來自ISDN線路的B與D信道數(shù)據(jù)。從而,緩沖存儲來自ISDN線路的各信道的數(shù)據(jù)使得在總線幀中先傳送所有D信道數(shù)據(jù),后隨芯片B信道數(shù)據(jù)(它是在幀中間傳送的)。更具體地,ISDN線路25a(線1)、26a(線2)、及27a(線3)的S/T接口芯片緩沖存儲它們各自的D與它們的B信道數(shù)據(jù)(標記為B1與B2)以便在圖6中所示的幀的時隙4、5與6期間傳送D信道數(shù)據(jù),及在該幀的時隙16至21期間傳送B信道數(shù)據(jù)。從而,線路1的B信道數(shù)據(jù),即L1B1Rc、L1B2Rc、L1B1Tx及L1B2Tx是分別在幀的時隙16與17期間由S/T芯片25傳送的;線路2的B信道數(shù)據(jù),即L2B1Rc、L2B2Rc、L2B1Tx與L2B2Tx,是分別在幀的時隙18與19期間由S/T芯片26傳送的;而線路3的B信道數(shù)據(jù),即L3B1Rc、L3B2Rc、L3B1Tx與L3B2Tx是分別在幀的時隙20與21期間由S/T芯片27傳送的。當(dāng)然,在使用附加的ISDN線路的情況中,將用附加數(shù)據(jù)占用幀的附加時隙(即時隙22等等)。按照這一背景,B與D信道數(shù)據(jù)是由FPGA32的多路傳送器65、66與67按照圖5中的表選擇路由的。例如多路傳送器65將IDL總線35的“來自BRI的Rc”部分上L1B1Rc數(shù)據(jù)路由選擇到IDL總線35的“到360的Rc”部分上。從那里將數(shù)據(jù)發(fā)送到處理器28供接合。此后,將數(shù)據(jù)從處理器28傳輸?shù)絀DL總線35的“來自360的接合”部分,此后通過多路傳送器67將數(shù)據(jù)傳輸?shù)絀DL總線36的“到承載體的Rc”部分。從那里將L1B1Rc數(shù)據(jù)傳輸?shù)匠休d體卡70(主機),后者可包括用于處理數(shù)據(jù)的視頻卡之類。如圖5中所示,然后可將處理過的L1B1Tx從承載體卡70傳送給IDL總線36的“來自承載體的Tx”部分。然后,多路傳送器67將該數(shù)據(jù)傳輸給IDL總線35的“到BRI的Tx”部分,從那里將數(shù)據(jù)傳輸給適當(dāng)?shù)腟/T接口芯片(這里是芯片25)并從而到ISDN線路。針對圖5中所示的其它數(shù)據(jù)執(zhí)行類似的過程。在觀察了圖4與5時,容易理解多路傳送器的時變特性。如果在ISDN線路上的通信不是接合的,只在S/T芯片25—27正在將接收的D信道數(shù)據(jù)驅(qū)動到總線35上的時隙期間多路傳送器63是活躍的;當(dāng)這些芯片25—27正在驅(qū)動B信道數(shù)據(jù)到總線35上時多路傳送器67是活躍的;及當(dāng)28通信微處理器正在驅(qū)動D信道數(shù)據(jù)到IDL總線37上以及當(dāng)主機70正在驅(qū)動傳輸B信道數(shù)據(jù)到IDL總線36上時多路傳送器66是活躍的。如果ISDN線路上的通信是接合的,在S/T芯片正在驅(qū)動接收的D與B信道數(shù)據(jù)到IDL總線35上的時隙期間及當(dāng)主機70正在驅(qū)動傳輸?shù)腂信道數(shù)據(jù)到IDL總線36上時多路傳送器65是活躍的;當(dāng)通信微處理器28正在驅(qū)動不接合的B信道數(shù)據(jù)到IDL總線37上時多路傳送器67是活躍的;及當(dāng)通信微處理器28正在驅(qū)動傳輸?shù)腄信道數(shù)據(jù)到IDL總線37上時及當(dāng)它在驅(qū)動接合的B信道數(shù)據(jù)到總線37上時多路傳送器66是活躍的。如上所述,來自各ISDN線路的B信道數(shù)據(jù)是在圖5中所示的幀的時隙16等期間傳送的。然后主機的承載體卡70通常期望接收在各幀的第一時隙上開始的數(shù)據(jù)。從而,所示的系統(tǒng)提供主要為承載體卡并從而為主機重新定義何時幀開始的方法。更具體地,如上所述,IDL總線上的幀是由幀脈沖后隨32個時隙構(gòu)成的。NIC通過在時隙16上生成“人工”的幀脈沖,即與來自第一S/T接口芯片的B信道數(shù)據(jù)的輸出重合,重新定義圖5中所示的幀。可用諸如處理器28等電路生成這一人工幀脈沖。通過輸出這一“人工”幀脈沖來與時隙16重合,NIC主要將幀重新定義成使得新時隙0對應(yīng)于老時隙16,新時隙1對應(yīng)于老時隙17,等等(見圖5的“承載體時隙”列)。結(jié)果,如愿以償,承載體卡40接收具有在其時隙0上開始的B信道數(shù)據(jù)的重新定義的幀。當(dāng)然,可以輸出“人工”幀脈沖來與圖5中所示的任何時隙重合,只要這是對IDL總線及對承載體卡兩者都能接受的。沿這些線路,如果承載體卡并不關(guān)心數(shù)據(jù)位于幀中何處,則不需要提供任何重新定義。3.與主機并行傳送NIC20能在主機串行接口或主機并行接口上傳送數(shù)據(jù)。并行傳送是通過發(fā)布中斷到主機來實行的,后者執(zhí)行直接存儲器存取或其它塊數(shù)據(jù)傳送操作來向或從NICDRAM31傳送數(shù)據(jù)。與主機的并行傳送通常如上述進行。然而,與串行傳送不同,NIC與主機之間的數(shù)據(jù)傳送是由示出在圖3中虛線左方的塊I/O控制電路執(zhí)行的。更具體地,當(dāng)處理器28用接收的ISDN數(shù)據(jù)填充DRAM31時,它發(fā)送中斷(在圖中指示為INTerrupt)到主機,指示數(shù)據(jù)已準備好傳送。然后主機上的驅(qū)動器軟件(未示出)便能通過在耦合NIC與主機的輔助控制線上宣稱地址來起動塊傳送或DMA操作。其中包含在圖3中指示為CAR—ADDR、IORD~及IOWR~的線路。所示的FPGA32的元件45—61通過經(jīng)由ISA總線52與標記為CAR—DATA的主機接口線路向與自DRAM31中請求的位置傳送數(shù)據(jù)來響應(yīng)這一信令。在NIC20內(nèi),并行傳送是通過將所有B信道數(shù)據(jù)發(fā)送給處理器28(而更具體地DRAM31)來實行的,不管向/自ISDN線路傳送的數(shù)據(jù)是接合的還是不接合的形式的。從而,在數(shù)據(jù)是要接合的情況中,以所要求的方式執(zhí)行接合,然后將接合的B信道數(shù)據(jù)存儲在DRAM31中。反之,如果不要執(zhí)行接合,處理器28將不接合的B信道數(shù)據(jù)直接存到DRAM31中。最好將這種不接合的B數(shù)據(jù)存儲在對應(yīng)于ISDN線路與/或數(shù)據(jù)從其進來的信道的存儲區(qū)中。利用控制電路45—62來訪問存儲器31及控制處理器28與主機之間的數(shù)據(jù)交換。為達此目的,F(xiàn)PGA32包含控制通過數(shù)據(jù)總線46與處理器28交換數(shù)據(jù)的多路傳送器45。包含在FPGA32中的還有字節(jié)選擇多路傳送器47、讀/寫多路傳送器49、數(shù)據(jù)鎖存器50、及芯片配置鎖存器51。一般地說,這些部件控制總線46與接口到主機上的總線(即ISA總線52)之間的數(shù)據(jù)傳送。具體地,字節(jié)選擇多路傳送器47選擇要寫的字節(jié),而讀/寫多路傳送器49將所選擇的字節(jié)寫到數(shù)據(jù)鎖存器50,從那里將這些字節(jié)傳輸?shù)娇偩€54(并從而到處理28)或到總線52(并從而到主機)。芯片配置鎖存器51包含可以影響這種數(shù)據(jù)傳送的諸如定時信息之類的信息。地址信息是在地址總線56上提供的。這一總線用于提供從FPGA32訪問主機存儲器以及用于總線訪問的內(nèi)部寄存器解碼的多路傳送的地址。這些存儲器地址是通過內(nèi)部DMA(“直接存儲器存取”)地址寄存器57與59提供的。這便是,如圖中所示,DMA地址寄存器連接在ISA總線52(它本身連接在主機上的對應(yīng)總線上)上來通過多路傳送器50尋址總線56。如所示,還在FPGA中提供I/O地址解碼塊61與62,用于分別與處理器28及主機交換控制信號等。為了在并行數(shù)據(jù)傳送期間維護等時性,NIC可為ISDN線路所定義的各ISDN幀發(fā)送中斷到主機。作為替代,較不頻繁發(fā)出這些中斷信號,從而利用這一數(shù)據(jù)傳送形式的效率。為此目的,F(xiàn)PGA32(或NIC中其它電路)可計數(shù)已與B信道數(shù)據(jù)一起從FPGA32傳輸?shù)教幚砥?8的幀脈沖的數(shù)據(jù)并從而幀的數(shù)目。當(dāng)達到預(yù)定的計數(shù)時,F(xiàn)PGA或處理器28中的軟件可發(fā)送中斷到主機。在本發(fā)明的較佳實施例中,這一預(yù)定的計數(shù)(a.k.a.,“超級幀脈沖”)包括160個幀脈沖;但也可使用其它計數(shù)。數(shù)據(jù)傳送可由處理器28本身在中斷時執(zhí)行,而不是由主機通過DMA執(zhí)行。4.逆多路傳送(接合)逆多路傳送過程在接收來自ISDN線路的數(shù)據(jù)之前開始。具體地,為了開始,NIC20與主機(未示出)一起在一或多條ISDN線路上建立對另一網(wǎng)絡(luò)節(jié)點/端點(未示出)的呼叫。然后NIC20與另一節(jié)點協(xié)商在ISDN線路25a、26a與27a的哪些“B”信道上交換數(shù)據(jù)。這稱作逆多路傳送過程的協(xié)商階段。下面假定只在兩條“B”信道上交換數(shù)據(jù)。當(dāng)然,不一定非這樣不可。例如,數(shù)據(jù)可以在任何數(shù)目的“B”信道及任何數(shù)目的ISDN線路上交換。一旦完成了協(xié)商階段,便開始逆多路傳送進行的訓(xùn)練階段。在這一階段期間識別諸如信道間延時與信道交叉等逆多路傳送參數(shù)。在所示的實施例中,訓(xùn)練階段是由在處理器28(最好在SCC41)中執(zhí)行的計算機可執(zhí)行的進程步驟實現(xiàn)的;然而,本發(fā)明不限于此。這些進程步驟最好存儲在諸如存儲器30等存儲器中并包含代碼(i)存儲從各ISDN信道接收的包含幀計數(shù)在內(nèi)的數(shù)據(jù)在多個緩沖器中各自的一個中;(ii)通過比較存儲在它們各自的進入緩沖器指針上或附近的緩沖器中的幀計數(shù)來確定信道間的時延;(iii)通過比較緩沖存儲的數(shù)據(jù)中所包含的信道信息識別信道交叉;及(iv)以補償信道交叉及采用經(jīng)過偏移來補償信道間延時的外出指針的次序從緩沖器中讀出數(shù)據(jù)。更詳細地,SCC41以其透明的或QMC模型進行操作來跟蹤分配給各相應(yīng)ISDN信道的數(shù)據(jù)緩沖器的進入與外出指針(例如行計數(shù))。這些緩沖器可包含在存儲器31或其它任何地方中,但最好在NIC中。在所示的實施例中,SCC41示出為只跟蹤兩條信道的進入與外出指針。SCC41根據(jù)諸如處理器28基于從ISDN線路接收的幀脈沖生成的主幀計數(shù)的低14位設(shè)定各信道的進入指針。具體地,SCC41將各進入指針設(shè)定為各信道起動通信時的低14位的值上。此后,SCC41將從該信道接收的訓(xùn)練數(shù)據(jù)存儲在各自的進入指針所指示的位置或地址上。隨著每一次寫入到緩沖器中,增量該指針。訓(xùn)練數(shù)據(jù)包括在多信道通話中包含的網(wǎng)絡(luò)節(jié)點之間傳輸?shù)挠?xùn)練模型。在本發(fā)明的較佳實施例中,采用圖7中所示的格式的傳統(tǒng)的逆多路傳送訓(xùn)練模型;但應(yīng)指出本發(fā)明的不限于采用具有圖7中所示的特定配置的訓(xùn)練模型。傳統(tǒng)的逆多路傳送訓(xùn)練模型的更完整的描述可在“Nx56/54Kbps呼叫的互相協(xié)作性要求”,接合國際協(xié)議,版本1.0(1992年9月1日)中找到,這里通過引用將其內(nèi)容結(jié)合在本申請中,如同將其全文陳述在此。如圖7中所示,較佳訓(xùn)練模型包括一個幀校準字,后隨63字節(jié)數(shù)據(jù),一個信息信道報文,后隨63字節(jié)數(shù)據(jù),一個幀計數(shù),后隨63字節(jié)數(shù)據(jù),及一個CRC(檢錯)字節(jié)。利用幀校準字來確定各幀數(shù)據(jù)的校準,信息信道報文標識從其始發(fā)數(shù)據(jù)的信道,而幀計數(shù)包括當(dāng)前數(shù)據(jù)幀的相對號碼。NIC接收時,S/T接口芯片將各訓(xùn)練模型放置到IDL總線35上的幀的各自的時隙中。然后FPGA32中的多路傳送器65通過IDL總線35的“到360的Rc”信道將訓(xùn)練數(shù)據(jù)幀從各信道路由到SCC41。在此或稍后的時間上,處理器分析各時隙中的訓(xùn)練數(shù)據(jù)的信息信道報文以便確定網(wǎng)絡(luò)是否已將這些信道交叉。從而例如,如果處理器確定在信道1上接收到了對信道3期望的數(shù)據(jù),它便存儲在聚集期間在重新排序數(shù)據(jù)中使用的標識符。SCC41根據(jù)上面確定的進入指針將接收的數(shù)據(jù)存儲在各自的接收緩沖器中(如在存儲器31中指示的緩沖器)。這一方面,在本發(fā)明的較佳實施例中,處理器只允許寫到緩沖器內(nèi)的長字邊界上。從而,在建立給定的信道時,進入指針可能指示要將數(shù)據(jù)寫入接收緩沖器的不允許的邊界上。為了解決這一問題,SCC可等待一至三幀來將數(shù)據(jù)寫到接收緩沖器中,借此保證將數(shù)據(jù)寫到長字邊界上。隨著數(shù)據(jù)寫入各自的接收緩沖器中,處理器28確認其字節(jié)包含期望的訓(xùn)練數(shù)據(jù),即幀計數(shù)、信息信道報文等。此后,處理器利用幀計數(shù)來確定各信道的延時量。具體地,處理器根據(jù)在數(shù)據(jù)初始輸入到各緩沖器時不同時隙緩沖器中的幀計數(shù)之間的差來確定信道延時量。例如,在只在兩個信道上接收數(shù)據(jù)的最簡單的情況中,圖8示出兩個接收緩沖器81與82,每一信道一個。起初,這兩個緩沖器是空的,如圖8中所示。此后,按照輸入指針83數(shù)據(jù)從第一ISDN信道輸入到緩沖器81中,如圖9中所示。正在輸入這一數(shù)據(jù)時,開始用來自第二ISDN信道的數(shù)據(jù)填充緩沖器82。如圖10中所示,按照輸入指針84填充緩沖器82。從圖10中顯而易見,由于在增量指針及寫入緩沖器中的SCC延時而兩個輸入指針可能會沒校準;然而它們通常以基本相同的速率前進通過它們各自的緩沖器。從而,基本上以相同的速率填充這兩個緩沖器81與82,如圖11中所示。一旦訓(xùn)練階段過去及多信道通話的實質(zhì)部分開始,可用補償信道間延時的方式從緩沖器中讀出通話數(shù)據(jù)。為此目的,所示的系統(tǒng)按下式確定延時△△=buffery(Iy)-bufferx(Ix)-(Iy-Ix)(1)其中bufferx(Ix)包括緩沖器81的外出指針上的幀計數(shù),buffery,(Iy)包括緩沖器82的外出指針上的幀計數(shù),而其中Ix與Iy分別包括緩沖器81與82中的指針值。應(yīng)指出上面式(1)中所確定的差是相對于0到64的標度,而不是正常的十進制標度的。按照這一標度例如0-1=63而不是-1。從而,對于圖12中所示實例,延時△確定如下△=9-63-(1046-1043)(2)它得出7。當(dāng)然,在不止只有兩個信道緩沖器的情況中,上文中的差是在各緩沖器與一個諸如緩沖器81等選擇的“基準”緩沖器之間確定的。如圖12中所示,這一△7包括兩個緩沖器中在諸如1043(即6-63)等單一指針值上的數(shù)據(jù)之間的差。一旦確定了這一信道間延時,SCC41利用這一值來位移SCC用來在總通話期間從緩沖器中讀出數(shù)據(jù)的外出指針。具體地,通過將幀之間的延時量加在該緩沖器的選擇的外出指針上來確定各非基準緩沖器的外出緩沖器指針。從數(shù)學(xué)上陳述,緩沖器y的外出指針Oy確定如下Oy=Ox-△(3)從而,參見圖12,假定緩沖器81是緩沖器x,并知道根據(jù)上式(2)延時△為7,及緩沖器81的外出指針Ox為1043,便有可能通過從1043中減去△(在本例中為7)來確定緩沖器82(即緩沖器y)的第一外出指針。如圖12中所示,這對應(yīng)于指針1036,這與緩沖器1中的指針1043一樣,指向值“63”。此后,將分別從1043與1036開始的緩沖器81與82的外出指針增量從而以基本上相同的速率輸出數(shù)據(jù)。一旦在訓(xùn)練階段中這樣確定了初始外出指針值,然后在訓(xùn)練階段后面便可用這些外出指針從緩沖器中讀出數(shù)據(jù)。必要時,還重新排序用計算出的外出指針從接收緩沖器中讀出的數(shù)據(jù)來校正任何“信道交叉”。這是最好通過在從緩沖器中輸出期間將特定信道的數(shù)據(jù)存儲到輸出緩沖器中的特定區(qū)域中來完成的。這一輸出緩沖器可位于諸如存儲器31中,或者它可以是處理器28內(nèi)部的。通過IDL總線35(標記為其“來自360的連接的”部分)與FPGA32將數(shù)據(jù)從這一輸出緩沖器傳輸?shù)街鳈C。上文描述了在從ISDN線路上接收的數(shù)據(jù)上執(zhí)行的逆多路傳送。也可在要由處理器28傳輸給ISDN線路的數(shù)據(jù)上按照本發(fā)明執(zhí)行多路傳送。具體地,在這一上下文中,多路傳送包括分段或分裂數(shù)據(jù)以便能在一條以上ISDN線路上傳輸它。為了實現(xiàn)這一點,NIC20可將數(shù)據(jù)分成多條信道的數(shù)據(jù)。然后,將這一數(shù)據(jù)存儲到各信道的各自的傳輸緩沖器中(即上述配套的接收緩沖器)。然后在IDL總線35上將數(shù)據(jù)從傳輸緩沖器讀出到FPGA上,最終從那里將其傳輸?shù)讲煌腎SDN線路上。5.軟件體系結(jié)構(gòu)在本發(fā)明的較佳實施例中在處理器28上執(zhí)行若干軟件任務(wù)來實現(xiàn)接合。圖14中示出這些任務(wù)的功能圖。接合任務(wù)90提供接合進程的總體控制。它處理建立、回答、協(xié)商、交叉連接及與呼叫處理任務(wù)91的交互作用。接合360任務(wù)92接收來自接合任務(wù)90的否則會傳輸給數(shù)字信號處理器(“DSP”)的報文。然后接合360任務(wù)92協(xié)調(diào)報文處理,初始化SCC信道,執(zhí)行幀狀態(tài)機,生成及接收訓(xùn)練與協(xié)商模型,計算幀相位延時,以及建立DMA來提供相位補償。接合360任務(wù)在報文隊列上等待報文。支持兩種類型的報文接合定時報文及從接合任務(wù)90到“DSP”的報文(在本例中不使用它)。接合定時報文是接合360任務(wù)起動的周期報文。利用這些報文來初始化按照本發(fā)明實現(xiàn)接合所需的“后臺”進程。搜索主信道幀,訓(xùn)練模型幀,主校準狀態(tài)機是響應(yīng)這一報文執(zhí)行的。這些報文本身不包含信息。接收該報文后,接合360任務(wù)重新起動定時器。接合任務(wù)DSP報文包括發(fā)送給控制狀態(tài)機來實現(xiàn)接合的報文。在本發(fā)明的這一實現(xiàn)中,這些報文是在稱作ProcessBondMessage()的函數(shù)中處理的。這些報文的處理檢驗該報文對信道的當(dāng)前狀態(tài)是否有效。對于各報文,采取適當(dāng)行動并更新信道狀態(tài)。下面的表1列出所有受支持的報文。所有其它報文被忽略。表1QMC模型中處理器28的透明信道便于按照本發(fā)明的接合。按照本發(fā)明,獨立起動各信道并保持16個DMA的相位校準(8個B信道中每信道兩個)。稱作StartChannel的函數(shù)執(zhí)行這一服務(wù)。StartChannel函數(shù)使用定時器處理器28來計數(shù)TDM總線幀。在起動信道時用這一計數(shù)來同步它們。在起動信道時,系統(tǒng)從定時器取得當(dāng)前計數(shù)并將其屏蔽到14位。然后利用這一值以上述方式計算Tx與Rx緩沖器內(nèi)的起點。處理器28要求接收緩沖器的起始地址在4的倍數(shù)的長字邊界上。因此,將為這一標準調(diào)節(jié)實際起始計數(shù),而在起動信道之前系統(tǒng)將等待直到定時器到達這一調(diào)節(jié)后的計數(shù)為止。關(guān)于這一方面,能在任何字節(jié)邊界上起動TxDMA。在圖15中所描繪的下面的實例中,為接合進程的主信道協(xié)商與/或訓(xùn)練階段起動兩條信道。信道1當(dāng)起動信道1時,幀同步計數(shù)器(定時器4)包含值Ox4122。將這一值向上歸整到Ox4124并屏蔽到14位以產(chǎn)生緩沖器起動偏移Ox0124。然后StartChannel函數(shù)等待直到幀同步計數(shù)器達到這一值并起動DMA。信道2當(dāng)起動信道2時,幀同步計數(shù)器(定時器4)包含值Ox4578。這一值也是4的倍數(shù);然而,由于不知道正在處理的時隙,必須等待到與幀同步脈沖校準。當(dāng)幀同步計數(shù)器成為Ox4579時出現(xiàn)這一情況。為了使這一值是4的倍數(shù)需要將其向上歸整到Ox457C。然后將這一值屏蔽到14位以產(chǎn)生緩沖器起動位移值Ox57C。然后StartChannel函數(shù)等待到幀同步計數(shù)到達這值并起動DMA。由于信道1的DMA現(xiàn)在偏移到Ox57C上,兩個信道將是同步的。在圖16中所描繪的以下實例中,在已確定了相位補償之后起動兩個信道。信道1當(dāng)起動信道1時,幀同步計數(shù)器(定時器4)包含值Ox4122。將這一值向上歸整到Ox4124并將其屏蔽到14位以產(chǎn)生接收器的緩沖器起動偏移Ox124。由于處理器28內(nèi)的操作次序,首先必須將Tx與RxDMA偏移至少兩個長字(8個字節(jié))。因此,如果檢測到相位延時零,必須加上偏移8。通過從起動Rx偏移中減去計算的相位延時加8計算出Tx起動緩沖器偏移。對于這一實例,信道1上的計算的相位延時為2。因此,Tx偏移為Ox334A。信道2當(dāng)起動信道2時,幀同步計數(shù)器(定時器4)包含值Ox0248。對于這一實例,信道2上的計算的相位延時為零。因此,Tx偏移為Ox244而Rx偏移為Ox24C。由于信道1上的TxDMA偏移10(8為SCP而2為相位延時)而信道2上的信道TxDMA偏移了8,將產(chǎn)生兩幀的相對延時(即10-8=2)。在附件中提出實現(xiàn)本發(fā)明的較佳實施例的計算機代碼。參照具體的示例性實施例描述了本發(fā)明。應(yīng)理解本發(fā)明不限于上述實施例及其修正,本技術(shù)中的普通技術(shù)人員可以作出各種改變與修正而不脫離本發(fā)明的精神與范圍。從而,例如應(yīng)理解本發(fā)明的不限于在IDL總線上傳輸?shù)哪娑嗦穫魉蛿?shù)據(jù),而是可用于逆多路傳送在其它類似總線的主機上傳輸?shù)臄?shù)據(jù)。此外,應(yīng)理解本發(fā)明不限于圖中所示及上面描述的特定定時序列。更進一步,應(yīng)理解本發(fā)明能用于更少、更多、或不同類型與數(shù)目的ISDN信道、S/T芯片、緩沖器、及微處理器。<prelisting-type="program-listing"><![CDATA[/*******************************************************************************************Filebndchan.cDateApril20,1996****(C)Copyright1997byVideoServerInc.**AllRightsReserved**EngineerDaveOliveira****DescriptionThefilecontainscodetosupportBondingonthe**68MH360*******************************************************************************************//*****************************************************************************************IncludeFiles*****************************************************************************************/#include<string.h>#include"codestd.h"#include"devkit.h"#include"imux_db.h"#include"bndqmc.h"/*****************************************************************************************ExternalData*****************************************************************************************/externChannelDataChanData[MAX_BOND_CHANNELS];externvolatileUint32TimerTicks;externUint32Where[];/*****************************************************************************************GlobalData*****************************************************************************************/PUBLICUint32ulTxinit=250;PUBLICUint32ulTxfa=250;PUBLICUint32ulTxadd01=500;PUBLICUint32ulTxdeq=350;PUBLICUint32ulTxadd02=500;PUBLICUint32ulTxadd=250;PUBLICUint32ulTxdel=250;PUBLICUint32ulTxdisc=250;PUBLICUint32ulTxnull=500;PUBLICUint32ulTCID=250;/*****************************************************************************************FunctionPrototypes*****************************************************************************************/PRIVATEvoidAnswerState(Int16wPhysChan);PRIVATEvoidMasterState(Int16wPhysChan);PRIVATEvoidNoSyncState(Int16wPhysChan);PRIVATEvoidTrainingState(Int16wPhysChan);PRIVATEvoidLearningState(Int16wPhysChan);PRIVATEBooleanNegoiationComplete(Int16wPhysChan);/*****************************************************************************************RoutineNameBond360ChannelState()****DescriptionThisfunctioniscalledwhentheperiodicbondingtimer**expires.Weprocessthestatemachineshere.****ParameterswPhysChan(I)Thechannelnumberofthechanneltoprocess****ReturnValueN/A*************************************************************************************************/PUBLICvoidBond360ChannelState(Int16wPhysChan){switch(ChanData[PhysToBuff(wPhysChan)].ubChanState){caseCS_NULLbreak;caseCS_ANSWERAnswerState(wPhysChan);break;caseCS_MASTERMasterState(wPhysChan); break; caseCS_NOSYNC NoSyncState(wPhysChan); break; caseCS_NEGODONE /*Nothingtodointhisstate*/ break; caseCS_TRAINING TrainingState(wPhysChan); break; caseCS_LEARNING LearningState(wPhysChan); break; caseCS_ALIGN break; }}/************************************************************************************************RoutineNameSetChannelTimer()****DescriptionThisfunctionsetsthetimerforachanneltoanew**expirationvalue.****ParameterswPhysChan(I)Thechannelnumberofthechanneltoprocess**ulTicks(I)Thenumberoftimertickstowait****ReturnValueN/A***************************************************************************************************/PUBLICvoidSetChannelTimer(Int16wPhysChan,Uint32ulTicks){ if(ulTicks?。?){ ulTicks=TimerTicks+ulTicks; if(ulTicks==0){ ulTicks=1; } } ChanData[PhysToBuff(wPhysChan)].ulTimer=ulTicks;}/************************************************************************************************RoutineNameCheckChannelTimer()****DescriptionThisfunctionchecksifthetimerforachannelhasexpired****ParameterswPhysChan(I)Thechannelnumberofthechanneltoprocess****ReturnValueTRUEThetimerhasexpired**FALSEThetimerisstillrunning**************************************************************************************************/PUBLICBooleanCheckChannelTimer(Int16wPhysChan){ registerInt16wBuffChan; /*-----------------------------------------------------------------------------------------* *Thetimerhasexpiredifthealloffollowingaretrue* *1.Thetimerisactive,i.e.thetimervalueisnotzero* *2.Thetimervalueandthecurrenttickcountbothhavethesame* *msb.* *3.TheTickcountisgreaterthanorequaltothetimervalue.* *-----------------------------------------------------------------------------------------*/ wBuffChan=PhysToBuff(wPhysChan); return((Boolean)((ChanData[wBuffChan].ulTimer?。?)&& (((TimerTicks^ChanData[wBuffChan].ulTimer)&0x80000000)==0)&& (TimerTicks>=ChanData[wBuffChan].ulTimer)));}/************************************************************************************************RoutineNameAnswerState()****DescriptionThisfunctioniscalledwhenthechannelisinthe**CS_ANSWERstate.****ParameterswPhysChan(I)Thechannelnumberofthechanneltoprocess****ReturnValueN/A**************************************************************************************************/PRIVATEvoidAnswerState(Int16wPhysChan){ registerInt16wBuffChan; /*-----------------------------------------------------------------------------------------------------------* *CheckforMasterChannelFraming* *-----------------------------------------------------------------------------------------------------------*/ wBuffChan=PhysToBuff(wPhysChan); if(IC_Sync(wPhysChan)){ ChanData[wBuffChan].ubChanState=CS_MASTER; SetChannelTimer(wPhysChan,ulTxinit); } /*-----------------------------------------------------------------------------------------------------------* *CheckforMulti-Frame* *-----------------------------------------------------------------------------------------------------------*/ elseif(MF_Sync(wPhysChan)){ ChanData[wBuffChan].ubChanState=CS_TRAINING; ChanData[wBuffChan].ulTimer=0; ChanData[wBuffChan].ubPxChanId= (ChanData[wBuffChan].ubIC_Last[1]>>1)&0x3F; } /*-----------------------------------------------------------------------------------------------------------* *CheckForTimeout* *-----------------------------------------------------------------------------------------------------------*/ elseif(CheckChannelTimer(wPhysChan)){ PostInfoMsg(wPhysChan,MCA_InSync,TimeoutError); TerminateChannel(wPhysChan); }}/**********************************************************************************************************************RoutineNameMasterState()****DescriptionThisfunctioniscalledwhenthechannelisinthe**CS_MASTERstate.****ParameterswPhysChan(I)Thechannelnumberofthechanneltoprocess****ReturnValueN/A************************************************************************************************************************/PRIVATEvoidMasterState(Int16wPhysChan){ registerInt16wBuffChan;/*---------------------------------------------------------------------------------------------------------------* *CheckforMasterChannelMessages* *---------------------------------------------------------------------------------------------------------------*/ wBuffChan=PhysToBuff(wPhysChan); if(IC_Sync(wPhysChan)){ if{NegoiationComplete(wPhysChan)){ ChanData[wBuffChan].ubChanState=CS_NOSYNC; SetChannelTimer(wPhysChan,ulTxadd01); }else{ SetChannelTimer(wPhysChan,ulTxinit); } } /*-----------------------------------------------------------------------* *CheckForTimeout* *-----------------------------------------------------------------------*/ elseif(CheckChannelTimer(wPhysChan)){ PostInfoMsg(wPhysChan,MCA_InitSync,TimeoutError); TerminateChannel(wPhysChan); }}/******************************************************************************RoutineNameNoSyncState()****DescriptionThisfunctioniscalledwhenthechannelisinthe**CS_NOSYNCstate.****ParameterswPhysChan(I)Thechannelnumberofthechanneltoprocess****ReturnValueN/A********************************************************************************/PRIVATEvoidNoSyncState(Int16wPhysChan){ registerInt16wBuffChan; /*-----------------------------------------------------------------------* *CheckforMasterChannelMessages* *-----------------------------------------------------------------------*/ wBuffChan=PhysToBuff(wPhysChan); IC_Sync(wPhysChan); if(ChanData[wBuffChan].ubIC_State==IC_NOSYNC){ PostInfoMsg(wPhysChan,MCA_InitSync,SyncLossError); ChanData[wBuffChan].ubChanState=CS_NEGODONE; ChanData[wBuffChan].ulTimer=0; } /*-----------------------------------------------------------------------* *CheckForTimeout* *-----------------------------------------------------------------------*/ elseif(CheckChannelTimer(wPhysChan)){ PostInfoMsg(wPhysChan,MCA_InitSync,TimeoutError); TerminateChannel(wPhysChan); }}/******************************************************************************RoutineNameTrainingState()****DescriptionThisfunctioniscalledwhenthechannelisinthe**CS_TRAININGstate.****ParameterswPhysChan(I)Thechannelnumberofthechanneltoprocess****ReturnValueN/A*******************************************************************************/PRIVATEvoidTrainingState(Int16wPhysChan){ registerInt16wBuffChan; /*------------------------------------------------------------------------* *CheckforMulti-Frame* *------------------------------------------------------------------------*/ if(MF_Sync(wPhysChan)){ wBuffChan=PhysToBuff(wPhysChan); ChanData[wBuffChan].ubChanState=CS_LEARNING; ChanData[wBuffChan].ulTimer=0; ChanData[wBuffChan].ubRxChanId= (ChanData[wBuffChan].ubIC_Last[1]>>1)&0x3F; } /*------------------------------------------------------------------------* *CheckForTimeout* *------------------------------------------------------------------------*/ elseif(CheckChannelTimer(wPhysChan)){ PostInfoMsg(wPhysChan,MCA_InSync,TimeoutError); TerminateChannel(wPhysChan); }}/*******************************************************************************RoutineNameLearningState()****DescriptionThisfunctioniscalledwhenthechannelisinthe**CS_LEAPNINGstate.****ParameterswPhysChan(I)Thechannelnumberofthechanneltoprocess****ReturnValueN/A*********************************************************************************/PRIVATEvoidLearningState(Int16wPhysChan){ /*------------------------------------------------------------------------* *CheckForTimeout* *------------------------------------------------------------------------*/ MF_Sync(wPhysChan); if(CheckChannelTimer(wPhysChan)){ PostInfoMsg(wPhysChan,MCA_InSync,TimeoutError); TerminateChannel(wPhysChan); }}/*******************************************************************************RoutineNameNegoiationComplete()****DescriptionThisfunctionchecksifthenegoiationonamasterchannel**hascompleted.****ParameterswChannel(I)Thechannelnumberofthechanneltoprocess****ReturnValueTRUENegoiationhascompleted**FALSENegoiationisstillinprogress.********************************************************************************/PRIVATEBooleanNegoiationComplete(Int16wPhysChan){ registerInt16wBuffChan; wBuffChan=PhysToBuff(wPhysChan); return(((ChanData[wBuffChan].ubIC_Last[1]>>1)&0x3F)!=0);}/*************************************************************************************************Filebndmsg.cDateApril20,1996****(C)Copyright1997byVideoServerInc.**AllRightsReserved**EngineerDaveOliveira****DescriptionThefilecontainscodetosupportBondingonthe**68MH360************************************************************************************************//**********************************************************************************************IncludeFiles**********************************************************************************************/#include<string.h>#include"codestd.h"#include"devkit.h"#include"imux_db.h"#include"bndqmc.h"/***********************************************************************************************LocalDefines***********************************************************************************************/#defineTX_NULL_EXTENSION250/***********************************************************************************************ExternalData***********************************************************************************************/externUint32BondBuffer[MAX_BOND_CHANNELS][MAX_DIE][MAX_BUFFER_LONGS];externChannelDataChanData[MAX_BOND_CHANNELS];externSessionDataSessions[MAX_BOND_SESSIONS];externUint32Where[];externUint32ulTxinit;externUint32ulTxfa;externUint32ulTxadd01;externUint32ulTxdeq;externUint32ulTxadd02;externUint32ulTxadd;externUint32ulTxdel;externUint32ulTxdisc;externUint32ulTxnull;externUint32ulTCID;/***********************************************************************************************FunctionPrototypes***********************************************************************************************/PRIVATEvoidChanNull(IMUXMsg*pMsg);PRIVATEvoidChanAnswer(IMUXMsg*pMsg);PRIVATEvoidChanMaster(IMUXMsg*pMsg);PRIVATEvoidChanTraining(IMUXMsg*pMsg);PRIVATEvoidChanLearning(IMUXMsg*pMsg);PRIVATEvoidChanAlign(IMuXMsg*pMsg);/*******************************************************************************RoutineNameProcessBondMsg()****DescriptionThisfunctioniscalledwhentheperiodicbondingtimer**expires.Weprocessthestatemachineshere.****parametersNone****ReturnValueN/A*********************************************************************************/PUBLICvoidProcessBondMsg(IMUXMsg*pMsg){ switch(ChanData[PhysToBuff(pMsg->IMUXData.DspMsg.ubDs0)].ubChanState){ caseCS_NULL ChanNull{pMsg); break; caseCS_ANSWER ChanAnswer(pMsg); break; caseCS_MASTER caseCS_NOSYNC caseCS_NEGODONE ChanMaster(pMsg); break; caseCS_TRAINING ChanTraining(pMsg); break; caseCS_LEARNING ChanLearning(pMsg); break; caseCS_ALIGN ChanAlign(pMsg); break; }}/*******************************************************************************RoutineNameChanNull()****DescriptionThisfunctioniscalledwhenthechannelisinthe**CS_NULLstateandaBondingDspMsgissentbytheBonding**Task.****ParameterspMsg(I)Themessagetobeprocessed.****ReturnValueN/A*******************************************************************************/PRIVATEvoidChanNull(IMUXMsg*pMsg){ Int16wStatus; Int16wPhysChan; Int16wBuffChan; /*------------------------------------------------------------------------------------* *InitializeVariables* *------------------------------------------------------------------------------------*/ wStatus=SUCCESSFUL; wPhysChan=pMsg->IMUXData.DspMsg.ubDs0; wBuffChan=PhysToBuff(wPhysChan); /*------------------------------------------------------------------------------------* *ProcessMessage* *------------------------------------------------------------------------------------*/ switch(pMsg->IMUXData.DspMsg.ubPrimcode){ caseMCA_AnswerCall memset((Uint8*)&ChanData[wBuffChan],0,sizeof(ChannelData)); memset((Uint8*)BondBuffer[wBuffChan][RX_BUFFER],0,BUFFER_BYTES); StartChannel(wPhysChan, (Uint8*)BondBuffer[wBuffChan][RX_BUFFER], (Uint8*)BondBuffer[wBuffChan][TX_BUFFER],0); GenBufferNego{wPhysChan,(Uint8*)&pMsg->IMUXData.DspMsg.data.info); ChanData[wBuffChan].ubInterface=pMsg->IMUXData.DspMsg.ubInterface; ChanData[wBuffChan].ubSession=pMsg->IMUXData.DspMsg.ubSession; ChanData[wBuffChan].ubDS0=pMsg->IMuXData.DspMsg.ubDs0; SetChannelTimer(wPhysChan,ulTxnull); ChanData[wBuffChan].ubChanState=CS_ANSWER; break; caseMCA_InitCall memset((Uint8*)&ChanData[wBuffChan],0,sizeof(ChannelData)); memset((Uint8*)BondBuffer[wBuffChan][RX_BUFFER],0,BUFFER_BYTES); StartChannel(wPhysChan, (Uint8*)BondBuffer[wBuffChan][RX_BUFFER], (Uint8*)BondBuffer[wBuffChan][TX_BUFFER],0); GenBufferNego(wPhysChan,(Uint8*)&pMsg->IMuXData.DspMsg.data.info); ChanData[wBuffChan].ubInterface=pMsg->IMUXData.DspMsg.ubInterface; ChanData[wBuffChan].ubSession=pMsg->IMUXData.DspMsg.ubSession; ChanData[wBuffChan].ubDS0=pMsg->IMUXData.DspMsg.ubDs0; SetChannelTimer(wPhysChan,ulTxnull); ChanData[wBuffChan].ubChanState=CS_MASTER; break; caseMCA_Begin_Training memset((Uint8*)&ChanData[wBuffChan],0,sizeof(ChannelData)); memset((Uint8*)BondBuffer[wBuffChan][RX_BUFFER],0,BUFFER_BYTES); startChannel(wPhysChan, (Uint8*)BondBuffer[wBuffChan][RX_BUFFER], (Uint8*)BondBuffsr[wBuffChan][TX_BUFFER],0); GenBufferTraining(wPhysChan,(Uint8*)&pMsg->IMUXData.DspMsg.data.info,0,0); ChanData[wBuffChan].ubInterface=pMsg->IMUXData.DspMsg.ubInterface;ChanData[wBuffChan].ubSession=pMsg->IMUXData.DspMsg.ubSession; ChanData[wBuffChan].ubDS0=pMsg->IMUXData.DspMsg.ubDs0; SetChannelTimer(wPhysChan,ulTxnull+TX_NULL_EXTENSION); ChanData[wBuffChan].ubChanState=CS_TRAINING; break; caseMCA_Align wStatus=ERROR_INVALID_MSG_STATE; /*NoBreak,F(xiàn)allintonextcase*/ caseMCA_Term_Channel TerminateChhannel(wPhysChan); break; defaultbreak; }}/*******************************************************************************RoutineNameChanAnswer()****DescriptionThisfunctioniscalledwhenthechannelisinthe**Cs_ANSWERstateandaBondingDspMsgissentbytheBonding**Task.****ParameterspMsg(I)Themessagetobeprocessed.****ReturnValueN/A*********************************************************************************/PRIVATEvoidChanAnswer(IMUXMsg*pMsg){ Int16wStatus; Int16wPhysChan; /*------------------------------------------------------------------------* *InitializeVariables* *------------------------------------------------------------------------*/wStatus=SUCCESSFUL;wPhysChan=pMsg->IMUXData.DspMsg.ubDs0;/*-------------------------------------------------------------------------* *ProcessMessage* *-------------------------------------------------------------------------*/switch(pMsg->IMUXData.DspMsg.ubPrimcode){ caseMCA_Align caseMCA_InitCall caseMCA_Begin_Training wStatus=ERROR_INVALID_MSG_STATE; /*NoBreak,F(xiàn)allintonextcase*/ caseMCA_Term_Channel TerminateChannel(wPhysChan); break;caseMCA_AnswerCall /*Ignore*/ break; default break; }}/******************************************************************************RoutineNameChanMaster()****DescriptionThisfunctioniscalledwhenthechannelisinthe**CS_MASTERstateandaBondingDspMsgissentbytheBonding**Task.****ParameterspMsg(I)Themessagetobeprocessed.****ReturnValueN/A********************************************************************************/PRIVATEvoidChanMaster(IMUXMsg*pMsg){ Int16wStatus; Int16wPhysChan; Int16wBuffChan; /*-----------------------------------------------------------------------* *InitializeVariables* *-----------------------------------------------------------------------*/ wStatus=SUCCESSFUL; wPhysChan=pMsg->IUXData.DspMsg.ubDs0; wBuffChan=PhysToBuff(wPhysChan); /*------------------------------------------------------------------------* *ProcessMessage* *------------------------------------------------------------------------*/ switch(pMsg->IMUXData.DspMsg.ubPrimcode){ caseMCA_InitCall GenBufferNego(wPhysChan,(Uint8*)&pMsg->IMUXData.DspMsg.data.info); ChanData[wBuffChan].ubInterface=pMsg->IMUXData.DspMsg.ubInterface; ChanData[wBuffChan].ubSession=pMsg->IMUXData.DspMsg.ubSession; ChanData[wBuffChan].ubDS0=pMsg->IMUXData.DspMsg.ubDs0; SetChannelTimer(wPhysChan,ulTxinit); break; caseMCA_Begin_Training memset(ChanData[wBuffChan].ubIC_Frame,0,3*16); memset(ChanData[wBuffChan].ubIC_Last,0,16); GenBufferTraining(wPhysChan,(Uint8*)&pMsg->IMUXData.DspMsg.data.info,0,0); ChanData[wBuffChan].ubInterface=pMsg->IMUXData.DspMsg.ubInterface; ChanData[wBuffChan].ubSession=pMsg->IMUXData.DspMsg.ubSession; ChanData[wBuffChan].ubDS0=pMsg->IMUXData.DspMsg.ubDs0;ChanData[wBuffChan].ubIC_BuffIndex=0; SetChannelTimer(wPhysChan,ulTxnull+TX_NULL_EXTENSION); ChanData[wBuffChan].ubChanstate=CS_TRAINING; break;caseMCA_Align; caseMCA_AnswerCall wStatus=BRRORINVALID_MSG_STATE; /*NoBreak,F(xiàn)allintonextcase*/ caseMCA_Term_Channel TerminateChannel(wPhysChan); break; default break; }}/************************************************************************************RoutineNameChanTraining()****DescriptionThisfunctioniscalledwhenthechannelisinthe**CS_TRAININGstateandaBondingDspMsgissentbytheBonding**Task.****ParameterspMsg(I)Themessagetobeprocessed.****ReturnValueN/A************************************************************************************/PRIVATEvoidChanTraining(IMUXMsg*pMsg){ Int16wStatus; Int16wPhysChan; Int16wBuffChan; /*-----------------------------------------------------------------------------* *InitializeVariables* *-----------------------------------------------------------------------------*/ wStatus=SUCCESSFUL; wPhysChan=pMsg->IMUXData.DspMsg.ubDs0; wBuffChan=PhysToBuff(wPhysChan); /*-----------------------------------------------------------------------------* *ProcessMessage* *-----------------------------------------------------------------------------*/ switch(pMsg->IMUXData.DspMsg.ubPrimcode){ caseMCA_Begin_Training memset(ChanData[wBuffChan].ubIC_Frame,0,3*16); memset(ChanData[wBuffChan].ubIC_Last,0,16); GenBufferTraining(wPhysChan,(Uint8*)&pMsg->IMUXData.DspMsg.data.info,0,0); ChanData[wBuffChan].ubInterface=pMsg->IMUXData.DspMsg.ubInterface;ChanData[wBuffChan].ubSession=pMsg->IMUXData.DspMsg.ubSession; ChanData[wBuffChan].ubDS0=pMsg->IMUXData.DspMsg.ubDs0; ChanData[wBuffChan].ubIC_BuffIndex=0; SetChannelTimer(wPhysChan,ulTxnull+TX_NULL_EXTENSION); break; caseMCA_Align caseMCA_AnswerCall caseMCA_InitCall wStatus=ERROR_INVALID_MSG_STATE; /*NoBreak,F(xiàn)allintonextcase*/ caseMCA_Term_Channel TerminateChannel(wPhysChan); break; default break; }}/***********************************************************************************************RoutineNameChanLearning()****DescriptionThisfunctioniscalledwhenthechannelisinthe**CS_LEARNINGstateandaBondingDspMsgissentbytheBonding**Task.***ParameterspMsg(I)Themessagetobeprocessed.****ReturnValueN/A************************************************************************************************/PRIVATEvoidChanLearning(IMUXMsg*pMsg){ Int16wStatus; Int16wPhysChan; Uint8ubSession; /*----------------------------------------------------------------------------------------* *InitializeVariables* *----------------------------------------------------------------------------------------*/ wStatus=SUCCESSFUL; wPhysChan=pMsg->IMUXData.DspMsg.ubDs0; /*----------------------------------------------------------------------------------------* *ProcessMessage* *----------------------------------------------------------------------------------------*/ switch(pMsg->IMUXData.DspMsg.ubPrimcode){ caseMCA_InitCa11 caseMCA_AnswerCall caseMCA_Begin_Training wStatus=ERROR_INVALID_MSG_STATE; /*NoBreak,F(xiàn)allintonextcase*/caseMCA_Term_Channel TerminateChannel(wPhysChan); break; caseMCA_Align ubSession=pMsg->IMUXData.DspMsg.ubSession; Sessions[ubSession].ubState=AS_RMT_STATE; Sessions[ubSession].wBaseChan=wPhysChan; break; default break; }}/******************************************************************************RoutineNameChanAlign()****DescriptionThisfunctioniscalledwhenthechannelisinthe**CS_ALIGNstateandaBondingDspMsgissentbytheBonding**Task.****ParameterspMsg(I)Themessagetobeprocessed.****ReturnValueN/A********************************************************************************/PRIVATEvoidChanAlign(IMUXMsg*pMsg){ Int16wStatus; Int16wPhysChan; /*-----------------------------------------------------------------------* *InitializeVariables* *-----------------------------------------------------------------------*/ wStatus=SUCCESSFUL; wPhysChan=pMsg->IMUXData.DspMsg.ubDs0; /*-----------------------------------------------------------------------* *ProcessMessage* *-----------------------------------------------------------------------*/ switch(pMsg->IMUXData.DspMsg.ubPrimcode){ caseMCA_Align caseMCA_InitCall caseMCA_AnswerCall caseMCA_Begin_Training wStatus=ERROR_INVALID_MSG_STATE; /*NoBreak,F(xiàn)allintonextcase*/ caseMCA_Term_Channel TerminateChannel(wPhysChan); break; defaultbreak; }}/************************************************************************************RoutineNameTerminateChannel()****DescriptionThisfunctioniscalledwhentheaterminatechannelmsg**isreceived.****ParameterswPhysChan(I)Thechannelnumberofthechanneltoprocess****ReturnValueN/A**************************************************************************************/PUBLICvoidTerminateChannel(Int16wPhysChan){ Int16wBuffChan; Uint8ubSession; BooleanboSessionDone; wBuffChan=PhysToBuff(wPhysChan); Bond360_RestoreChannel(wPhysChan); ubSession=ChanData[wBuffChan].ubSession; memset(&ChanData[wBuffChan],0,sizeof(ChannelData)); boSessionDone=TRUE; for(wBuffChan=0;wBuffChan<MAX_BOND_CHANNELS;wBuffChan++){ if((ChanData[wBuffChan].ubSession==ubSession)&& (ChanData[wBuffChan].ubChanState?。紺S_NULL)){ boSessionDone=FALSE; } } if(boSessionDone){ memset(&Sessions[ubSession],0,sizeof(SessionData)); }}*********************************************************************************************** ** *Filebndqmc.cDateApril20,1996* ** *(C)Copyright1997byVideoServerInc.* *AllRightsReserved* *EngineerDaveOliveira* ** *DescriptionThefilecontainscodetosupportBondingonthe* *68MH360* ** **********************************************************************************************//********************************************************************************************** *IncludeFiles* **********************************************************************************************/#include"codestd.h"#include"flags.h"#include"compiler.h"#include"gendef.h"#include"tune.h"#include"lif.h"#include"mc68360.h"#include"m360.h"#include"bndqmc.h"#ifdefBRICK#include"hbdt.h"#endif/*************************************************************************************************LocalDefines*************************************************************************************************/#defineQMC_INTR_RXB0x01#defineQMC_INTR_TXB0x02#definePRESCALE_TMR18#defineMAX_LOOPS200/*MaxNumberofloopstowaitforFS*/#defineMIN_DMA_SIZE8/*MinimumnumberofbytestoDMA*//*************************************************************************************************LocalData*************************************************************************************************/PRIVATEUint8ubCurrentBondSeg[MAX_BOND_CHANNELS][MAX_DIR];pRIVATEUint8*pubUpdateAddr[MAX_BOND_CHANNELS][MAX_DIR];/*************************************************************************************************LocalFunctionPrototypes*************************************************************************************************/PRIVATEvoidInitializeFsCounter(void);PRIVATEvoidSetupChannel(Int16wPhysChan,Uint8*pRxBuffer,Uint8*pTxBuffer);PRIVATEvoidSetTxBufferDesc(Int16wPhysChan,Int16wSegment,Int16wControl, void*pvData,Int16wLen);PRIVATEvoidSetRxBufferDesc(Int16wPhysChan,Int16wSegment,Int16wControl, void*pvData,Int16wLen);******************************************************************************ExternalData******************************************************************************/externCPU_DATACPU_Data[MAX_CPU];externUint32Where[];/******************************************************************************GlobalData******************************************************************************//*---------------------------------------------------------------------------**BondingBuffers.****ThesearethebuffersthattheSCCDMAswillgetandputthedatafor**bonding.ThesebuffersmustbedeclaredasUint32ssothattheywillbe**alignedonlongwordboundries.****DimensionsBondBuffer[][][]**|||**||--->BufferData**|--->BufferDirectionTxorRx**--->LogicalChannelNumber****---------------------------------------------------------------------------*/PUBLICUint32BondBuffer[MAX_BOND_CHANNELS][MAX_DIR][MAX_BUFFER_LONGS];PUBLICBooleanboBondTimeslots[32];/******************************************************************************ExternalFunctionPrototypes******************************************************************************/externUint8*_getMBAR(Uint32processor);externvoidQMC_IssueCmd(Uint16uwChannel,Uint8ubOpCode);/******************************************************************************RoutineNameInitializeBond360()****DescriptionThisroutineinitializesthesystemforBondingontheMH360****ParametersNone****ReturnValueN/A********************************************************************************/PUBLICvoidInitializeBond360(void){ if(CPU_Data.Controller_Type==UP_QMC){ InitializeFsCounter(); memset((char*)BondBuffer,0,sizeof(BondBuffer)); memset((char*)boBondTimeslots,F(xiàn)ALSE,sizeof(boBondTimeslots));#ifdefBRICK InitializeHBDT();#endif }}/******************************************************************************RoutineNameStartChannel()****DescriptionThisfunctionstartsachannelTxandRxsynchronizedto**themastercounter.****ParameterswChannel(I)Thechannelnumbertoinitialize**wTxDelay(I)Transmitoffsetframedelay**wMode(I)Channelmode,TrainingorDelayCompensation****ReturnValueSUCCESSFULThechannelwassuccessfullystarted**ERROR_FS_TIMEOUTTimeoutwaitingforFScounter**ERROR_DMA_TIMEOUTTimeoutwaitingforDMA************************************************************************************************/PUBLICInt16StartChannel(Int16wPhysChan,Uint8*pubRxBuffer, Uint8*pubTxBuffer,Int16wTxDelay){ registerInt16wBuffChan;/*BufferChannelNumber*/ registerInt16wIndex;/*LoopCounter*/ registerP_BUF_DESCpRxBd;/*PointertoRxBufferDescriptors*/ registerP_BUF_DESCpTxBd;/*PointertoTxBufferDescriptors*/ Int16wStatus;/*ReturnStatus*/ Int16wRxLen;/*LengthofInitialRxBuffer*/ Int16wTxLen;/*LengthofInitialTxBuffer*/ Uint16uwIntMask;/*Currentvalueofinterruptprioritymask*/ Uint16uwRxMaster;/*ValueofMastercounterforRx*/ Uint16uwTxMaster;/*AdjustedvalueofMastercounterforTx*/ Uint16uwRbPtr;/*NewvalueforRBPTRinchannelparameters*/ Uint16uwTbPtr;/*NewvalueforTBPTRinchannelparameters*/ Uint16uwRxSeg;/*whichbuffersegmentshouldbestartedforRx*/ Uint16uwTxSeg;/*WhichbuffersegmentshouldbestartedforTx*/ Uint8*pubRxAddr;/*StartinglocationinRxbuffer*/ Uint8*pubTxAddr;/*StartinglocationinTxbuffer*/ Uint32cCount;/*Maximumloopcount*/ /*----------------------------------------------------------------------------------------* *SetupTxandRxBufferDescriptors* *----------------------------------------------------------------------------------------*/ wStatus=SUCCESSFUL; wBuffChan=PhysToBuff(wPhysChan); boBondTimeslots[wPhysChan]=TRUE; SetupChannel(wPhysChan,pubRxBuffer,pubTxBuffer); /*----------------------------------------------------------------------------------------* *GetaddressesofTxandRxBufferDescriptors* *----------------------------------------------------------------------------------------*/ pRxBd=(P_BUF_DESC)(IN32(MCBASE_QMC)+ IN16(RBASE_QMC(wPhysChan))); pTxBd=(P_BUF_DESC)(IN32(MCBASE_QMC)+ IN16(TBASE_QMC(wPhysChan))); /*----------------------------------------------------------------------------------------* *DisableInterruptsduringthisprocess**-------------------------------------------------------------------------------------*/uwIntMask=intr_set(7);/*-------------------------------------------------------------------------------------**Waitforalignmentwithframesync**-------------------------------------------------------------------------------------*/uwRxMaster=IN16(TCN4);for(cCount=0;(cCount<MAX_LOOPS)&&(uwPxMastsr==IN16(TCN4));cCount++);if(uwRXMaster==IN16(TCN4)){ wStatus=ERROR_FS1_TIMEOUT;}/*-------------------------------------------------------------------------------------**ComputeMasterTimerValueatDMAStart**-------------------------------------------------------------------------------------*/if(wStatus==SUCCESSFUL){ uwRxMaster=(IN16(TCN4)+4)&0x3FFC; wRxLen=BYTES_PER_SEGMENT-(uwRxMaster%BYTES_PER_SEGMENT); if(wRxLen<MIN_DMA_SIZE){ uwRxMaster+=MIN_DNA_SIZE; } /*---------------------------------------------------------------------------------* *ComputeRxStartingLocation* *---------------------------------------------------------------------------------*/ uwRXSeg=uwRxMaster>>11; uwRBPtr=uwRxSeg*sizeof(BUF_DESC); pubRxAddr=&pubRxBuffer[uwRxMaster]; wRXLen=BYTES_PER_SEGMENT-(uwRxMaster%BYTES_PER_SEGNT); pubUpdateAddr[wBuffChan][RX_BUFFER]= &pubRxBuffer[uwRxSeg*BYTES_PER_SEGMENT];/*-------------------------------------------------------------------------------* *ComputeTXStartingLocation* *-------------------------------------------------------------------------------*/uwTxMaster=(uwRxMaster-wTxDelay)&0x3FFF;uwTxSeg=uwTxMaster>>11;uwTbPtr=uwTxSeg*sizeof(BUF_DESC);pubTxAddr=&pubTxBuffer[uwTxMaster];wTxLen=BYTES_PER_SEGMENT-(uwTxaster%BYTES_PER_SEGNT);pubUpdateAddr[wBuffChan][TX_BUFFER]= &pubTxBuffer[uwTxSeg*BYTES_PER_SEGMNT];/*-------------------------------------------------------------------------------* *SetupInitialbuffer* *-------------------------------------------------------------------------------*/OUT32(RxPtr_QMC(wPhysChan),0x00000000);OIT16(RBPTR_QMC(wPhysChan),IN16(RBASE_QMC(wPhysChan))+uwRbPtr);OUT16(TBPTR_QMC(wPhysChan),IN16(TBASE_EMC(wPhysChan))+uwTbPtr);OUT16(TMRBLR_QMC(wPhysChan),wRxLen);OUT16(BDFLAGS_QMC(wPhysChan),0x0000);OUT32(TUPACK_QMC(wPhysChan),0x00000000);OUT32(RPACK_QMC(wPhysChan),0x00000000);pRxBd[uwRxSeg].pData=pubRxAddr;pTxBd[uwTxSeg].pData=pubTxAddr; pTxBd[uwTxSeg].length=wTxLen; ubCurrentBondSeg[wBuffChan][RX_BUFFER]=(Uint8)uwRxSeg; ubCurrentBondSeg[wBuffChan][TX_BUFFER]=(Uint8)uwTxSeg; /*---------------------------------------------------------------------------------------* *Waitforframesyncalignmenttoalongwordboundry* *---------------------------------------------------------------------------------------*/ for(cCount=0;(cCount<MAX_LOOPS*(4+MIN_DMA_SIZE))&& (uwRxMaster!*(IN16(TCN4)&0x3FFF));cCount++); if(uwRxMaster?。?IN16(TCN4)&0x3FFF)){ wStatus=ERROR_FS2_TIMEOUT; } } /*----------------------------------------------------------------------------------------------------* *SetPollbit* *----------------------------------------------------------------------------------------------------*/ if(wStatus==SUCCESSFUL){ OUT32(ZDSTATE_QMC(wphysChan),0x18000080); OUT32(RSTATE_QMC(wPhysChan),0x39000000); OUT16(TSAT_QMC(wPhysChan),(IN16(TSAT_QMC(wPhysChan))|0x8000)); OUT16(CHAMR_QMC(wPhysChan),(IN16(CHAMR_QMC(wPhysChan))|0x0100)); /*----------------------------------------------------------------------------------------------------* *TurnonR&Ebitsforallbufferdescriptors* *----------------------------------------------------------------------------------------------------*/ for(wIndex=0;wIndex<BUFFER_SEGMENTS;wIndex++){ pRxBd[wIndex].sc|=E_BIT; pTxBd[wIndex].sc|=R_BIT; } /*----------------------------------------------------------------------------------------------------* *WaitforDMAcyclebeforechangingMaxReceiveBufferLength* *----------------------------------------------------------------------------------------------------*/ for(cCount=0;(cCount<MAX_LOOPS*8)&& (IN32(RxPtr_QMC(wPhysChan))==0);cCount++); OUT16(TMRBLR_QMC(wPhysChan),BYTES_PER_SEGMNT); if(IN32(RxPtr_QMC(wPhysChan))==0){ wStatus=ERROR_DMA_TIMEOUT; }} /*----------------------------------------------------------------------------------------------------* *Re-EnableInterrupts* *----------------------------------------------------------------------------------------------------*/ intr_set(uwIntMask); return(wStatus);}/***********************************************************************************************************RoutineNameSetupChannel()****DescriptionThisfunctioninitializesachannelforBondingoperation****ParameterswChannel(I)Thechannelnumbertoinitialize****ReturnValueN/A************************************************************************************************************/PRIVATEvoidSetupChannel(Int16wPhysChan,Uint8*pRxBuffer,Uint8*pTxBuffer){ Int16wBuffChan;/*BufferChannelNumber*/ Int16wIndex;/*Loopcounter*/ uint16uwFrCount;/*CurrentValueforFramecounter*/ Uint16uwIntMask;/*Currentvalueofinterruptprioritymask*/ Uint32cCount;/*Maximumloopcount*/ /*----------------------------------------------------------------------------------------------------* *InitializeVariables* *----------------------------------------------------------------------------------------------------*/ wBuffChan=PhysToBuff(wPhysChan); /*----------------------------------------------------------------------------------------------------* *DisableInterruptsduringthisprocess* *----------------------------------------------------------------------------------------------------*/ uwIntMask=intr_set(7); /*----------------------------------------------------------------------------------------------------* *CleartheValidbitintheTimeslottable.* *----------------------------------------------------------------------------------------------------*/ OUT16(TSAT_QMC(wPhysChan),(IN16(TSAT_QMC(wPhysChan))&-0x8000)); /*----------------------------------------------------------------------------------------------------* *Waitforalignmentwithframesync* *----------------------------------------------------------------------------------------------------*/ uwFrCount=(IN16(TCN4)+3)&0xFFFC; for(cCount=0;(cCount<MAX_LOOPS*(4+MIN_DMA_SIZE))&& (uwFrCount?。絀N16(TCN4));cCount++); /*----------------------------------------------------------------------------------------------------* *StoptheTransmitterandReceiver* *----------------------------------------------------------------------------------------------------*/ QMC_IssueCmd(wPhysChan,0x01); QMC_IssueCmd(wPhysChan,0x00); /*----------------------------------------------------------------------------------------------------* *ConfiguretheChannelSpecificParametersforTransparentMode* *----------------------------------------------------------------------------------------------------*/ /* *SettheRISCStateMachines */ OUT32(TSTATE_QMC(wPhysChan),0x38000000); OUT32(ZISTATE_QMC(wPhysChan),0x00000100); /* *SettheTMRBLR(sameoffsetasMFLR)*/ OUT16(TMRBLR_QMC(wPhysChan),BYTES_PER_SEGMENT); /* *ChannelModeRegister(seepage2-12) * *MODE=0-TransparentMode *RD=1-ReverseBitorder,sendMSBfirst *=1-Bit13issetto1inTransparentmode *ENT=1-EnableTransmit *SYNC=0-Notamultichanneloperation *POL=0-DisablePollingofthetransmitBDs */ OUT16(CHAMR_QMC(wPhysChan),0x7000); /*----------------------------------------------------------------------------------------------------* *SetupthebufferdescriptorsforBonding* *----------------------------------------------------------------------------------------------------*/ /*Initializeallbutthelastbufferdescriptor*/ for(wIndex=0;wIndex<BUFFER_SEGMENTS-1;wIndex++){ SetTxBufferDesc(wPhysChan,wIndex,(I_BIT|CM_BIT), pTxBuffer,BYTES_PER_SEGMENT); SetRxBufferDesc(wPhysChan,wIndex,(I_BIT|CM_BIT), pRxBuffer,0x0000); pTxBuffer+=BYTES_PER_SEGMENT; pRxBuffer+=BYTES_PER_SEGMENT;}/*Initializethelastbufferdescriptorwiththewrapbitset*/SetTxBufferDesc(wPhysChan,wIndex,(I_BIT|CM_BIT|W_BIT), pTxBuffer,BYTES_PER_SEGMENT);SetRxBufferDesc(wPhysChan,wIndex,(I_BIT|CM_BIT|W_BIT), pRxBuffer,0x0000);/*-------------------------------------------------------------------------------------------------------**Re-EnableInterrupts**-------------------------------------------------------------------------------------------------------*/ intr_set(uwIntMask);}/************************************************************************************************************RoutineNameSetTxBufferDesc()****DescriptionThisfunctioninitializesatransmitbufferdescriptor.****ParameterswChannel(I)Thelogicalchannelnumber**wSegment(I)Whichsegmenttoinitialize**wControl(I)Controldataforsegment**pvData(I)bufferpointer**wLen(I)length****ReturnValueN/A**************************************************************************************************************/PRIVATEvoidSetTxBufferDesc(Intl6wPhysChan,Int16wSegment,Int16wControl, void*pvData,Int16wLen){ P_BUF_DESCpBd;/*Bufdescriptorpointer*/ pBd=(P_BUF_DESC)(IN32(MCBASE_QMC)+ IN16(TBASE_QMC(wPhysChan))+ (wSegment*sizeof(BUF_DESC))); pBd->pData=pvData; pBd->length=wLen; pBd->sc=wControl;}/******************************************************************************************RoutineNameSetRxBufferDesc()****DescriptionThisfunctioninitializesareceivebufferdescriptor.****ParameterswChannel(I)Thelogicalchannelnumber**wSegment(I)Whichsegmenttoinitialize**wControl(I)Controldataforsegment**pvData(I)bufferpointer**wLen(I)length****ReturnValueN/A********************************************************************************************/PRIVATEvoidSetRxBufferDesc(Int16wPhysChan,Int16wSegment,Int16wControl, void*pvData,Int16wLen){ P_BUF_DESCpBd;/*Burdescriptorpointer*/ pBd=(P_BUF_DESC)(IN32(MCBASE_QMC)+ IN16(RBASE_QMC(wPhysChan))+ (wSegment*sizeof(BUF_DESC))); pBd->pData=pvData; pBd->length=wLen; pBd->sc=wControl;}/******************************************************************************************RoutineNameBond360_QMC_Interrupt()****DescriptionThisroutineprocessesinterruptsforbondingchannels****ParameterswPhysChan(I)Thisisthephysicalchannelthe**interruptoccuredon.**ubInterruptFlags(I)Thisistheinterruptbitflags**indicatingthecauseoftheinterrupt****ReturnValueNone********************************************************************************************/PUBLICvoidBond360_QMC_Interrupt(Int16wPhysChan,Uint8ubInterruptFlags){Uint16uwSeg; Uint16wBuffChan; P_BUF_DESCpBd; /*----------------------------------------------------------------------------------------------* *InitailizeVariables* *----------------------------------------------------------------------------------------------*/ wBuffChan=PhysToBuff(wPhysChan); /*----------------------------------------------------------------------------------------------* *CheckForReceiveFrameComplete* *----------------------------------------------------------------------------------------------*/ if(ubInterruptFlags&QMC_INTR_RXB){ pBd=(P_BUF_DESC)(IN32(MCBASE_QMC)+IN16(RBASE_QMC(wPhysChan))); uwSeg=ubCurrentBondSeg[wBuffChan][RX_BUFFER]; ubCurrentBondSeg[wBuffChan][RX_BUFFER]=(uwSeg+1)%BUFFER_SEGMENTS; if(pubUpdateAddr[wBuffChan][RX_BUFFER]?。絅ULL){ pBd[uwSeg].pData=pubUpdateAddr[wBuffChan][RX_BUFFER]; pubUpdateAddr[wBuffChan][RX_BUFFER]=NULL; } } /*----------------------------------------------------------------------------------------------* *CheckForTransmitFrameComplete* *----------------------------------------------------------------------------------------------*/ if(ubInterruptFlags&QMC_INTR_TXB){ pBd=(P_BUF_DESC)(IN32(MCBASE_QMC)+IN16(TBASE_QMC(wPhysChan))); uwSeg=ubCurrentBondSeg[wBuffChan][TX_BUFFER]; ubCurrentBondSeg[wBuffChan][TX_BUFFER]=(uwSeg+1)%BUFFER_SEGMENTS; if(pubUpdateAddr[wBuffChan][TX_BUFFER]?。絅ULL){ pBd[uwSeg].pData=pubUpdateAddr[wBuffChan][TX_BUFFER]; pBd[uwSeg].length=BYTES_PER_SEGMENT; pubUpdateAddr[wBuffChan][TX_BUFFER]=NULL; } } /*----------------------------------------------------------------------------------------------* *CheckForOtherInterrupts* *----------------------------------------------------------------------------------------------*/ if(ubInterruptFlags&-(QMC_INTR_TXB|QMC_INTR_RXB)){ }}/**********************************************************************************************************RoutineNameInitializeFsCounter()****DescriptionTimer4onthe360isconnectedtoframesync.Initialize**ittocountframesyncpulses.Wewillusethisasour**mastercountertowhichallbondingdataissynchronized****ParametersNone****ReturnValueN/A************************************************************************************************************/PRIVATEvoidInitializeFsCounter(void){ /*----------------------------------------------------------------------------------------------* *ConfigureTimer4tocountframesyncpulses* *----------------------------------------------------------------------------------------------*/ OUT16(TGCR,IN16(TGCR)&(TGCR_MASK1|TGCR_MASK2|TGCRMASK3)); OUT16(TMR4,(TMR_CE_ISABLE|TMR_OM_PULSE|TMR_ORI_DISABLE| TMR_FFR_FREERUN|TMR_ICLK_TIN|TMR_GE_IGNORE)); OUT16(TCN4,0x0000);/*Se<InitialCount*/ OUT16(TRR4,0x0000);/*SetReference*/ OUT16(TER4,0xFFFF);/*ClearEvents*/ OUT16(TGCR,IN16(TGCR)|TGCR_RST4);/*Enablethetimer*/}/************************************************************************************************** ** *Filebndstate.cDateApril20,1996* ** *(C)Copyright1997byVideoServerInc.* *AllRightsReserved* *EngineerDaveOliveira* ** *DescriptionThefilecontainscodetosupportBondingonthe* *68MH360* ** **************************************************************************************************//************************************************************************************************** *IncludeFiles* **************************************************************************************************/#include<mriext.h>#include<string.h>#include"flags.h"#include"codestd.h"#include"compiler.h"#include"tune.h"#include"gendef.h"#include"exec.h"#include"vrtx.h"#include"vrtxil.h"#include"devkit.h"#include"amdev.h"#include"imux_db.h"#include"bndqmc.h"#include"mc68360.h"#include"m360.h"#include"hd_proto.h"#include"hituser.h"/*****************************************************************************************************,LocalDefines*****************************************************************************************************/#defineMIN_TX_OFFSET8#defineALIGN_DELAY88L/*****************************************************************************************************ExternalData*****************************************************************************************************/externUint32BondBuffer(MAX_BOND_CHANNELS][MAX_DIR][MAX_BUFFER_LONGS];externChannelDataChanData[MAX_BOND_CHANNELS];externSessionDataSessions[MAX_BOND_SESSIONS];externCPU_DATACPU_Data[MAX_CPU];externvolatileUint32TimerTicks;externBondingParmsBondingData[];externUint32Where[];/*****************************************************************************************************GlobalData**************************************************************************************/PRIVATEMAILBOX*pMbox;/**************************************************************************************FunctionPrototypes**************************************************************************************/PRIVATEvoidProcessBondTimer(void);PRIVATEvoidBond360AlignState(Uint8ubSession);PRIVATEvoidAlignRemoteReady(Uint8ubSession);PRIVATEvoidAligrDelay(Uint8ubSession);PRIVATEvoidAlignClearA(Uint8ubSession);PRIVATEInt16ComputeAlignment(Uint8ubSession);PRIVATEInt16PostAlignComplete(Uint8ubSession,Int16wMaxDelay,Uint8ubRetCode);PRIVATEvoidSetsessionTimer(Uint8ubSession,Uint32ulTicks);PRIVATEBooleanCheckSessionTimer(Uint8ubSession);/**************************************************************************************ExternalFunctionPrototypes**************************************************************************************/externIMUXMsg*GetIMUXblock(Int16*ret_code);externvoidReleaseIMUXblock(IMUXMsg*pMsg);externMAILBOX*QID_to_MTEX(Int16qid,Int16*errP);externvoid_LOADDStrap(Int16,Int16,voidFAR*);/**************************************************************************************RoutineNameBond360_Tx_Task()****DescriptionThisfunctionimplementsthe"transmit"taslforthe**68MH360implementationofbonding,i.e.noDSP.****ParametersNone****ReturnValueN/A****************************************************************************************/PUBLICvoidBond360_Tx_Task(void){ Int16wStatus; IMUXMsg*pMsg; TIMER_BLOCK*pTID; SEQNOSeqNum; EXT_MEMExtMem; /*----------------------------------------------------------------------------* *StarttheperiodicTimer* *----------------------------------------------------------------------------*/ pMbox=QID_to_MTEX(IMUX_Tx_Queue,&wStatus); if(wStatus==Ret_Ok){ pMsg=GetIMUXblock(&wStatus); if(wStatus==Ret_Ok){ memset(pMsg,0,sizeof(IMUXMsg)); pMsg->ubPrimcode=BondingTimerTick; ExtMem.Addr=(BYTE*)pMsg; SetTimer(pMbox,&ExtMem,5,&pTID,&SeqNum,0); }} /*----------------------------------------------------------------------------------------------* *ProcesstheMessage* *----------------------------------------------------------------------------------------------*/ for(;;){ pMsg=(IMUXMsg*)sc_qpend(IMUX_Tx_Queue,0L,&wStatus); if(wStatus==Ret_Ok){ switch(pMsg->ubPrimcode){ caseBondingTimerTick ProcessBondTimer(); SetTimer(pMbox,&ExtMem,5,&pTID,&SeqNum,0); break; caseBondingDspMsg ProcessBondMsg(pMsg); ReleaseIMUXblock(pMsg); break; default break; } } else{ trap(SC_QPEND,wStatus,NULL); } }}/*****************************************************************************************************RoutineNameProcessBondTimer()****Descriptionhisfunctioniscalledwhentheperiodicbondingtimer**expires.Weprocessthestatemachineshere.****ParametersNone****ReturnValueN/A*******************************************************************************************************/PRIVATEvoidProcessBondTimer(void){ Int16wBuffChan; Uint8ubSession;/*-----------------------------------------------------------------------------------------------* *ProcesstheChannelStateMachines* *-----------------------------------------------------------------------------------------------*/for(wBuffChan=0;wBuffChan<MAX_BOND_CHANNELS;wBuffChan++){ Bond360ChannelState(BuffToPhys(wBuffChan)); }/*----------------------------------------------------------------------* *ProcesstheAlignerStateMachines* *----------------------------------------------------------------------*/ for(ubSession=0;ubSession<MAX_BOND_SESSIONS;uhSession++){ Bond360AlignState(ubSession); }}/**********************************************************************************RoutineNameBond360AlignState()****DescriptionThisfunctioniscalledwhentheperiodicbondingtimer**expires.Weprocessthealignmentstatemachinehere****ParametersubSession(I)ThisistheSessionnumberofthesession**toprocess.****ReturnValueN/A************************************************************************************/PRIVATEvoidBond360AlignState(Uint8ubSession){ switch(Sessions[ubSession].ubState){ caseAS_NULL break; caseAS_RMT_STATE AlignRemoteReady(ubSession); break; caseAS_DELAY AlignDelay(ubSession); break; caseAS_CLEAR_A AlignClearA(ubSession); break; caseAS_ALIGNED break; default break; }}/**********************************************************************************RoutineNameAlignRemoteReady()****DescriptionThisfunctionchecksifallofthechannelsforasession**areintheproperstateandtheRIbitofthereceived**Infochannelsareset.****ParametersubSession(I)ThisistheSessionnumberofthesession**toprocess.****ReturnValueN/A********************************************************************************/PRIVATEvoidAlignRemoteReady(Uint8ubSession){ Int16wBuffChan; BooleanboReady; /*-----------------------------------------------------------------------* *Checkifallofthechannelsinthissessionareready* *-----------------------------------------------------------------------*/ boReady=TRUE; for(wBuffChan=0;wBuffChan<MAX_BOND_CHANNELS;wBuffChan++){ if((ChanData[wBuffChan].ubSession==ubSession)&& (ChanData[wBuffChan].ubChanState?。紺S_NULL)){ if((ChanData[wBuffChan].ubChanState?。紺S_LEARNING)|| ((ChanData[wBuffChan].ubIC_Frame[6]&0x40)==0)){ boReady=FALSE; break; } } } /*------------------------------------------------------------------------* *IftheChannelsAreReady,CleartheABitandchangethestate* *------------------------------------------------------------------------*/ if(boReady){ for(wBuffChan=0;wBuffChan<MAX_BOND_CHANNELS;wBuffChan++){ if((ChanData[wBuffChan].ubsession==ubSession)&& (ChanData[wBuffChan].ubChanState?。紺S_NULL)){ Set_A_Bit(BuffToPhys(wBuffChan),0); } } Sessions[ubSession].ubState=AS_DELAY; SetSessionTimer(ubSession,ALIGN_DELAY); }}/*******************************************************************************RoutineNameAlignDelay()****DescriptionThisfunctionchecksifdelaytimerhasexpired.****ParametersubSession(I)ThisistheSessionnumberofthesession**toprocess.****ReturnValueN/A*********************************************************************************/PRIVATEvoidAlignDelay(Uint8ubSession){ /*------------------------------------------------------------------------**Checkifthetimerhasexpired* *----------------------------------------------------------------------*/ if(CheckSessionTimer(ubSession)){ Sessions[ubSession].ubState=AS_CLEAR_A; AlignClearA(ubSession); }}/**********************************************************************************RoutineNameAlignClearA()****DescriptionThisfunctionchecksiftheinboundAbitisclearedorthe**frameisnolongerinsync.****ParametersubSession(I)ThisistheSessionnumberofthesession**toprocess.****ReturnValueN/A*************************************************************************************/PRIVATEvoidAlignClearA(Uint8ubSession){ Int16wBuffChan; Int16wMaxDelay; BooleanboReady; /*----------------------------------------------------------------------------* *CheckifallthechannelshavetheRxAbitclearedorhavelostsync* *----------------------------------------------------------------------------*/ boReady=TRUE;#if0 for(wBuffCban=0;wBuffChan<MAX_BOND_CHANNELS;wBuffChan++){ if((ChanData[wBuffChan].ubSession==ubSession)&& (ChanData[wBuffChan].ubChanState!=CS_NULL)){ if((ChanData[wBuffChan].ubMF_State?。?)|| ((ChanData[wBuffChan].ubMF_RxCrc&0x40)?。?)){ boReady=FALSE; break; } } }#else wBuffChan=wBuffChan;#endif /*----------------------------------------------------------------------------* *Ifallthechannelsarereadydothealignment* *----------------------------------------------------------------------------*/ if(boReady){ wMaxDelay=ComputeAlignment(ubSession); PostAlignComplete(ubSession,wMaxDelay,0); Sessions[ubSession].ubState=AS_ALIGNED; }}/***********************************************************************************RoutineNameAlignChannels()****DescriptionThisfunctioncomputestheframealignment****ParametersubSession(I)ThisistheSessionnumberofthesession**toprocess.****ReturnValueN/A************************************************************************************************/PRIVATEInt16ComputeAlignment(Uint8ubSession){ Int16wBuffChan; Int16wMaxDelay; Int16wMinDiff; Iht16wDiff; Int16wStart; Int16wBase; Int16wFrame0; Uint8ubOrder[MAX_BOND_CHANNELS]; BooleanboTDMbus; /*---------------------------------------------------------------------------------------* *Findachannelinthesessiontouseasastartchannel* *---------------------------------------------------------------------------------------*/ for(wBuffChan=0;wBuffChan<MAX_BOND_CHANNELS;wBuffChan++){ if((ChanData[wBuffChan].ubSession==ubSession)&& (ChanData[wBuffChan].ubChanState?。紺S_NULL)){ wStart=wBuffChan; break; } } /*---------------------------------------------------------------------------------------* *FindtheBaseChannel,i.e.Channelwithlongestdelay* *---------------------------------------------------------------------------------------*/ wMinDiff=32000; wFrame0=ChanData[wStart].wMF_Frame0Index-ChanData[wStart].ubRxChanId; for(wBuffChan=0;wBuffChan<MAX_BOND_CHANNELS;wBuffChan++){ if((ChanData[wBuffChan].ubSession==ubSession)&& (ChanData[wBuffChan].ubChanState?。紺S_NULL)){ wDiff=wFrame0-(ChanData[wBuffChan].wMF_Frame0Index-ChanData[wBuffChan].ubRxChanId); if(abs(wDiff)>8192){ wDiff^=0xC000; } if(wDiff<wMinDiff){ wMinDiff=wDiff; wBase=wBuffChan; } } } /*--------------------------------------------------------------------------------------* *ComputetheDelayOffsetsforEachChannel**----------------------------------------------------------------------------*/ wMaxDelay=-32000; wFrame0=ChanData[wBase].wMF_Frame0Index-ChanData[wBase].ubRxChanId; for(wBuffChan=0;wBuffChan<MAX_BOND_CHANNELS;wBuffChan++){ if((ChanData[wBuffChan].ubSession==ubSession)&& (ChanData[wBuffChan].ubChanState?。紺S_NULL)){ ChanData[wBuffChan].wOffset=wFrame0-(ChanData[wBuffChan].wMF_Frame0Index-ChanData[wBuffChan].ubRxChanId); if(abs(ChanData[wBuffChan].wOffset)>8192){ ChanData[wBuffChan].wOffset^=0xC000; } wMaxDelay=max(wMaxDelay,ChanData[wBuffChan].wOffset); } } /*---------------------------------------------------------------------------------* *DeterminetheChannelOrder* *---------------------------------------------------------------------------------*/ boTDMbus=(BondingData[ubSession].ubBChanProtocol?。紿OST_TRANSPAR); if(boTDMbus){ ChannelOrder(ubOrder,ubSession); } /*---------------------------------------------------------------------------------* *Re-StartEachChannelwiththecomputedDelays* *---------------------------------------------------------------------------------*/ if(boTDMbus){ for(wBuffChan=0,wBase=0;wBuffChan<MAX_BOND_CHANNELS;wBuffChan++){ if((ChanData[wBuffChan].ubSession==ubSession)&& (ChanData[wBuffChan].ubChanState!=CS_NULL)){ wStart=ubOrder[wBase++]; StartChannel(BuffToPhys(wBuffChan), (Uint8*)BondBuffer[wBuffChan][RX_BUFFER], (Uint8*)BondBuffer[wStart][RX_BUFFER], ChanData[wStart].wOffset+MIN_TX_OFFSET); ChanData[wBuffChan].ubChanState=CS_ALIGN; } } } /*---------------------------------------------------------------------------------* *ForHBDTcalls,CleartheTxbufferandchangethechannelstate* *---------------------------------------------------------------------------------*/ if(!boTDMbus){ for(wBuffChan=0,wBase=0;wBuffChan<MAX_BOND_CHANNELS;wBuffChan++){ if((ChanData[wBuffChan].ubSession==ubSession)&& (ChanData[wBuffChan].ubChanState?。紺S_NULL)){ memset((Uint8*)BondBuffer[wBuffChan][TX_BUFFER],0xFF,BUFFER_BYTES); ChanData[wBuffChan].ubChanState=CS_ALIGN; } } }return(wMaxDelay);}/****************************************************************************************RoutineNameChannelOrder()****DescriptionThisfunctiondeterminesthechannelorder****Parameterspuborder(I)Thearraytoplacetheorderedlistinto.**ubSession(I)Thesessionnumberofthesessiontoprocess****ReturnValueNone******************************************************************************************/PUBLICvoidChannelOrder(Uint8*pubOrder,Uint8ubSession){ Int16wBuffChan; Int16wBase; /*---------------------------------------------------------------------------------* *InitializetheOrderArray* *---------------------------------------------------------------------------------*/ memset(pubOrder,-1,MAX_BOND_CHANNELS); /*---------------------------------------------------------------------------------* *FillintheChannelOrderArray* *---------------------------------------------------------------------------------*/ for(wBuffChan=0;wBuffChan<MAX_BOND_CHANNELS;wBuffChan++){ if((ChanData[wBuffChan].ubdession==ubSession)&& (ChanData[wBuffChan].ubChanState!=CS_NULL)){ pubOrder[ChanData[wBuffChan].ubRxChanId-1]=wBuffChan; } } /*---------------------------------------------------------------------------------* *CompresstheChannelOrderArray* *---------------------------------------------------------------------------------*/ for(wBase=0;wBase<MAX_BOND_CHANNELS;wBase++){ if(pubOrder[wBase]==0xFF){ memcpy(&pubOrder[wBase],&pubOrder[wBase+1], (MAX_BOND_CHANNELS-wBase)-1); } }}/****************************************************************************************RoutineNamePostAlignComplete()****DescriptionThisfunctionsendsanAlignCompleteMessage****ParametersubSession(I)Thesessionnumberofthesessiontoprocess**wMaxDelay(I)Thecomputedmaximumrelativedelay****ReturnValueRET_OKThemessagewassent*****************************************************************************************/PRIVATEInt16PostAlignComplete(Uint8ubSession,Int16wMaxDelay,Uint8ubRetCode){ Int16wPhysChan; Int16wBuffChan; Int16wStatus; IMUXMsg*pMsg; /*---------------------------------------------------------------------------------* *GetBlocktosendmessagein* *---------------------------------------------------------------------------------*/ pMsg=GetIMUXblock(&wStatus); if(wStatus==Ret_Ok){ memset(pMsg,0,sizeof(IMUXMsg)); wPhysChan=Sessions[ubSession].wBaseChan; wBuffChan=PhysToBuff(wPhysChan); /*-----------------------------------------------------------------------------* *FillintheDatafortheMessage* *-----------------------------------------------------------------------------*/ pMsg->IMUXData.DspMsg.ubLength=22; pMsg->IMUXData.DspMsg.ubPrimcode=MCA_AlignComplete; pMsg->IMUXData.DspMsg.ubDs0=wPhysChan; pMsg->IMUXData.DspMsg.ubInterface=ChanData[wBuffChan].ubInterface; pMsg->IMUXData.DspMsg.ubSession=ubSession; pMsg->IMUXData.DspMsg.ubRetcode=ubRetCode; pMsg->ubPrimcode=BondingDspMsg; pMsg->ubSession=ubSession; pMsg->ubDspTSlot=wPhysChan; pMsg->ubStartDs0=PhysToBuff(wPhysChan)&0x01; pMsg->ubInterface=PhysToBuff(wPhysChan)>>1; pMsg->IMUXData.DspMsg.data.uwMaxDelay=(Uint16)SwapWord(wMaxDelay); /*-----------------------------------------------------------------------------* *SendtheMessagetotheBondingTask* *-----------------------------------------------------------------------------*/ sc_qpost(IMUX_Rx_Queue,(Uint8*)pMsg,&wStatus); if(wStatus?。絉et_Ok){ ReleaseIMUXblock(pMsg); trap(SC_QPOST,wStatus,NULL); }}return(wStatus);}/****************************************************************************************RoutineNameSetSessionTimer()****DescriptionThisfunctionsetsthetimerforasessiontoanew**expirationvalue.****ParametersubSession(I)Thesessionnumberofthesessiontoprocess**ulTicks(I)Thenumberoftimertickstowait****ReturnValueN/A*********************************************************************************************/PRIVATEvoidSetSessionTimer(Uint8ubSession,Uint32ulTicks){ if(ulTicks?。?){ ulTicks=TimerTicks+ulTicks; if(ulTicks==0){ ulTicks=1; } } Sessions[ubSession].ulTimer=ulTicks;}/*******************************************************************************************RoutineNameCheckSessionTimer()****DescriptionThisfunctionchecksifthetimerforasessionhasexpired****ParametersubSession(I)Thesessionnumberofthesessiontoprocess**ReturnValueTRUEThetimerhasexpired**FALSEThetimerisstillrunning*********************************************************************************************/PRIVATEBooleanCheckSessionTimer(Uint8ubSession){ /*-------------------------------------------------------------------------------------* *Thetimerhasexpiredifthealloffollowingaretrue* *1.Thetimerisactive,i.e.thetimervalueisnotzero* *2.Thetimervalueandthecurrenttickcountbothhavethesame* *msb.* *3.TheTickcountisgreaterthanorequaltothetimervalue.* *-------------------------------------------------------------------------------------*/ return((Boolean)((Sessions[ubSession].ulTimer!=0)&& (((TimerTicks^Sessions[ubSession].ulTimer)&0x80000000)==0)&& (TimerTicks>=Sessions[ubSession].ulTimer)));}/********************************************************************************************RoutineNameBond360ChannelData()****DescriptionThisfunctionformatsanddisplaystheChannelDatafora**channel.****ParameterswChannel(I)Thechannelnumberofthechanneltoprocess****ReturnValueNone**********************************************************************************************/PCBLICBond360ChannelData(Int16wPhysChan){Int16wFrame; Int16wIndex; Int16wBuffChan; wBuffChan=PhysToBuff(wPhysChan); printf("Channel%d%p\n",wPhysChan,&ChanData[wBuffChan]); printf("ChanState%dSession%dInterface%dDS0%d\n", ChanData[wBuffChan].ubChanState,ChanData[wBuffChan].ubSession, ChanData[wBuffChan].ubInterface,ChanData[wBuffChan].ubDS0); printf("Offset%4dTxChanId%2dRxChanId%2dTimer%081x\n\n", ChanData[wBuffChan].wOffset,ChanData[wBuffChan].ubTxChanId, ChanData[wBuffChan].ubRxChanId,ChanData[wBuffChan].ulTimer); printf{"MF_State%dIndex%04XFrame0%04XFrameCount%02x\n", ChanData[wBuffChan].ubMF_State,ChanData[wBuffChan].wMF_Index, ChanData[wBuffChan].wMF_Frame0Index,ChanData[wBuffChan].ubMF_FrameCounter); printf("FawLoss%dFcLoss%dInfoIndex%2dRxCrc%02x\n\n", ChanData[wBuffChan].ubMF_FawLoss,ChanData[wBuffChan].ubMF_FcLoss, ChanData[wBuffChan].ubMF_InfoIndex,ChanData[wBuffChan].ubMF_RxCrc); printf("IC_State%dIndex%04XBuffIndex%dTicks%081x\n", ChanData[wBuffChan].ubIC_State,ChanData[wBuffChan].wIC_Index, ChanData[wBuffChan].ubIC_BuffIndex,TimerTicks); for(wFrame=0;wFrame<3;wFrame++){ printf("Frame[%d]",wFrame); for(wIndex=0;wIndex<16;wIndex++){ printf("%02X",ChanData[wBuffChan].ubIC_Frame[wFrame][wIndex]); } printf("\n"); } printf("Last"); for(wIndex=0;wIndex<16;wIndex++){ printf("%02X",ChanData[wBuffChan].ubIC_Last[wIndex]); } printf("\n");}/***********************************************************************************************RoutineNameBond360SessionData()****DescriptionThisfunctionformatsanddisplaystheSessionDatafora**session.****ParametersubSession(I)Thesessionnumberofthesessiontoprocess****ReturnValueNone*************************************************************************************************/PUBLICvoidBond360SessionData(Uint8ubSession){printf("session%dState%dBaseChan%dTimer%081x\n",ubSession, Sessions[ubSession].ubState, Sessions[ubSession].wBaseChan, Sessions[ubSession].ulTimer);}****************************************************************************************************Filebndsync.cDateApril20,1996****(C)Copyright1997byVideoServerInc.**AllRightsReserved**EngineerDaveOliveira****DescriptionThefilecontainscodetosupportBondingonthe**68MH360******************************************************************************************************/#defineUSE_ASM/****************************************************************************************************IncludeFiles****************************************************************************************************/#include<string.h>#include"codestd.h"#include"flags.h"#include"compiler.h"#include"gendef.h"#include"tune.h"#include"lif.h"#include"vrtx.h"#include"vrtxil.h"#include"devkit.h"#include"imux_db.h"#include"bndqmc.h"#include"mc68360.h"#include"m360.h"/****************************************************************************************************ExternalData****************************************************************************************************/externUint32BondBuffer[MAX_BOND_CNANNELS][MAX_DIR][MAX_BUFFER_LONGS);externCPU_DATACPU_Data[MAX_CPU];externUint32Where[];/****************************************************************************************************GlobalData****************************************************************************************************/ChannelDataChanData[MAX_BOND_CHANNELS];SessionDataSessions[MAX_BOND_SESSIONS];/****************************************************************************************************ExternalFunctionPrototyces****************************************************************************************************/externIMUXMsg*GetIMUXblock(Int16*ret_code);externvoidReleaseIMUXblock(IMUXMsg*pMsg);externvoid_LOADDStrap(Int16,Int16,voidFAR*);externvoid*ret_addr(void);/*****************************************************************************************************RoutineNameIC_Sync()****DescriptionThisroutineisthestatemachineforsynchronizingto**theinformationchannelframe.****ParameterswPhysChan(I)Channelnumbertooperateon****ReturnValueN/A*************************************************************************************************/PUBLICBooleanIC_Sync(Int16wPhysChan){ registerInt16wIndex; registerInt16wCpyIndex; registerInt16wCpyCount; registerInt16wBytesLeft; registerUint8*pubBuffer; registerChannelData*pCdPtr; registerUint8*pubFrame; Uint8*pubEndPtr; BooleanboMsgSent; /*-----------------------------------------------------------------------------------------* *InitializeVariables* *-----------------------------------------------------------------------------------------*/ pubBuffer=(Uint8*)BondBuffer[PhysToBuff(wPhysChan)][RX_BUFFER]; pCdPtr=&ChanData[PhysToBuff(wPhysChan)]; wIndex=pCdPtr->wIC_Index; boMsgSent=FALSE; /*-----------------------------------------------------------------------------------------* *ComputeNumberofBytestoScan* *-----------------------------------------------------------------------------------------*/ pubEndPtr=(Uint8*)(IN32(RxPtr_QMC(wPhysChan))); if(pubEndPtr<&pubBuffer[wIndex]){ wBytesLeft=(BUFFER_BYTES-wIndex)+(pubEndPtr-pubBuffer); } else{ wBytesLeft=pubEndPtr-&pubBuffer[wIndex]; } /*-----------------------------------------------------------------------------------------* *ScantheBuffer* *-----------------------------------------------------------------------------------------*/ while(wBytesLeft>0){ switch(pCdPtr->ubIC_State){ /*---------------------------------------------------------------------------------* *NoSyncByteshavebeenfound,CheckforFAW**---------------------------------------------------------------------------------*/ caseIC_NOSYNC while(wBytesLeft>0){ if(pubBuffer[wIndex]==IFAW){ pCdPtr->ubIC_State=IC_IFAW_FOUND; wIndex=(wIndex+1)&0x3FFF;wBytesLeft--; break; } wIndex=(wIndex+1)&0x3FFF; wBytesLeft--; } break;/*----------------------------------------------------------------------------**AnIFAWhasbeenforCheckifBit1isset**----------------------------------------------------------------------------*/caseIC_IFAW_FOUND if((pubBuffer[wIndex]&0x81)==0x81){ pCdPtr->ubIC_State=IC_BITI_FOUND; wIndex=(wIndex+1)&0x3FFF; wByteeLeft--; break; } else{ pCdPtr->ubIC_State=IC_NOSYNC; break; } break;/*----------------------------------------------------------------------------**CheckifaIFAWappearsattheendofthisframe**----------------------------------------------------------------------------*/caseIC_BIT1_FOUND if(wBytesLeft>=14){ if(pubBuffer[(wIndex+14)&0x3FFFF]==IFAW){ /* *Weareinsync,copytheInfochanneldata */ pubFrame=pCdPtr->ubIC_Frame[pCdPtr->ubIC_BuffIndex]; for(wCpyCount=0,wCpyIndex=0;wCpyCount<16;wCpyCount++){ *pubFrame++=pubBuffer[wCpyIndex]; wCpyIndex=(wCpyIndex+1)&0x3FFF; } pCdPtr->ubIC_State=IC_INSYNC; wIndex=(wIndex+14)&0x3FFF; wBytesLeft-=14; boMsgSent=CheckNewMessage(wPhysChan,MCA_InitSync); } else{ pCdPtr->ubIC_State=IC_NOSYNC; } } else{ wBytesLeft=0; } break;/*----------------------------------------------------------------------------**Wehavedeclaredsync,lookforInfoChannelMsgs**----------------------------------------------------------------------------*/ caseIC_INSYNC caseIC_NO_IFAW_1 caseIC_NO_IFAW_2 while(wBytesLeft>16){ if(pubBuffer[wIndex]?。絀FAW){ pCdPtr->ubIC_State++; if(pCdPtr->ubIC_State>=IC_NO_IFAW_3){ pCdPtr->ubIC_State=IC_NOSYNC; break; } } pubFrame=pCdPtr->ubIC_Frame[pCdPtr->ubIC_BuffIndex]; wCpyIndex=wIndex; for(wCpyCount=0;wCpyCount<16;wCpyCount++){ *pubFrame++=pubBuffer[wCpyIndex]; wCpyIndex=(wCpyIndex+1)&0x3FFF; } boMsgSent|=CheckNewMessage(wPhysChan,MCA_InitSync); wIndex=(wIndex+16)&0x3FFF; wBytesLeft-=16; } wBytesLeft=0; break; default /*WeShouldNEVERGetHere*/ break; } } pCdPtr->wIC_Index=wIndex; return(boMsgSent);}/*****************************************************************************************************RoutineNameMF_Sync()****DescriptionThisroutineisthestatemachineforsynchronizingto**themulti-framesignal.****ParameterswPhysChan(I)Channelnumbertooperateon****ReturnValueN/A********************************************************************************************************/PUBLICBooleanMF_Sync(Int16wPhysChan){ registerInt16wIndex; registerInt16wBytesLeft; registerUint8*pubBuffer; registerChannelData*pCdPtr; Uint8*pubEndPtr; Uint8ubNextFc;BooleanboMsgSent; /*----------------------------------------------------------------------------* *InitializeVariables* *----------------------------------------------------------------------------*/ pubBuffer=(Uint8*)BondBuffer[PhysToBuff(wPhysChan)][RX_BUFFER]; pCdPtr=&ChanData[PhysToBuff(wPhysChan)]; wIndex=pCdPtr->wMF_Index; boMsgSent=FALSE; /*----------------------------------------------------------------------------* *ComputeNumberofBytestoScan* *----------------------------------------------------------------------------*/ pubEndPtr=(Uint8*)(IN32(RxPtr_QMC(wPhysChan))); if(pubEndPtr<&pubBuffer[wIndex]){ wBytesLeft=(BUFFER_BYTES-wIndex)+(pubEndPtr-pubBuffer); } else{ wBytesLeft=pubEndPtr-&pubBuffer[wIndex]; } /*---------------------------------------------------------------------------------* *ScantheBuffer* *---------------------------------------------------------------------------------*/ while(wBytesLeft>0){ switch(pCdPtr->ubMF_State){ /*-------------------------------------------------------------------------* *NoSyncByteshavebeenfound,CheckforFAW* *-------------------------------------------------------------------------*/ caseMF_NOSYNC while(wBytesLeft>0){ if(pubBuffer[wIndex]==FAW){ pCdPtr->ubMF_State=MF_FAW_FOUND; wIndex=(wIndex+1)&0x3FFF; wBytesLeft--; break; } wIndex=(wIndex+1)&0x3FFF; wBytesLeft--; } break; /*---------------------------------------------------------------------------* *AnFAWhasbeenforCheckifBit1isset* *---------------------------------------------------------------------------*/ caseMF_FAW_FOUND if(wBytesLeft>=128){ if((pubBuffer[(wIndex+127)&0x3FFFF]&0x81)==0x81){ pCdPtr->ubMF_state=MF_BIT1_FOUND; pCdPtr->ubMF_FrameCounter=pubBuffer[(wIndex+127)&0x3FFFF]; wIndex=(wIndex+127)&0x3FFF; wBytesLeft-=127;break; } else{ pCdPtr->ubMF_State=MF_NOSYNC; break; } } else{ wBytesLeft=0; } break; /*----------------------------------------------------------------------------* *CheckifaFAWappearsattheendofthisframe* *----------------------------------------------------------------------------*/ caseMF_BIT1_FOUND if(wBytesLeft>=128){ if(pubBuffer[(wIndex+128)&0x3FFFF]==FAW){ pCdPtr->ubMF_State=MF_INSYNC_DATA_1; pCdPtr->ubMF_FawLoss=0; pCdPtr->ubMF_FcLoss=0; pCdPtr->ubMF_InfoIndex=0; pCdPtr->wMF_Frame0Sample=0xFFFF; wIndex=(wIndex+128)&0x3FFF; wBytesLeft-=128; Set_A_Bit(wPhysChan,1); break; } else{ pCdPtr->ubMF_State=MF_NOSYNC; break; } } else{ wBytesLeft=0; } break; /*-------------------------------------------------------------------------* *FrameSyncAquired,LookingforFAW* *-------------------------------------------------------------------------*/ caseMF_INSYNC_DATA_0 if(wBytesLeft>=64){ pCdPtr->ubMF_State=MF_INSYNC_DATA_1; wIndex=(wIndex+64)&0x3FFF; wBytesLeft-=64; if(pubBuffer[wIndex]?。紽AW){ pCdPtr->ubMF_FawLoss++; if(pCdPtr->ubMF_FawLoss>=3){ pCdPtr->ubMF_State=MF_NOSYNC; Set_A_Bit(wPhysChan,0); } } else{ pCdPtr->ubMF_FawLoss=0;} } else{ wBytesLeft=0; } break; /*----------------------------------------------------------------------------* *FrameSyncAquired,LookingforInfoChannel* *----------------------------------------------------------------------------*/ caseMF_INSYNC_DATA_1 if(wBytesLeft>=64){ pCdPtr->ubMF_State=MF_INSYNC_DATA_2; wIndex=(wIndex+64)&0x3FFF; wBytesLeft-=64;pCdPtr->ubIC_Frame[pCdPtr->ubIC_BuffIndex][pCdPtr->ubMF_InfoIndex++]=pubBuffer[wIndex]; pCdPtr->ubMF_InfoIndex&=0x0F; if(pubBuffer[wIndex]==IFAW){ pCdPtr->ubMF_InfoIndex=1; pCdPtr->ubIC_Frame[pCdPtr->ubIC_BuffIndex]=IFAW; if(CheckNewMessage(wPhysChan,MCA_InSync)){ boMsgSent|=TRUE; pCdPtr->wMF_Frame0Index=pCdPtr->wMF_Frame0Sample; } } } else{ wBytesLeft=0; } break; /*---------------------------------------------------------------------------------* *FrameSyncAquired,LookingforFrameCounter* *---------------------------------------------------------------------------------*/ caseMF_INSYNC_DATA_2 if{wBytesLeft>=64){ pCdPtr->ubMF_State=MF_INSYNC_DATA_3; wIndex=(wIndex+64)&0x3FFF; wBytesLeft-=64; ubNextFc=pCdPtr->ubMF_FrameCounter+2|0x81; pCdPtr->ubMF_FrameCounter=pubBuffer[wIndex]; if(ubNextFc?。絧ubBuffer[wIndex]){ pCdPtr->ubMF_FcLoss++; if(pCdPtr->ubMF_FcLoss>=3){ pCdPtr->ubMF_State=MF_NOSYNC; Set_A_Bit(wPhysChan,0); } } else{ if(pCdPtr->wMF_Frame0Sample==0xFFFF){ pCdPtr->wMF_Frame0Sample=((wIndex-128)- (((pubBuffer[wIndex]>>1)&0x3F)*256)) &0x3FFF;} pCdPtr->ubMF_FcLoss=0; Set_RI_Bit(wPhysChan,1); } } else{ wBytesLeft=0; } break; /*----------------------------------------------------------------------------* *FrameSyncAquired,LookingforCRC* *----------------------------------------------------------------------------*/ caseMF_INSYNC_DATA_3 if(wBytesLeft>=64){ wBytesLeft-=64; wIndex=(wIndex+64)&0x3FFF; pCdPtr->ubMF_State=MF_INSYNC_DATA_0; pCdPtr->ubMF_RxCrc=pubBuffer[wIndex]; } else{ wBytesLeft=0; } break; default /*WeShouldNEVERGetHere*/ break; }}pCdPtr->wMF_Index=wIndex;return(boMsgSent);}/*******************************************************************************************RoutineNameCheckNewMessage()****DescriptionThisfunctionchecksifavaildnewmessagehasbeen**receivedontheinfochannel.****ParameterswPhysChan(I)Channelnumbertooperateon**ubMsgId(I)PrimCodetosendifaInfoChanMsgfound****ReturnValueN/A*********************************************************************************************/PUBLICBooleanCheckNewMessage(Int16wPhysChan,Uint8ubMsgId){ registerBooleanboSend; registerInt16wIndex; registerUint8*pubFrame; registerUint8*pubLast; registerUint8*pubVote; ChannelData*DCdPtr;Uint8ubVote[16]; /*----------------------------------------------------------------------------* *InitializeVariables* *----------------------------------------------------------------------------*/ boSend=TRUE; pCdPtr=&ChanData[PhysToBuff(wPhysChan)]; wIndex=wIndex; /*----------------------------------------------------------------------------* *Isthisavalidframe?* *----------------------------------------------------------------------------*/ pubFrame=pCdPtr->ubIC_Frame[pCdPtr->ubIC_BuffIndex]; pubLast=pCdPtr->ubIC_Last; /*Notes *1.wecastthepointertolongsandthedothemaskandcompare *withlongs.Thiscodeisuglybutitisabout8timesfaster *thantheequivalentloop. *2.ThiscodeonlyworksonBigEndianmachines.ForLittle *Endianmachines,byteswapthemasksandcomparevalues. */ if((((((Uint32*)pubFrame))&0xFFB18181)?。?x7F818181)|| (((((Uint32*)pubFrame)[1])&0x81818181)!=0x81818181)|| (((((uint32*)pubFrame)[2])&0xE1E1E1E1)?。?x81E1E1E1)|| (((((Uint32*)pubFrame)[3])&0xE1E1E1E1)?。?xE1E1E1E1)){ boSend=FALSE; } /*-----------------------------------------------------------------------------* *Isthismessagethesameasthelast?* *-----------------------------------------------------------------------------*/ if(boSend){ pubLast=pCdPtr->ubIC_Last; /*Note *1.Wecastthepointerstolongsandthedotheandcompare *withlongs.Thiscodeisuglybutitisabout3timesfaster *thantheequivalentloop. *2.ThestateoftheRIbitisignored. */ if(((((Uint32*)pubFrame))==(((Uint32*)pubLast)))&& ((((Uint32*)pubFrame)[1]&0xFFFFBFFF)==(((Uint32*)pubLast)[1]&0xFFFFBFFF))&& ((((Uint32*)pubFrame)[2])==(((Uint32*)pubLast)[2]))&& ((((Uint32*)pubFrame)[3])==(((Uint32*)pubLast)[3]))){ boSend=FALSE; pCdPtr->ubIC_BuffIndex=0; } } /*----------------------------------------------------------------------------------* *Wehavereceivedthreemessages,dothevote* *----------------------------------------------------------------------------------*/ if(boSend){ if(pCdPtr->ubIC_BuffIndex>=2){ pCdPtr->ubIC_BuffIndex=0;pubFrame=pCdPtr->ubIC_Frame; pubVote=ubVote; /*Notes *1.Thiscodeisuglybutitisabout4timesfaster *thantheequivalent"C"code. *2.Forthefollowingcodetowork,wIndex,pubFrameand *pubVotemustberegistervaraibles. */ asm("clr.1`wIndex`"); asm("clr.1`boSend`"); asm("VoteLoopmove.1(`pubFrame`,`wIndex`),D0"); asm("and.1(16,`pubFrame`,`wIndex`),D0"); asm("move.1(16,`pubFrame`,`wIndex`),D1"); asm("and.1(32,`pubFrame`,`wIndex`),D1"); asm("or.1D0,D1"); asm("move.1(`pubFrame`,`wIndex`),D0"); asm("and.1(32,`pubFrame`,`wIndex`),D0"); asm("or.1D1,D0"); asm("move.1D0,(`pubVote`,`wIndex`)"); asm("sub.1(`pubLast`,`wIndex`),D0"); asm("or.1D0,`boSend`"); asm("addq.1#4,`wIndex`"); asm("cmpi.1#16,`wIndex`"); asm("bltVoteLoop"); asm("tst.1`boSend`"); asm("sne`boSend`"); asm("andi.1#1,`boSend`"); } else{ pCdPtr->ubIC_BuffIndex++; boSend=FALSE; } } /*-----------------------------------------------------------------------------------------* *SendtheMessagetotheBondingProcess* *-----------------------------------------------------------------------------------------*/ if(boSend){ memcpy(pubLast,pubVote,16); PostInfoMsg(wPhysChan,ubMsgId,0); } return(boSend);}/***************************************************************************************************RoutineNamePostInfoMsg()****DescriptionThisroutineformatsandsendsamessagetothebonding**taskwiththemostrecentlyfoundinfochannelmessage.****ParameterswPhysChan(I)Channelnumbertooperateon**ubMsgId(I)PrimCodetosendifaInfoChanMsgfound**ubRetCode(I)ReturnCodeforMessage****ReturnValueN/A*************************************************************************************************/PUBLICvoidPostInfoMsg(Int16wPhysChan,Uint8ubMsgId,Uint8ubRetCode){ registerChannelData*pCdPtr; registerIMUXMsg*pMsg; Int16wStatus; pCdPtr=&ChanData[PhysToBuff(wPhysChan)]; pMsg=GetIMUXblock(&wstatus); if(wStatus==Ret_Ok){ memset(pMsg,0,sizeof(IMUXMsg)); memcpy(&pMsg->IMUXData.DspMsg.data.info,pCdPtr->ubIC_Last,16); pMsg->IMUXData.DspMsg.ubLength=22; pMsg->IMUXData.DspMsg.ubPrimcode=ubMsgId; pMsg->IMUXData.DspMsg.ubDs0=pCdPtr->ubDS0; pMsg->IMUXData.DspMsg.ubInterfacs=pCdPtr->ubInterface; pMsg->IMUXData.DspMsg.ubSession=pCdPtr->ubSession; pMsg->IMUXData.DspMsg.ubRetcode=ubRetCcde; pMsg->ubPrimcode=BondingDspMsg; pMsg->ubSession=pCdPtr->ubSession; pMsg->ubDspTSlot=wPhysChan; pMsg->ubStartDs0=PhysToBuff(wPhysChan)&0x01; pMsg->ubInterface=PhysToBuff(wPhysChan)>>1; sc_qpost(IMUX_Rx_Queue,(Uinc8*)pMsg,&wStatus); if(wStatus?。絉et_Ok){ ReleaseIMUXblock(pMsg); trap(SC_QPOST,wStatus,NULL); } }}/************************************************************************************************RoutineNameGenBufferNego()****DescriptionThisfunctionfillstheTxbufferwiththemasterchannel**infochannelframe.****ParameterswPhysChan(I)ThechanneltoganeratetheDatafor**pubInfoChannel(I)TheinfochannelData****ReturnValueN/A**************************************************************************************************/PUBLICvoidGenBufferNego(Int16wPhysChan,Uina8*pubInfoChannal){ Uint8*pTxBuffer;/*PointertotheTxBuffer*/pTxBuffer=(Uint8*)BondBuffer[PhysToBuff(wPhysChan)][TX_BUFFER]; memcpy(pTxBuffer,pubInfoChannel,16); memcpy(pTxBuffer+16,pTxBuffer,BUFFER_BYTES-16); ChanData[PhysToBuff(wPhysChan)].ubTxChanId=(pubInfoChannel[1]>>1)&0x3F;}/******************************************************************************************RoutineNameGenBufferTraining()****DescriptionThisfunctionfillstheTxbufferwiththetrainingpattern****ParameterswPhysChan(I)ThechanneltogeneratetheDatafor**pubInfoChannel(I)TheinfochannelData**ubA_Bit(I)Thestatetosetthe"A"bitto.**ubE_Bit(I)Thestatetosatthe"E"bitto.****ReturnValueN/A********************************************************************************************/PUBLICvoidGenBufferTraining(Int16wPhysChan,Uint8*pubInfoChannel, Uint8ubA_Bit,Uint8ubE_Bit){ /*-----------------------------------------------------------------------------------* *Fillbufferwithallonesandgeneratetrainingpattern* *-----------------------------------------------------------------------------------*/ memset(BondBuffer[PhysToBuff(wPhysChan)][TX_BUFFER],0xFF,BUFFER_BYTES); UpdateBufferTraining(wPhysChan,pubInfoChannel,ubA_Bit,ubE_Bit,TX_BUFFER);}/******************************************************************************************RoutineNameUpdateBufferTraining()****DescriptionThisfunctionupdatesthetrainingpatterninthetxbuffer****ParameterswPhysChan(I)ThechanneltogeneratetheDatafor**pubInfoChannel(I)TheinfochannelData**ubA_Bit(I)Thestatetosetthe"A"bitto.**ubE_Bit(I)Thestatetosetthe"E"bitto.**ubDir(I)Thisindicateswhichbuffertoputthe**datainto.**ReturnValueN/A****NotesTheubDirargumentshouldnormallyalwaysbesettoTX_BUFFER.**Thisargumentallowsustogeneratethebufferfordebugandtest.********************************************************************************************/PUBLICvoidUpdateBufferTraining(Int16wPhysChan,Uint8*pubInfoChannel, Uint8ubA_Bit,Uint8ubE_Bit,Uint8ubDir){ Uint8*pTxBuffer;/*PointertotheTxBuffer*/ Uint8ubChanId;/*ChannelIDforthebuffer*/ Uint8ubCrc;/*CRC,A&EBits*/ Uint8ubFrameCount;/*CurrentFrameCounter*/Iht16wInfoIndex;/*IndexintoInfoChannelData*/ Int16wPatIndex;/*IndexintoMulti-FrameTrainingPattern*/ Int16wCounter;/*LoopCounter*/ /*--------------------------------------------------------------------------------* *Initializevariables* *--------------------------------------------------------------------------------*/ wInfoIndex=0; ubFrameCount=0x81; ubCrc=((ubA_Bit==0)?00x40)| ((ubE_Bit==0)?00x20)|0x9F; ubChanId=(pubInfoChannel[1]>>1)&0x3F; pTxBuffer=(Uint8*)BondBuffer[PhysToBuff(wPhysChan)][ubDir]; ChanData[PhysToBuff(wPhysChan)].ubTxChanId=ubChanId; /*--------------------------------------------------------------------------------* *FillintheFrameStructure* *--------------------------------------------------------------------------------*/ for(wCounter=0;wCounter<BUFFER_BYTES;wCounter+=256){ wPatIndex=(wCounter+ubChanId)%BUFFER_BYTES; pTxBuffer[wPatIndex+0]=0x1B; pTxBuffer[wPatIndex+64]=pubInfoChannel[wInfoIndex++]; pTxBuffer[wPatIndex+128]=ubFrameCount; pTxBuffer[wPatIndex+192]=ubCrc; wInfoIndex&=0x000F; ubFrameCount+=2; }}/*******************************************************************************************RoutineNameSet_A_Bit()****DescriptionThisfunctionupdatesthetrainingpatterninthetxbuffer****ParameterswPhysChan(I)ThechanneltogeneratetheDatafor**ubA_Bit(I)Thestatetosetthe"A"bitto.****ReturnValueN/A*********************************************************************************************/PUBLICvoidSet_A_Bit(Int16wPhysChan,Uint8ubA_Bit){ Uint8*pTxBuffer;/*PointertotheTxBuffer*/ Uint8ubChanId;/*ChannelIDforthebuffer*/ Uint8ubCrc;/*CRC,A&EBits*/ Int16wPatIndex;/*IndexintoMulti-FrameTrainingPattern*/ Int16wCounter;/*LoopCounter*/ /*------------------------------------------------------------------------------------* *Initializevariables* *------------------------------------------------------------------------------------*/ ubA_Bit=((ubA_Bit==0)?00x40); pTxuuffer=(UintB*)BondBuffer[PhysToBuff(wPhysChan)][TX_BUFFER]; ubChanId=ChanData[PhysToBuff(wPhysChan)].ubTxChanId; ubCrc=pTxBuffer[ubChanId+192]&0xBF|ubA_Bit;/*----------------------------------------------------------------------------* *FillintheFrameStructure* *----------------------------------------------------------------------------*/ for(wCounter=0;wCounter<BUFFER_BYTES;wCounter+=256){ wPatIndex=(wCounter+ubChanId)%BUFFER_BYTES; pTxBuffer[wPatIndex+192]=ubCrc; }}/*****************************************************************************************RoutineNameSet_RI_Bit()****DescriptionThisfunctionupdatesthetrainingpatterninthetxbuffer****ParameterswPhysChan(I)ThechanneltogeneratetheDatafor**ubRI_Bit(I)Thestatetosetthe"A"bitto.****ReturnValueN/A*******************************************************************************************/PUBLICvoidSet_RI_Bit(Int16wPhysChan,Uint8ubRI_Bit){ UintB*pTxBuffer;/*PointertotheTxBuffer*/ Uint8ubRev;/*Newvaluefor"rev"byteinInfoChannel*/ Uint8ubChanId;/*ChannelIDforthebuffer*/ Int16wPatIndex;/*IndexintoMulti-FrameTrainingPattern*/ Int16wCounter;/*LoopCounter*/ /*----------------------------------------------------------------------------------* *Initializevariables* *----------------------------------------------------------------------------------*/ ubRI_Bit=((ubRI_Bit==0)?00x40); pTxBUffer=(Uint8*)BondBuffer[PhysToEuff(wPhysChan)][TX_BUFFER]; ubChanId=ChanData[PhysToBuff(wPhysChan)].ubTxChanId; wPatIndex=(1600+ubChanId)%BUFFER_BYTES; ubRev=pTxBuffer[wPatIndex]&0xBF|ubRI_Bit; /*----------------------------------------------------------------------------------* *FillintheFrameStructure* *----------------------------------------------------------------------------------*/ for(wCounter=0;wCounter<BUFFER_BYTES;wCounter+=4096){ wPatIndex=(wCounter+1600+UbChanId)%BUFFER_BYTES; pTxBuffer[wPatIndex]=ubRev; }}Exchange.147760_1.wpd]]></pre>權(quán)利要求1.一種對多條信道數(shù)據(jù)執(zhí)行逆多路傳送的方法,該方法包括下述步驟接收多條信道數(shù)據(jù),各信道在其數(shù)據(jù)中包含計數(shù);將各信道數(shù)據(jù)存儲在多個緩沖器的各自的一個中;根據(jù)信道數(shù)據(jù)中的計數(shù)確定多個緩沖器的每一個的外出指針的偏移;以及按照外出指針從該多個緩沖器的每一個中讀出數(shù)據(jù)。2.按照權(quán)利要求1的方法,其中該確定步驟根據(jù)緩沖器中的信道數(shù)據(jù)的計數(shù)與基準緩沖器中信道數(shù)據(jù)的計數(shù)之差確定緩沖器的外出指針。3.按照權(quán)利要求2的方法,還包括生成多個緩沖器的進入指針及將從各信道接收的數(shù)據(jù)存儲在對應(yīng)于該信道的進入指針的位置上。4.按照權(quán)利要求3的方法,其中各緩沖器的進入指針的初始值對應(yīng)于從對應(yīng)信道初始接收數(shù)據(jù)期間的主幀計數(shù)。5.按照權(quán)利要求1的方法,其中該讀步驟包括從多個緩沖器中讀出數(shù)據(jù)到輸出緩沖器,輸出緩沖器中的數(shù)據(jù)具有被逆多路傳送的特性以便補償信道數(shù)據(jù)之間的延時。6.按照權(quán)利要求5的方法,還包括確定從信道接收的數(shù)據(jù)是否已交叉;以及其中在兩或多條信道數(shù)據(jù)已交叉的情況中,以按信道重新排序數(shù)據(jù)的序列從多個緩沖器中讀出數(shù)據(jù)以便校正信道交叉。7.按照權(quán)利要求6的方法,其中該讀步驟通過在輸出緩沖器的預(yù)定位置中存儲來自各自的信道的數(shù)據(jù)來重新排序數(shù)據(jù)。8.按照權(quán)利要求1的方法,其中該存儲步驟包含在將來自信道的數(shù)據(jù)存儲在多個緩沖器的各自的一個中之前等待至少一幀。9.一種對多條信道數(shù)據(jù)執(zhí)行逆多路傳送的網(wǎng)絡(luò)接口卡(NIC),該NIC包括多個緩沖器,各緩沖器用于存儲一條信道數(shù)據(jù),各信道在其數(shù)據(jù)中包含計數(shù);以及執(zhí)行下述進程步驟的控制器,以便(i)根據(jù)信道數(shù)據(jù)中的計數(shù)確定該多個緩沖器的每一個的外出指針;以及(ii)按照外出指針從該多個緩沖器的每一個中讀出數(shù)據(jù);其中偏移這些外出指針來補償信道間延時。10.按照權(quán)利要求9的NIC,其中該控制器包括微處理器的串行通信控制器。11.按照權(quán)利要求10的NIC,其中該控制器還執(zhí)行進程步驟以便為多個緩沖器確定進入指針。12.按照權(quán)利要求11的NIC,其中各緩沖器的進入指針的初始值對應(yīng)于在從對應(yīng)的信道初始接收數(shù)據(jù)期間的主幀計數(shù)。13.按照權(quán)利要求9的NIC,還包括輸出緩沖器;其中該控制器從多個緩沖器中讀出數(shù)據(jù)到該輸出緩沖器中,輸出緩沖器中的數(shù)據(jù)具有被逆多路傳送的特性以便補償信道數(shù)據(jù)之間的延時。14.按照權(quán)利要求13的NIC,其中該控制器執(zhí)行進程步驟來確定信道數(shù)據(jù)是否已交叉;以及其中在兩或多條信道數(shù)據(jù)已交叉的情況中,當(dāng)從多個緩沖器中讀出數(shù)據(jù)時,該控制器按信道重新排序數(shù)據(jù)以便校正信道交叉。15.按照權(quán)利要求14的NIC,其中該控制器通過將來自各自的信道的數(shù)據(jù)存儲在輸出緩沖器的預(yù)定位置上來重新排序數(shù)據(jù)。16.按照權(quán)利要求9的NIC,其中在接收各信道數(shù)據(jù)時,控制器在將數(shù)據(jù)存儲在多個緩沖器中各自的一個中之前等待一或多幀。17.按照權(quán)利要求9的NIC,還包括接口到對應(yīng)于各信道數(shù)據(jù)的ISDN線路上的多個接口;以及將各信道數(shù)據(jù)的路由選擇到來自接口在多個接口芯片與該FPGA之間的總線的SCC上的現(xiàn)場可編程門陣列(FPGA)。18.存儲在計算機可讀的介質(zhì)上的計算機可執(zhí)行進行程步驟,這些計算機可執(zhí)行進程步驟對多個信道數(shù)據(jù)執(zhí)行逆多路傳送,這些計算機可執(zhí)行進程步驟包括接收多個信道數(shù)據(jù)的代碼,各信道在其數(shù)據(jù)中包含計數(shù);將各信道數(shù)據(jù)存儲在多個緩沖器中各自的一個中的代碼;根據(jù)信道數(shù)據(jù)中的計數(shù)確定多個緩沖器中每一個的外出指針的代碼;以及按照外出指針從該多個緩沖器的每一個讀出數(shù)據(jù)的代碼;其中該確定代碼確定外出指針以便補償信道間延時。19.按照權(quán)利要求18的計算機可執(zhí)行進程步驟,還包括生成多個緩沖器的進入指針的代碼。20.按照權(quán)利要求20的計算機可執(zhí)行進程步驟,其中各緩沖器的進入指針的初始值對應(yīng)于從對應(yīng)的信道初始接收數(shù)據(jù)期間的主幀計數(shù)。21.按照權(quán)利要求18的計算機可執(zhí)行進程步驟,其中該讀代碼從多個緩沖器中讀出數(shù)據(jù)到輸出緩沖器中,輸出緩沖器中的數(shù)據(jù)具有被逆多路傳送的特性以便補償信道數(shù)據(jù)之間的延時。22.按照權(quán)利要求21的計算機可執(zhí)行進程步驟,還包括確定信道數(shù)據(jù)是否已交叉的代碼;以及其中在兩或多條信道數(shù)據(jù)已交叉的情況中,當(dāng)從多個緩沖器中讀出數(shù)據(jù)時,讀代碼按信道重新排序數(shù)據(jù)以便校正信道交叉。23.按照權(quán)利要求27的計算機可執(zhí)行進程步驟,其中該讀代碼通過將來自各自的信道的數(shù)據(jù)存儲在輸出緩沖器的預(yù)定位置中來重新排序數(shù)據(jù)。24.按照權(quán)利要求30的計算機可執(zhí)行進程步驟,其中在接收代碼接收各信道數(shù)據(jù)時,存儲代碼在將數(shù)據(jù)存儲在多個緩沖器中各自的一個中之前等待信道中的一或多個數(shù)據(jù)幀。25.按照權(quán)利要求18的計算機可執(zhí)行進程步驟,其中該接收代碼接收來自對應(yīng)的ISDN線路的各信道數(shù)據(jù)。26.按照權(quán)利要求18的計算機可執(zhí)行進程步驟,其中該接收、存儲、確定、及讀代碼是至少部分地在網(wǎng)絡(luò)接口卡(NIC)上的微處理器的串行通信控制器(SCC)上執(zhí)行的。27.按照權(quán)利要求18的方法,其中該接收、存儲、確定、與讀步驟是至少部分地在網(wǎng)絡(luò)接口卡(NIC)上的微處理器的串行通信控制器(SCC)上執(zhí)行的。全文摘要一種用于改進多信道ISDN通信的逆多路傳送的網(wǎng)絡(luò)接口卡(NIC)(23),包含控制器(91)及各存儲來自各自的信道數(shù)據(jù)的多個緩沖器(92)。NIC生成該多個緩沖器中每一個的外出指針并根據(jù)從這些信道接收及存儲在各自的緩沖器中的幀計數(shù)數(shù)據(jù)將其偏移。NIC按照外出指針從該多個緩沖器的每一個中讀取數(shù)據(jù),借此校正數(shù)據(jù)中的信道間延時。還從補償信道交叉的序列中的指針上讀取數(shù)據(jù)。文檔編號H04J3/04GK1328727SQ99809521公開日2001年12月26日申請日期1999年6月11日優(yōu)先權(quán)日1998年6月12日發(fā)明者戴維·P·奧利韋拉申請人:泰爾考系統(tǒng)公司