amazon_tpe.c 92 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074
  1. /*
  2. * This program is free software; you can redistribute it and/or modify
  3. * it under the terms of the GNU General Public License as published by
  4. * the Free Software Foundation; either version 2 of the License, or
  5. * (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program; if not, write to the Free Software
  14. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  15. */
  16. //-----------------------------------------------------------------------
  17. /*
  18. * Description:
  19. * Driver for Infineon Amazon TPE
  20. */
  21. //-----------------------------------------------------------------------
  22. /* Author: [email protected]
  23. * Created: 12-April-2004
  24. */
  25. //-----------------------------------------------------------------------
  26. /* History
  27. * Last changed on: 13 Oct. 2004
  28. * Last changed by: [email protected]
  29. * Last changed on: 28 Jan. 2004
  30. * Last changed by: [email protected]
  31. * Last changed Reason:
  32. * - AAL5R may send more bytes than expected in MFL (so far, confirmed as 64 bytes)
  33. */
  34. // 507261:tc.chen 2005/07/26 re-organize code address map to improve performance.
  35. // 507281:tc.chen 2005/07/28 fix f4 segment isssue
  36. /* 511045:linmars 2005/11/04 from Liu.Peng: change NRT_VBR bandwidth calculation based on scr instead of pcr */
  37. #ifndef __KERNEL__
  38. #define __KERNEL__
  39. #endif
  40. #ifndef EXPORT_SYMTAB
  41. #define EXPORT_SYMTAB
  42. #endif
  43. /*TPE level loopback, bypass AWARE DFE */
  44. #undef TPE_LOOPBACK
  45. /* enable debug options */
  46. #undef AMAZON_ATM_DEBUG
  47. /* enable rx error packet analysis */
  48. #undef AMAZON_ATM_DEBUG_RX
  49. /* test AAL5 Interrupt */
  50. #undef AMAZON_TPE_TEST_AAL5_INT
  51. /* dump packet */
  52. #undef AMAZON_TPE_DUMP
  53. /* read ARC register*/
  54. /* this register is located in side DFE module*/
  55. #undef AMAZON_TPE_READ_ARC
  56. /* software controlled reassembly */
  57. #undef AMAZON_TPE_SCR
  58. /* recovery from AAL5 bug */
  59. #undef AMAZON_TPE_AAL5_RECOVERY
  60. #if defined(AMAZON_TPE_READ_ARC) || defined(AMAZON_TPE_AAL5_RECOVERY)
  61. #define ALPHAEUS_BASE_ADDR 0x31c00
  62. #define A_CFG_ADDR (ALPHAEUS_BASE_ADDR+0x04)
  63. #define AR_CB0_STATUS_ADDR (ALPHAEUS_BASE_ADDR+0x2c)
  64. #define AR_CB1_STATUS_ADDR (ALPHAEUS_BASE_ADDR+0x30)
  65. #define AT_CELL0_ADDR (ALPHAEUS_BASE_ADDR+0x90)
  66. #define AR_CELL0_ADDR (ALPHAEUS_BASE_ADDR+0x1a0)
  67. #define AR_CD_CNT0_ADDR (ALPHAEUS_BASE_ADDR+0x1c8)
  68. #endif
  69. #include <linux/module.h>
  70. #include <linux/config.h>
  71. #include <linux/init.h>
  72. #include <linux/kernel.h>
  73. #include <linux/slab.h>
  74. #include <linux/fs.h>
  75. #include <linux/types.h>
  76. #include <linux/errno.h>
  77. #include <linux/time.h>
  78. #include <linux/atm.h>
  79. #include <linux/atmdev.h>
  80. #include <linux/netdevice.h>
  81. #include <asm/byteorder.h>
  82. #include <asm/io.h>
  83. #include <asm/uaccess.h>
  84. #include <asm/system.h>
  85. #include <asm/atomic.h>
  86. #include <asm/bitops.h>
  87. #include <asm/system.h>
  88. #include <asm/amazon/amazon.h>
  89. #include <asm/amazon/irq.h>
  90. #include <linux/in.h>
  91. #include <linux/netdevice.h>
  92. #include <linux/etherdevice.h>
  93. #include <linux/ip.h>
  94. #include <linux/tcp.h>
  95. #include <linux/skbuff.h>
  96. #include <linux/in6.h>
  97. #include <linux/delay.h>
  98. #include <asm/amazon/atm_defines.h>
  99. #include <asm/amazon/amazon_dma.h>
  100. #include <asm/amazon/amazon_tpe.h>
  101. #if defined(AMAZON_TPE_READ_ARC) || defined(AMAZON_TPE_AAL5_RECOVERY)
  102. #include <asm/amazon/amazon_mei.h>
  103. #include <asm/amazon/amazon_mei_app.h>
  104. #endif
  105. #define AMAZON_TPE_EMSG(fmt, args...) printk( KERN_ERR "%s: " fmt,__FUNCTION__, ## args)
  106. /***************************************** External Functions *******************************************/
  107. extern unsigned int amazon_get_fpi_hz(void);
  108. extern void mask_and_ack_amazon_irq(unsigned int irq_nr);
  109. extern void amz_push_oam(unsigned char *);
  110. //amazon_mei.c
  111. #if defined(AMAZON_TPE_READ_ARC) || defined(AMAZON_TPE_AAL5_RECOVERY)
  112. extern MEI_ERROR meiDebugRead(u32 srcaddr, u32 *databuff, u32 databuffsize);
  113. extern MEI_ERROR meiDebugWrite(u32 destaddr, u32 *databuff, u32 databuffsize);
  114. #endif
  115. /***************************************** Internal Functions *******************************************/
  116. int amazon_atm_read_procmem(char *buf, char **start, off_t offset,int count, int *eof, void *data);
  117. /***************************************** Global Data *******************************************/
  118. amazon_atm_dev_t g_atm_dev; //device data
  119. static struct tq_struct swex_start_task; //BH task
  120. static struct tq_struct swex_complete_task; //BH task
  121. #ifdef AMAZON_TPE_SCR
  122. static struct tq_struct a5r_task; //BH task
  123. #endif
  124. static struct dma_device_info g_dma_dev; //for DMA
  125. static struct atm_dev * amazon_atm_devs[AMAZON_ATM_PORT_NUM];
  126. static struct oam_last_activity g_oam_time_stamp[AMAZON_ATM_MAX_VCC_NUM];
  127. static u8 g_oam_cell[AMAZON_AAL0_SDU+4]; //for OAM cells
  128. #ifdef AMAZON_CHECK_LINK
  129. static int adsl_link_status; //ADSL link status, 0:down, 1:up
  130. #endif //AMAZON_CHECK_LINK
  131. /***************************************** Module Parameters *************************************/
  132. // Parameter Definition for module
  133. static int port_enable0 = 1; // Variable for parameter port_enable0
  134. static int port_enable1 = 0; // Variable for parameter port_enable1
  135. static int port_max_conn0 = 15; // Variable for parameter port_max_conn0
  136. static int port_max_conn1 = 0; // Variable for parameter port_max_conn1
  137. static int port_cell_rate_up0 = 7500; // Variable for parameter port_cell_rate_up0
  138. static int port_cell_rate_up1 = 7500; // Variable for parameter port_cell_rate_up1
  139. static int qsb_tau = 1; // Variable for parameter qsb_tau
  140. static int qsb_srvm = 0xf; // Variable for parameter qsb_srvm
  141. static int qsb_tstep = 4 ; // Variable for parameter qsb_tstep
  142. static int cbm_nrt = 3900; // Variable for parameter cbm_nrt
  143. static int cbm_clp0 =3500; // Variable for parameter cbm_clp0
  144. static int cbm_clp1 =3200; // Variable for parameter cbm_clp1
  145. static int cbm_free_cell_no = AMAZON_ATM_FREE_CELLS; // Variable for parameter cbm_free_cell_no
  146. static int a5_fill_pattern = 0x7e; // Variable for parameter a5_fill_pattern '~'
  147. static int a5s_mtu = 0x700; // mtu for tx
  148. static int a5r_mtu = 0x700; // mtu for rx
  149. static int oam_q_threshold = 64; // oam queue threshold, minium value 64
  150. static int rx_q_threshold = 1000; // rx queue threshold, minium value 64
  151. static int tx_q_threshold = 800; // tx queue threshold, minium value 64
  152. MODULE_PARM(port_max_conn0, "i");
  153. MODULE_PARM_DESC(port_max_conn0, "Maximum atm connection for port #0");
  154. MODULE_PARM(port_max_conn1, "i");
  155. MODULE_PARM_DESC(port_max_conn1, "Maximum atm connection for port #1");
  156. MODULE_PARM(port_enable0, "i");
  157. MODULE_PARM_DESC(port_enable0, "0 -> port disabled, 1->port enabled");
  158. MODULE_PARM(port_enable1, "i");
  159. MODULE_PARM_DESC(port_enable1, "0 -> port disabled, 1->port enabled");
  160. MODULE_PARM(port_cell_rate_up0, "i");
  161. MODULE_PARM_DESC(port_cell_rate_up0, "ATM port upstream rate in cells/s");
  162. MODULE_PARM(port_cell_rate_up1, "i");
  163. MODULE_PARM_DESC(port_cell_rate_up1, "ATM port upstream rate in cells/s");
  164. MODULE_PARM(qsb_tau,"i");
  165. MODULE_PARM_DESC(qsb_tau, "Cell delay variation. value must be > 0");
  166. MODULE_PARM(qsb_srvm, "i");
  167. MODULE_PARM_DESC(qsb_srvm, "Maximum burst size");
  168. MODULE_PARM(qsb_tstep, "i");
  169. MODULE_PARM_DESC(qsb_tstep, "n*32 cycles per sbs cycles n=1,2,4");
  170. MODULE_PARM(cbm_nrt, "i");
  171. MODULE_PARM_DESC(cbm_nrt, "Non real time threshold for cell buffer");
  172. MODULE_PARM(cbm_clp0, "i");
  173. MODULE_PARM_DESC(cbm_clp0, "Threshold for cells with cell loss priority 0");
  174. MODULE_PARM(cbm_clp1, "i");
  175. MODULE_PARM_DESC(cbm_clp1, "Threshold for cells with cell loss priority 1");
  176. MODULE_PARM(cbm_free_cell_no, "i");
  177. MODULE_PARM_DESC(cbm_free_cell_no, "Number of cells in the cell buffer manager");
  178. MODULE_PARM(a5_fill_pattern, "i");
  179. MODULE_PARM_DESC(a5_fill_pattern, "filling pattern (PAD) for aal5 frames");
  180. MODULE_PARM(a5s_mtu, "i");
  181. MODULE_PARM_DESC(a5s_mtu, "max. SDU for upstream");
  182. MODULE_PARM(a5r_mtu, "i");
  183. MODULE_PARM_DESC(a5r_mtu, "max. SDU for downstream");
  184. MODULE_PARM(oam_q_threshold, "i");
  185. MODULE_PARM_DESC(oam_q_threshold, "oam queue threshold");
  186. MODULE_PARM(rx_q_threshold, "i");
  187. MODULE_PARM_DESC(rx_q_threshold, "downstream/rx queue threshold");
  188. MODULE_PARM(tx_q_threshold, "i");
  189. MODULE_PARM_DESC(tx_q_threshold, "upstream/tx queue threshold");
  190. /***************************************** local functions *************************************/
  191. /* Brief: valid QID
  192. * Return: 1 if valid
  193. * 0 if not
  194. */
  195. static inline int valid_qid(int qid)
  196. {
  197. return ( (qid>0) && (qid<AMAZON_ATM_MAX_QUEUE_NUM));
  198. }
  199. /*
  200. * Brief: align to 16 bytes boundary
  201. * Parameter:
  202. * skb
  203. * Description:
  204. * use skb_reserve to adjust the data pointer
  205. * don't change head pointer
  206. * pls allocate extrac 16 bytes before call this function
  207. */
  208. static void inline alloc_align_16(struct sk_buff * skb)
  209. {
  210. if ( ( ((u32) (skb->data)) & 15) != 0){
  211. AMAZON_TPE_DMSG("need to adjust the alignment manually\n");
  212. skb_reserve(skb, 16 - (((u32) (skb->data)) & 15) );
  213. }
  214. }
  215. /*
  216. * Brief: initialize the device according to the module paramters
  217. * Return: not NULL - ok
  218. * NULL - fails
  219. * Description: arrange load parameters and call the hardware initialization routines
  220. */
  221. static void atm_init_parameters(amazon_atm_dev_t *dev)
  222. {
  223. //port setting
  224. dev->ports[0].enable = port_enable0;
  225. dev->ports[0].max_conn = port_max_conn0;
  226. dev->ports[0].tx_max_cr = port_cell_rate_up0;
  227. if (port_enable1){
  228. dev->ports[1].enable = port_enable1;
  229. dev->ports[1].max_conn = port_max_conn1;
  230. dev->ports[1].tx_max_cr = port_cell_rate_up1;
  231. }
  232. //aal5
  233. dev->aal5.padding_byte = a5_fill_pattern;
  234. dev->aal5.tx_max_sdu = a5s_mtu;
  235. dev->aal5.rx_max_sdu = a5r_mtu;
  236. //cbm
  237. dev->cbm.nrt_thr = cbm_nrt;
  238. dev->cbm.clp0_thr = cbm_clp0;
  239. dev->cbm.clp1_thr = cbm_clp1;
  240. dev->cbm.free_cell_cnt = cbm_free_cell_no;
  241. //qsb
  242. dev->qsb.tau = qsb_tau;
  243. dev->qsb.tstepc =qsb_tstep;
  244. dev->qsb.sbl = qsb_srvm;
  245. //allocate on the fly
  246. dev->cbm.mem_addr = NULL;
  247. dev->cbm.qd_addr = NULL;
  248. }
  249. /* Brief: Find QID for VCC
  250. * Parameters: vcc - VCC data structure
  251. * Return Value: -EINVAL - VCC not found
  252. * qid - QID for this VCC
  253. * Description:
  254. * This function returns the QID of a given VCC
  255. */
  256. static int amazon_atm_get_queue(struct atm_vcc* vcc)
  257. {
  258. int i;
  259. for (i=0;i<AMAZON_ATM_MAX_QUEUE_NUM;i++) {
  260. if (g_atm_dev.queues[i].vcc == vcc) return i;
  261. }
  262. return -EINVAL;
  263. }
  264. /*
  265. * Brief: Find QID for VPI/VCI
  266. * Parameters: vpi - VPI to found
  267. * vci - VCI to found
  268. *
  269. * Return Value: -EINVAL - VPI/VCI not found
  270. * qid - QID for this VPI/VCI
  271. *
  272. * Description:
  273. * This function returns the QID for a given VPI/VCI. itf doesn't matter
  274. */
  275. static int amazon_atm_find_vpivci(u8 vpi, u16 vci)
  276. {
  277. int i;
  278. struct atm_vcc * vcc;
  279. for (i=0;i<AMAZON_ATM_MAX_QUEUE_NUM;i++) {
  280. if ( (vcc = g_atm_dev.queues[i].vcc)!= NULL) {
  281. if ((vcc->vpi == vpi) && (vcc->vci == vci)) return i;
  282. }
  283. }
  284. return -EINVAL;
  285. }
  286. /* Brief: Find QID for VPI
  287. * Parameters: vpi - VPI to found
  288. * Return Value: -EINVAL - VPI not found
  289. * qid - QID for this VPI
  290. *
  291. * Description:
  292. * This function returns the QID for a given VPI. itf and VCI don't matter
  293. */
  294. static int amazon_atm_find_vpi(u8 vpi)
  295. {
  296. int i;
  297. for (i=0;i<AMAZON_ATM_MAX_QUEUE_NUM;i++) {
  298. if ( g_atm_dev.queues[i].vcc!= NULL) {
  299. if (g_atm_dev.queues[i].vcc->vpi == vpi) return i;
  300. }
  301. }
  302. return -EINVAL;
  303. }
  304. /*
  305. * Brief: Clears QID entries for VCC
  306. *
  307. * Parameters: vcc - VCC to found
  308. *
  309. * Description:
  310. * This function searches for the given VCC and sets it to NULL if found.
  311. */
  312. static inline void amazon_atm_clear_vcc(int i)
  313. {
  314. g_atm_dev.queues[i].vcc = NULL;
  315. g_atm_dev.queues[i].free = 1;
  316. }
  317. /*
  318. * Brief: dump skb data
  319. */
  320. static inline void dump_skb(u32 len, char * data)
  321. {
  322. #ifdef AMAZON_TPE_DUMP
  323. int i;
  324. for(i=0;i<len;i++){
  325. printk("%2.2x ",(u8)(data[i]));
  326. if (i % 16 == 15)
  327. printk("\n");
  328. }
  329. printk("\n");
  330. #endif
  331. }
  332. /*
  333. * Brief: dump queue descriptor
  334. */
  335. static inline void dump_qd(int qid)
  336. {
  337. #ifdef AMAZON_TPE_DUMP
  338. u8 * qd_addr;
  339. if (valid_qid(qid) != 1) return;
  340. qd_addr = (u8 *) KSEG1ADDR((unsigned long)g_atm_dev.cbm.qd_addr);
  341. AMAZON_TPE_EMSG("qid: %u [%8x][%8x][%8x][%8x]\n", qid
  342. ,readl(qd_addr+qid*CBM_QD_SIZE+0x0)
  343. ,readl(qd_addr+qid*CBM_QD_SIZE+0x4)
  344. ,readl(qd_addr+qid*CBM_QD_SIZE+0x8)
  345. ,readl(qd_addr+qid*CBM_QD_SIZE+0xc));
  346. #endif
  347. }
  348. /*
  349. * Brief: release TX skbuff
  350. */
  351. static inline void amazon_atm_free_tx_skb_vcc(struct atm_vcc *vcc, struct sk_buff *skb)
  352. {
  353. if ( vcc->pop != NULL) {
  354. vcc->pop(vcc, skb);
  355. } else {
  356. dev_kfree_skb_any(skb);
  357. }
  358. }
  359. /*
  360. * Brief: release TX skbuff
  361. */
  362. static inline void amazon_atm_free_tx_skb(struct sk_buff *skb)
  363. {
  364. struct atm_vcc* vcc = ATM_SKB(skb)->vcc;
  365. if (vcc!=NULL){
  366. amazon_atm_free_tx_skb_vcc(vcc,skb);
  367. } else {
  368. dev_kfree_skb_any(skb);//fchang:Added
  369. }
  370. }
  371. /* Brief: divide by 64 and round up
  372. */
  373. static inline u32 divide_by_64_round_up(int input)
  374. {
  375. u32 tmp1;
  376. tmp1 = (u32) input;
  377. tmp1 = (tmp1%64)?(tmp1/64 + 1): (tmp1/64);
  378. if (tmp1 == 0) tmp1 = 1;
  379. return tmp1;
  380. }
  381. /*
  382. * Brief: statistics
  383. */
  384. #ifdef AMAZON_ATM_DEBUG
  385. static inline void queue_statics(int qid, qs_t idx)
  386. {
  387. if (valid_qid(qid)){
  388. g_atm_dev.queues[qid].qs[idx]++;
  389. }
  390. }
  391. #else //not AMAZON_ATM_DEBUG
  392. static inline void queue_statics(int qid, qs_t idx){}
  393. #endif //AMAZON_ATM_DEBUG
  394. /* Brief: set dma tx full, i.e. there is no available descriptors
  395. */
  396. static void inline atm_dma_full(void)
  397. {
  398. AMAZON_TPE_DMSG("ch0 is full\n");
  399. atomic_set(&g_atm_dev.dma_tx_free_0,0);
  400. }
  401. /*
  402. * Brief set dma tx free (at least one descript is available)
  403. */
  404. inline static void atm_dma_free(void)
  405. {
  406. AMAZON_TPE_DMSG("ch0 is free\n");
  407. atomic_set(&g_atm_dev.dma_tx_free_0,1);
  408. }
  409. /* Brief: return the status of DMA TX descriptors
  410. * Parameters: TX channel (DMA_TX_CH0, TX_CH1)
  411. * Return:
  412. * 1: there are availabel TX descriptors
  413. * 0: no available
  414. * Description:
  415. *
  416. */
  417. inline int dma_may_send(int ch)
  418. {
  419. if (atomic_read(&g_atm_dev.dma_tx_free_0)){
  420. return 1;
  421. }
  422. return 0;
  423. }
  424. /******************************* global functions *********************************/
  425. /*
  426. * Brief: SWIE Cell Extraction Start Routine
  427. * and task routine for swex_complete_task
  428. * Parameters: irq_stat - interrupt status
  429. *
  430. * Description:
  431. * This is the routine for extracting cell. It will schedule itself if the hardware is busy.
  432. * This routine runs in interrupt context
  433. */
  434. void amazon_atm_swex(void * irq_stat)
  435. {
  436. u32 ex_stat=0;
  437. u32 addr;
  438. // Read extraction status register
  439. ex_stat = readl(CBM_HWEXSTAT0_ADDR);
  440. // Check if extraction/insertion is in progress
  441. if ( (ex_stat & CBM_EXSTAT_SCB) || (ex_stat & CBM_EXSTAT_FB) || (test_and_set_bit(SWIE_LOCK, &(g_atm_dev.swie.lock))!=0)) {
  442. AMAZON_TPE_DMSG(" extraction in progress. Will wait\n");
  443. swex_start_task.data = irq_stat;
  444. queue_task(&swex_start_task, &tq_immediate);
  445. mark_bh(IMMEDIATE_BH);
  446. }else {
  447. // Extract QID
  448. g_atm_dev.swie.qid = (((u32)irq_stat) >> 24);
  449. AMAZON_TPE_DMSG("extracting from qid=%u\n",g_atm_dev.swie.qid);
  450. //read status word
  451. addr = KSEG1ADDR((unsigned long)g_atm_dev.cbm.qd_addr);
  452. addr = readl((addr + g_atm_dev.swie.qid * 0x10 + 4) & 0xFFFFFFC0);
  453. addr = KSEG1ADDR(addr);
  454. g_atm_dev.swie.sw = readl(addr+52)&SWIE_ADDITION_DATA_MASK;
  455. AMAZON_TPE_DMSG("cell addition word: %8x \n", g_atm_dev.swie.sw);
  456. // Start extraction
  457. AMAZON_WRITE_REGISTER_L(g_atm_dev.swie.qid | SWIE_CBM_PID_SUBADDR, CBM_HWEXPAR0_ADDR);
  458. AMAZON_WRITE_REGISTER_L(SWIE_CBM_SCE0, CBM_HWEXCMD_ADDR);
  459. }
  460. }
  461. #ifdef AMAZON_TPE_SCR
  462. u32 g_a5r_wait=0;
  463. /*
  464. * Brief: AAL5 Packet Extraction Routine and task routine for a5r_task
  465. * Parameters: irq_stat - interrupt status
  466. *
  467. * Description:
  468. * This is the routine for extracting frame. It will schedule itself if the hardware is busy.
  469. * This routine runs in interrupt context
  470. */
  471. void amazon_atm_a5r(void* qid)
  472. {
  473. volatile u32 ex_stat=0;
  474. u32 addr;
  475. u32 a5r_wait=0;
  476. ex_stat = readl(CBM_HWEXSTAT0_ADDR);
  477. #if 0
  478. // Check if extraction/insertion is in progress
  479. if ( (ex_stat & CBM_EXSTAT_SCB) || (ex_stat & CBM_EXSTAT_FB) ) {
  480. AMAZON_TPE_DMSG(" extraction in progress. Will wait\n");
  481. a5r_task.data = qid;
  482. queue_task(&a5r_task, &tq_immediate);
  483. mark_bh(IMMEDIATE_BH);
  484. }else {
  485. AMAZON_TPE_DMSG("extracting from qid=%u\n",(u8)qid);
  486. // Start extraction
  487. AMAZON_WRITE_REGISTER_L(((u8)qid) | CBM_HWEXPAR_PN_A5, CBM_HWEXPAR0_ADDR);
  488. AMAZON_WRITE_REGISTER_L(CBM_HWEXCMD_FE0, CBM_HWEXCMD_ADDR);
  489. }
  490. #else
  491. //while ( (ex_stat & CBM_EXSTAT_SCB) || (ex_stat & CBM_EXSTAT_FB) ) {
  492. while ( ex_stat != 0x80){
  493. a5r_wait++;
  494. ex_stat = readl(CBM_HWEXSTAT0_ADDR);
  495. #if 0
  496. if (a5r_wait >= 0xffffff){
  497. a5r_wait=0;
  498. printk(".");
  499. }
  500. #endif
  501. }
  502. if (a5r_wait > g_a5r_wait){
  503. g_a5r_wait = a5r_wait;
  504. }
  505. AMAZON_WRITE_REGISTER_L(((u8)qid) | CBM_HWEXPAR_PN_A5, CBM_HWEXPAR0_ADDR);
  506. AMAZON_WRITE_REGISTER_L(CBM_HWEXCMD_FE0, CBM_HWEXCMD_ADDR);
  507. #endif
  508. }
  509. #endif //AMAZON_TPE_SCR
  510. /* Brief: Handle F4/F5 OAM cell
  511. * Return:
  512. * 0 ok
  513. * <0 fails
  514. */
  515. static int inline amazon_handle_oam_cell(void *data, u8 vpi, u16 vci,u32 status)
  516. {
  517. struct atm_vcc* vcc=NULL;
  518. int qid;
  519. if (!status&SWIE_EOAM_MASK){
  520. AMAZON_TPE_EMSG("unknown cell received, discarded\n");
  521. goto amazon_handle_oam_cell_err_exit;
  522. }else if (status&SWIE_ECRC10ERROR_MASK){
  523. AMAZON_TPE_EMSG("CRC-10 Error Status:%8x, discarded\n", status);
  524. goto amazon_handle_oam_cell_err_exit;
  525. }else{
  526. if(status & (SWIE_EVCI3_MASK |SWIE_EVCI4_MASK)){
  527. //F4 level (VPI) OAM, Assume duplex
  528. qid = amazon_atm_find_vpi(vpi)+CBM_RX_OFFSET;
  529. }else if (status & (SWIE_EPTI4_MASK|SWIE_EPTI5_MASK)){
  530. //F5 level (VCI) OAM, Assume duplex
  531. qid = amazon_atm_find_vpivci(vpi,vci)+CBM_RX_OFFSET;
  532. }else{
  533. qid = -1;
  534. AMAZON_TPE_EMSG("non-F4/F5 OAM cells?, discarded\n");
  535. goto amazon_handle_oam_cell_err_exit;
  536. }
  537. }
  538. if (valid_qid(qid) && ((vcc = g_atm_dev.queues[qid].vcc)!=NULL)){
  539. //TODO, should we do this for ALL OAM types? (Actually only User and CC)
  540. g_atm_dev.queues[qid].access_time=xtime;
  541. if (vcc->push_oam){
  542. (*vcc->push_oam)(vcc,data);
  543. }else{
  544. amz_push_oam(data);
  545. }
  546. }else{
  547. AMAZON_TPE_EMSG("no VCC yet\n");
  548. goto amazon_handle_oam_cell_err_exit;
  549. }
  550. return 0;
  551. amazon_handle_oam_cell_err_exit:
  552. dump_skb(AMAZON_AAL0_SDU,(char *)data);
  553. return -1;
  554. }
  555. /* Brief: SWIE Cell Extraction Finish Routine
  556. * and task routine for swex_complete_task
  557. * Description:
  558. * 1.Allocate a buffer of type struct sk_buff
  559. * 2.Copy the data from the temporary memory to this buffer
  560. * 3.Push the data to upper layer
  561. * 4.Update the statistical data if necessary
  562. * 5.Release the temporary data
  563. */
  564. void amazon_atm_swex_push(void * data)
  565. {
  566. struct atm_vcc* vcc=NULL;
  567. struct sk_buff* skb=NULL;
  568. struct amazon_atm_cell_header * cell_header;
  569. u32 status;
  570. int qid;
  571. if (!data){
  572. AMAZON_TPE_EMSG("data is NULL\n");
  573. return;
  574. }
  575. qid = ((u8*)data)[AMAZON_AAL0_SDU];
  576. status = ((u32*)data)[ATM_AAL0_SDU/4];
  577. cell_header = (struct amazon_atm_cell_header *) data;
  578. if (valid_qid(qid) != 1){
  579. AMAZON_TPE_EMSG("error qid: %u\n",qid);
  580. AMAZON_TPE_EMSG("unknown cells recieved\n");
  581. }else if (qid == AMAZON_ATM_OAM_Q_ID){
  582. //OAM or RM or OTHER cell
  583. //Find real connection
  584. #ifdef IKOS_MINI_BOOT
  585. //for OAM loop back test
  586. dump_skb(56,(char *)data);
  587. //kfree(data); using g_oam_cell
  588. return;
  589. #endif //IKOS_MINI_BOOT
  590. #ifdef TPE_LOOPBACK
  591. amz_push_oam(data);
  592. return;
  593. #endif//TPE_LOOPBACK
  594. int ret = 0;
  595. ret = amazon_handle_oam_cell(data,cell_header->bit.vpi,cell_header->bit.vci,status);
  596. if (ret == 0)
  597. return;
  598. }else{
  599. //should be normal AAL0 cells
  600. // Get VCC
  601. vcc = g_atm_dev.queues[qid].vcc;
  602. if (vcc != NULL) {
  603. AMAZON_TPE_DMSG("push to upper layer\n");
  604. skb = dev_alloc_skb(AMAZON_AAL0_SDU);
  605. if (skb != NULL) {
  606. //skb->dev=vcc->dev;
  607. memcpy(skb_put(skb, AMAZON_AAL0_SDU), data, AMAZON_AAL0_SDU);
  608. skb->stamp = xtime;
  609. ATM_SKB(skb)->vcc = vcc;
  610. (*g_atm_dev.queues[qid].push)(vcc,skb,0);
  611. }else{
  612. AMAZON_TPE_EMSG(" No memory left for incoming AAL0 cell! Cell discarded!\n");
  613. //inform the upper layer
  614. (*g_atm_dev.queues[qid].push)(vcc,skb,-ENOMEM);
  615. atomic_inc(&vcc->stats->rx_drop);
  616. }
  617. }else{
  618. AMAZON_TPE_EMSG("invalid qid %u\n",qid);
  619. }
  620. }
  621. //kfree(data); using g_oam_cell
  622. }
  623. /*
  624. * Brief: Interrupt handler for software cell extraction (done)
  625. * Parameters: irq - CPPN for this interrupt
  626. * data - Device ID for this interrupt
  627. * regs - Register file
  628. *
  629. * Description:
  630. * When a software extraction is finished this interrupt is issued.
  631. * It reads the cell data and sends it to the ATM stack.
  632. */
  633. void amazon_atm_swex_isr(int irq, void *data, struct pt_regs *regs)
  634. {
  635. u32 * cell = NULL;
  636. int i;
  637. //ATM_AAL0 SDU + QID
  638. AMAZON_TPE_DMSG("SWIE extraction done\n");
  639. cell = (u32 *) g_oam_cell;
  640. if (cell != NULL){
  641. //convert to host byte order from big endian
  642. for(i=0;i<ATM_AAL0_SDU;i+=4){
  643. cell[i/4]=readl(SWIE_ECELL_ADDR+i);
  644. }
  645. cell[ATM_AAL0_SDU/4]= g_atm_dev.swie.sw;
  646. ((u8*)cell)[AMAZON_AAL0_SDU] = g_atm_dev.swie.qid;
  647. #ifdef IKOS_MINI_BOOT
  648. for(i=0;i<ATM_AAL0_SDU;i+=4){
  649. AMAZON_TPE_DMSG("[%2x][%2x][%2x][%2x]\n",
  650. ((char*)cell)[i],
  651. ((char*)cell)[i+1],
  652. ((char*)cell)[i+2],
  653. ((char*)cell)[i+3]
  654. );
  655. }
  656. AMAZON_TPE_DMSG("qid: %u\n", ((u8*)cell)[AMAZON_AAL0_SDU]);
  657. amazon_atm_swex_push((void *) cell);
  658. #else //not IKOS_MINI_BOOT
  659. swex_complete_task.data = cell;
  660. queue_task(&swex_complete_task,&tq_immediate);
  661. mark_bh(IMMEDIATE_BH);
  662. #endif //not IKOS_MINI_BOOT
  663. }else{
  664. AMAZON_TPE_EMSG("no memory for receiving AAL0 cell\n");
  665. }
  666. /* release the lock and check */
  667. if (test_and_clear_bit(SWIE_LOCK,&(g_atm_dev.swie.lock)) == 0){
  668. AMAZON_TPE_EMSG("swie lock is already released\n");
  669. }
  670. wake_up(&g_atm_dev.swie.sleep);
  671. }
  672. /* Brief: Interrupt handler for software cell insertion
  673. *
  674. * Parameters: irq - CPPN for this interrupt
  675. * data - Device ID for this interrupt
  676. * regs - Register file
  677. *
  678. * Description:
  679. * When a software insertion is finished this interrupt is issued.
  680. * The only purpose is to release the semaphore and read the status register.
  681. */
  682. void amazon_atm_swin_isr(int irq, void *data, struct pt_regs *regs)
  683. {
  684. AMAZON_TPE_DMSG("SWIE insertion done\n");
  685. /* release the lock and check */
  686. if (test_and_clear_bit(SWIE_LOCK,&(g_atm_dev.swie.lock)) == 0){
  687. AMAZON_TPE_EMSG("swie lock is already released");
  688. }
  689. // Release semaphore
  690. up(&g_atm_dev.swie.in_sem);
  691. }
  692. /* Brief: Interrupt handler for software cell insertion & extraction
  693. * Parameters: irq - CPPN for this interrupt
  694. * data - Device ID for this interrupt
  695. * regs - Register file
  696. * Description:
  697. * When a software insertion or extractionis finished this interrupt is issued.
  698. */
  699. void amazon_atm_swie_isr(int irq, void *data, struct pt_regs *regs)
  700. {
  701. u32 status=0;
  702. // Read status register
  703. status = readl(SWIE_ISTAT_ADDR);
  704. AMAZON_TPE_DMSG("insertion status: %8x\n", status);
  705. if (status & SWIE_ISTAT_DONE){
  706. //clear interrupt in peripheral and ICU
  707. AMAZON_WRITE_REGISTER_L(SRC_TOS_MIPS | SRC_CLRR|SRC_SRE_ENABLE | AMAZON_SWIE_INT, SWIE_ISRC_ADDR);
  708. mask_and_ack_amazon_irq(AMAZON_SWIE_INT);
  709. amazon_atm_swin_isr(irq,data,regs);
  710. }
  711. status = readl(SWIE_ESTAT_ADDR);
  712. AMAZON_TPE_DMSG("extraction status: %8x\n", status);
  713. if (status & SWIE_ESTAT_DONE){
  714. //clear interrupt
  715. AMAZON_WRITE_REGISTER_L(SRC_TOS_MIPS | SRC_CLRR|SRC_SRE_ENABLE | AMAZON_SWIE_INT, SWIE_ESRC_ADDR);
  716. mask_and_ack_amazon_irq(AMAZON_SWIE_INT);
  717. amazon_atm_swex_isr(irq,data,regs);
  718. }
  719. //clear interrupt in ICU
  720. }
  721. /*
  722. * Brief: Insert ATM cell into CBM
  723. * Parameters: queue - Target queue
  724. * cell - Pointer to cell data
  725. * Return Value: EBUSY - CBM is busy
  726. * 0 - OK, cell inserted
  727. * Description:
  728. * This function inserts a cell into the CBM using the software insertion
  729. * method. The format of the cell should be
  730. * Little Endian (address starting from 0)
  731. * H3, H2, H1, H0, P3, P2, P1, P0, P7, P6, P5, P4, ..., P47, P46, P45, P44
  732. * Big Endian (address starting from 0)
  733. * H0, H1, H2, H3, P0, P1, P2, P3, P4, P5, P6, P7, ..., P44, P45, P46, P47
  734. * This function does not free memory!!!
  735. */
  736. int amazon_atm_swin(u8 queue, void* cell)
  737. {
  738. u32 status=0;
  739. int i;
  740. // Read status register
  741. status = readl(SWIE_ISTAT_ADDR);
  742. AMAZON_TPE_DMSG(" SWIE status=0x%08x\n",status);
  743. AMAZON_TPE_DMSG(" Inserting cell qid=%u\n",queue);
  744. #ifdef AMAZON_CHECK_LINK
  745. if (adsl_link_status == 0){
  746. return -EFAULT;
  747. }
  748. #endif //AMAZON_CHECK_LINK
  749. // Get semaphore (if possible)
  750. if (down_interruptible(&g_atm_dev.swie.in_sem)) {
  751. return -ERESTARTSYS;
  752. }
  753. /* try to set lock */
  754. wait_event_interruptible(g_atm_dev.swie.sleep,(test_and_set_bit(SWIE_LOCK,&(g_atm_dev.swie.lock)) == 0));
  755. if (signal_pending(current)){
  756. return -ERESTARTSYS;
  757. }
  758. // Store cell in CBM memory
  759. for(i=0;i<ATM_AAL0_SDU;i+=4){
  760. AMAZON_WRITE_REGISTER_L(((u32*)cell)[i/4],SWIE_ICELL_ADDR+i);
  761. }
  762. //Store queue id
  763. AMAZON_WRITE_REGISTER_L((u32) queue,SWIE_IQID_ADDR);
  764. //Start SWIE
  765. AMAZON_WRITE_REGISTER_L(SWIE_ICMD_START,SWIE_ICMD_ADDR);
  766. return 0;
  767. }
  768. #ifdef AMAZON_ATM_DEBUG
  769. /*
  770. * Brief: Interrupt handler for HTU
  771. *
  772. * Parameters: irq - CPPN for this interrupt
  773. * data - Device ID for this interrupt
  774. * regs - Register file
  775. *
  776. */
  777. void amazon_atm_htu_isr(int irq, void *data, struct pt_regs *regs)
  778. {
  779. u32 irq_stat=0;
  780. // Read interrupt status register
  781. irq_stat = readl(HTU_ISR0_ADDR);
  782. AMAZON_TPE_DMSG("HTU status: %8x\n",irq_stat);
  783. //Clear interrupt in CBM and ICU
  784. AMAZON_WRITE_REGISTER_L(SRC_CLRR|SRC_TOS_MIPS | SRC_SRE_ENABLE | AMAZON_HTU_INT, HTU_SRC0_ADDR);
  785. mask_and_ack_amazon_irq(AMAZON_HTU_INT);
  786. // Check if Any Cell Arrived
  787. if (irq_stat & (HTU_ISR_NE | HTU_ISR_PNE) ) {
  788. AMAZON_TPE_EMSG("INFNOENTRY %8x\n", readl(HTU_INFNOENTRY_ADDR));
  789. }else if (irq_stat & (HTU_ISR_TORD|HTU_ISR_PT)){
  790. AMAZON_TPE_EMSG("Time Out %8x\n", readl(HTU_INFTIMEOUT_ADDR));
  791. }else if (irq_stat & HTU_ISR_IT){
  792. AMAZON_TPE_EMSG("Interrupt Test\n");
  793. }else if (irq_stat & HTU_ISR_OTOC){
  794. AMAZON_TPE_EMSG("Overflow of Time Out Counter\n");
  795. }else if (irq_stat & HTU_ISR_ONEC){
  796. AMAZON_TPE_EMSG("Overflow of No Entry Counter\n");
  797. }else{
  798. AMAZON_TPE_EMSG("unknown HTU interrupt occurs %8x\n", irq_stat);
  799. }
  800. }
  801. #endif //AMAZON_ATM_DEBUG
  802. #ifdef AMAZON_TPE_TEST_AAL5_INT
  803. /*
  804. * Brief: Interrupt handler for AAL5
  805. *
  806. * Parameters: irq - CPPN for this interrupt
  807. * data - Device ID for this interrupt
  808. * regs - Register file
  809. *
  810. */
  811. void amazon_atm_aal5_isr(int irq, void *data, struct pt_regs *regs)
  812. {
  813. volatile u32 irq_stat=0;
  814. // Read interrupt status register
  815. irq_stat = readl(AAL5_SISR0_ADDR);
  816. if (irq_stat){
  817. AMAZON_TPE_EMSG("A5S status: %8x\n",irq_stat);
  818. //Clear interrupt in CBM and ICU
  819. AMAZON_WRITE_REGISTER_L(SRC_CLRR|SRC_TOS_MIPS | SRC_SRE_ENABLE | AMAZON_AAL5_INT, AAL5_SSRC0_ADDR);
  820. mask_and_ack_amazon_irq(AMAZON_AAL5_INT);
  821. }
  822. irq_stat = readl(AAL5_RISR0_ADDR);
  823. if (irq_stat){
  824. AMAZON_TPE_EMSG("A5R status: %8x\n",irq_stat);
  825. //Clear interrupt in CBM and ICU
  826. AMAZON_WRITE_REGISTER_L(SRC_CLRR|SRC_TOS_MIPS | SRC_SRE_ENABLE | AMAZON_AAL5_INT, AAL5_RSRC0_ADDR);
  827. mask_and_ack_amazon_irq(AMAZON_AAL5_INT);
  828. }
  829. }
  830. #endif //AMAZON_TPE_TEST_AAL5_INT
  831. /*
  832. * Brief: Interrupt handler for CBM
  833. *
  834. * Parameters: irq - CPPN for this interrupt
  835. * data - Device ID for this interrupt
  836. * regs - Register file
  837. *
  838. * Description:
  839. * This is the MIPS interrupt handler for the CBM. It processes incoming cells
  840. * for SWIE queues.
  841. */
  842. void amazon_atm_cbm_isr(int irq, void *data, struct pt_regs *regs)
  843. {
  844. u32 irq_stat=0;
  845. u8 qid=0;
  846. // Read interrupt status register
  847. while ( (irq_stat = readl(CBM_INTINF0_ADDR))){
  848. AMAZON_TPE_DMSG("CBM INT status: %8x\n",irq_stat);
  849. //Clear interrupt in CBM and ICU
  850. AMAZON_WRITE_REGISTER_L(SRC_CLRR|SRC_TOS_MIPS | SRC_SRE_ENABLE | AMAZON_CBM_INT, CBM_SRC0_ADDR);
  851. qid = (u8) ((irq_stat & CBM_INTINF0_QID_MASK)>>CBM_INTINF0_QID_SHIFT);
  852. #ifdef AMAZON_TPE_SCR
  853. if (irq_stat & CBM_INTINF0_EF){
  854. amazon_atm_a5r((void*)qid);
  855. }
  856. #endif
  857. // Check if Any Cell Arrived
  858. if (irq_stat & CBM_INTINF0_ACA) {
  859. amazon_atm_swex((void *)irq_stat);
  860. }
  861. //TX AAL5 PDU discard
  862. if (irq_stat & CBM_INTINF0_OPF){
  863. if ( (qid) < CBM_RX_OFFSET ){
  864. g_atm_dev.mib_counter.tx_drop++;
  865. }
  866. queue_statics(qid, QS_HW_DROP);
  867. }
  868. if (irq_stat & (CBM_INTINF0_ERR|CBM_INTINF0_Q0E|CBM_INTINF0_Q0I|CBM_INTINF0_RDE)){
  869. AMAZON_TPE_EMSG("CBM INT status: %8x\n",irq_stat);
  870. if (irq_stat & CBM_INTINF0_ERR){
  871. AMAZON_TPE_EMSG("CBM Error: FPI Bus Error\n");
  872. }
  873. if (irq_stat & CBM_INTINF0_Q0E){
  874. AMAZON_TPE_EMSG("CBM Error: Queue 0 Extract\n");
  875. }
  876. if (irq_stat & CBM_INTINF0_Q0I){
  877. AMAZON_TPE_EMSG("CBM Error: Queue 0 Extract\n");
  878. }
  879. if (irq_stat & CBM_INTINF0_RDE){
  880. AMAZON_TPE_EMSG("CBM Error: Read Empty Queue %u\n",qid);
  881. dump_qd(qid);
  882. }
  883. }
  884. }
  885. mask_and_ack_amazon_irq(AMAZON_CBM_INT);
  886. }
  887. /* Brief: check the status word after AAL SDU after reassembly
  888. */
  889. static inline void check_aal5_error(u8 stw0, u8 stw1, int qid)
  890. {
  891. if (stw0 & AAL5_STW0_MFL){
  892. AMAZON_TPE_DMSG("Maximum Frame Length\n");
  893. g_atm_dev.queues[qid].aal5VccOverSizedSDUs++;
  894. }
  895. if (stw0 & AAL5_STW0_CRC){
  896. AMAZON_TPE_DMSG("CRC\n");
  897. g_atm_dev.queues[qid].aal5VccCrcErrors++;
  898. }
  899. #ifdef AMAZON_ATM_DEBUG_RX
  900. AMAZON_TPE_EMSG("qid:%u stw0:%8x stw1:%8x\n",qid,stw0,stw1);
  901. #endif
  902. }
  903. /* Brief: Process DMA rx data
  904. * Parameters:
  905. dma_dev: pointer to the dma_device_info, provided by us when register the dma device
  906. * Return: no
  907. * Description: DMA interrupt handerl with OoS support. It is called when there is some data in rx direction.
  908. *
  909. */
  910. //507261:tc.chen void atm_process_dma_rx(struct dma_device_info* dma_dev)
  911. void __system atm_process_dma_rx(struct dma_device_info* dma_dev)
  912. {
  913. u8 * head=NULL;
  914. u32 length=0;
  915. u8 stw0=0;
  916. u8 stw1=0;
  917. struct sk_buff * skb=NULL;
  918. struct atm_vcc * vcc=NULL;
  919. int qid=0;
  920. #ifdef AMAZON_ATM_DEBUG_RX
  921. static int dma_rx_dump=0;
  922. static u32 seq=0;
  923. seq++;
  924. if (dma_rx_dump>0){
  925. printk("\n=========================[%u]=========================\n",seq);
  926. }
  927. #endif
  928. length=dma_device_read(dma_dev,&head,(void**)&skb);
  929. AMAZON_TPE_DMSG("receive %8p[%u] from DMA\n", head,length);
  930. if (head == NULL||length<=0) {
  931. AMAZON_TPE_DMSG("dma_read null \n");
  932. goto error_exit;
  933. }
  934. if (length > (g_atm_dev.aal5.rx_max_sdu+64)){
  935. AMAZON_TPE_EMSG("received packet too large (%u)\n",length);
  936. goto error_exit;
  937. }
  938. //check AAL5R trail for error and qid
  939. //last byte is qid
  940. length--;
  941. qid = (int) head[length];
  942. AMAZON_TPE_DMSG("head[%u] qid %u\n",length, qid);
  943. //STW0 is always 4 bytes before qid
  944. length -= 4;
  945. stw0 = head[length]&0xff;
  946. AMAZON_TPE_DMSG("head[%u] stw0 %8x\n",length, stw0);
  947. //position of STW1 depends on the BE bits
  948. length = length-4 + (stw0&AAL5_STW0_BE);
  949. stw1 = head[length]&0xff;
  950. AMAZON_TPE_DMSG("head[%u] stw1 %8x\n",length, stw1);
  951. if ( (stw0 & AAL5_STW0_MASK) || (stw1 & AAL5_STW1_MASK) ){
  952. //AAL5 Error
  953. check_aal5_error(stw0, stw1,qid);
  954. goto error_exit;
  955. }
  956. //make data pointers consistent
  957. //UU + CPI
  958. length -= 2;
  959. AMAZON_TPE_DMSG("packet length %u\n", length);
  960. //error: cannot restore the qid
  961. if (valid_qid(qid) != 1){
  962. AMAZON_TPE_EMSG("received frame in invalid qid %u!\n", qid);
  963. goto error_exit;
  964. }
  965. vcc = g_atm_dev.queues[qid].vcc;
  966. if (vcc == NULL){
  967. AMAZON_TPE_EMSG("received frame in invalid vcc, qid=%u!\n",qid);
  968. goto error_exit;
  969. }
  970. if (skb == NULL){
  971. AMAZON_TPE_EMSG("cannot restore skb pointer!\n");
  972. goto error_exit;
  973. }
  974. skb_put(skb,length);
  975. skb->stamp = xtime;
  976. g_atm_dev.queues[qid].access_time=xtime;
  977. if ((*g_atm_dev.queues[qid].push)(vcc,skb,0)){
  978. g_atm_dev.mib_counter.rx_drop++;
  979. queue_statics(qid, QS_SW_DROP);
  980. }else{
  981. g_atm_dev.mib_counter.rx++;
  982. adsl_led_flash();//joelin adsl led
  983. queue_statics(qid, QS_PKT);
  984. AMAZON_TPE_DMSG("push successful!\n");
  985. }
  986. #ifdef AMAZON_ATM_DEBUG_RX
  987. if (dma_rx_dump>0){
  988. printk("\nOK packet [dump=%u] length=%u\n",dma_rx_dump,length);
  989. dump_skb(length+7, head);
  990. }
  991. if (dma_rx_dump >0) dma_rx_dump--;
  992. #endif
  993. return ;
  994. error_exit:
  995. #ifdef AMAZON_ATM_DEBUG_RX
  996. if ( (head!=NULL) && (length >0)){
  997. AMAZON_TPE_EMSG("length=%u\n",length);
  998. dump_skb(length+5, head);
  999. }
  1000. dma_rx_dump++;
  1001. #endif
  1002. g_atm_dev.mib_counter.rx_err++;
  1003. queue_statics(qid, QS_ERR);
  1004. /*
  1005. if (vcc){
  1006. (*g_atm_dev.queues[qid].push)(vcc,skb,1);
  1007. }
  1008. */
  1009. if (skb != NULL) {
  1010. dev_kfree_skb_any(skb);
  1011. }
  1012. return;
  1013. }
  1014. /*Brief: ISR for DMA pseudo interrupt
  1015. *Parameter:
  1016. dma_dev: pointer to the dma_device_info, provided by us when register the dma device
  1017. intr_status:
  1018. RCV_INT: rx data available
  1019. TX_BUF_FULL_INT: tx descriptor run out of
  1020. TRANSMIT_CPT_INT: tx descriptor available again
  1021. *Return:
  1022. 0 for success???
  1023. */
  1024. //507261:tc.chen int amazon_atm_dma_handler(struct dma_device_info* dma_dev, int intr_status)
  1025. int __system amazon_atm_dma_handler(struct dma_device_info* dma_dev, int intr_status)
  1026. {
  1027. AMAZON_TPE_DMSG("status:%u\n",intr_status);
  1028. switch (intr_status) {
  1029. case RCV_INT:
  1030. atm_process_dma_rx(dma_dev);
  1031. break;
  1032. case TX_BUF_FULL_INT:
  1033. //TX full: no descriptors
  1034. atm_dma_full();
  1035. break;
  1036. case TRANSMIT_CPT_INT:
  1037. //TX free: at least one descriptor
  1038. atm_dma_free();
  1039. break;
  1040. default:
  1041. AMAZON_TPE_EMSG("unknown status!\n");
  1042. }
  1043. return 0;
  1044. }
  1045. /*Brief: free buffer for DMA tx
  1046. *Parameter:
  1047. dataptr: pointers to data buffer
  1048. opt: optional parameter, used to convey struct skb pointer, passwd in dma_device_write
  1049. *Return:
  1050. 0 for success???
  1051. *Description:
  1052. called by DMA module to release data buffer after DMA tx transaction
  1053. *Error:
  1054. cannot restore skb pointer
  1055. */
  1056. int amazon_atm_free_tx(u8*dataptr, void* opt)
  1057. {
  1058. struct sk_buff *skb;
  1059. if (opt){
  1060. AMAZON_TPE_DMSG("free skb%8p\n",opt);
  1061. skb = (struct sk_buff *)opt;
  1062. amazon_atm_free_tx_skb(skb);
  1063. }else{
  1064. AMAZON_TPE_EMSG("BUG: cannot restore skb pointer!\n");
  1065. }
  1066. return 0;
  1067. }
  1068. /*Brief: allocate buffer & do alignment
  1069. */
  1070. inline struct sk_buff * amazon_atm_alloc_buffer(int len)
  1071. {
  1072. struct sk_buff *skb;
  1073. skb = dev_alloc_skb(len+16);
  1074. if (skb){
  1075. //alignment requriements (4x32 bits (16 bytes) boundary)
  1076. alloc_align_16(skb);
  1077. }
  1078. return skb;
  1079. }
  1080. /*Brief: allocate buffer for DMA rx
  1081. *Parameter:
  1082. len: length
  1083. opt: optional data to convey the skb pointer, which will be returned to me in interrupt handler,
  1084. *Return:
  1085. pointer to buffer, NULL means error?
  1086. *Description:
  1087. must make sure byte alignment
  1088. */
  1089. u8* amazon_atm_alloc_rx(int len, int* offset, void **opt)
  1090. {
  1091. struct sk_buff *skb;
  1092. *offset = 0;
  1093. skb = amazon_atm_alloc_buffer(len);
  1094. if (skb){
  1095. AMAZON_TPE_DMSG("alloc skb->data:%8p len:%u\n",skb->data,len);
  1096. *(struct sk_buff**)opt = skb;
  1097. }else{
  1098. AMAZON_TPE_DMSG("no memory for receiving atm frame!\n");
  1099. return NULL;
  1100. }
  1101. return skb->data;
  1102. }
  1103. /* Brief: Allocate kernel memory for sending a datagram.
  1104. * Parameters
  1105. * vcc virtual connection
  1106. * size data buffer size
  1107. * Return:
  1108. * NULL fail
  1109. * sk_buff a pointer to a sk_buff
  1110. * Description:
  1111. * This function can allocate our own additional memory for AAL5S inbound
  1112. * header (8bytes). We have to replace the protocol default one (alloc_tx in /net/atm/common.c)
  1113. * when we open the device.
  1114. * byte alignment is done is DMA driver.
  1115. */
  1116. struct sk_buff *amazon_atm_alloc_tx(struct atm_vcc *vcc,unsigned int size)
  1117. {
  1118. struct sk_buff *skb;
  1119. if (!dma_may_send(DMA_TX_CH0)){
  1120. AMAZON_TPE_EMSG("no DMA descriptor available!\n");
  1121. return NULL;
  1122. }
  1123. //AAL5 inbound header space + alignment extra buffer
  1124. size+=8+AAL5S_INBOUND_HEADER;
  1125. if (atomic_read(&vcc->tx_inuse) && !atm_may_send(vcc,size)) {
  1126. AMAZON_TPE_EMSG("Sorry tx_inuse = %u, size = %u, sndbuf = %u\n",
  1127. atomic_read(&vcc->tx_inuse),size,vcc->sk->sndbuf);
  1128. return NULL;
  1129. }
  1130. skb = amazon_atm_alloc_buffer(size);
  1131. if (skb == NULL){
  1132. AMAZON_TPE_EMSG("no memory\n");
  1133. return NULL;
  1134. }
  1135. AMAZON_TPE_DMSG("dev_alloc_skb(%u) = %x\n", skb->len, (u32)skb);
  1136. AMAZON_TPE_DMSG("tx_inuse %u += %u\n",atomic_read(&vcc->tx_inuse),skb->truesize);
  1137. atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
  1138. //reserve for AAL5 inbound header
  1139. skb_reserve(skb,AAL5S_INBOUND_HEADER);
  1140. return skb;
  1141. }
  1142. /* Brief: change per queue QSB setting according to vcc qos parameters
  1143. * Paramters:
  1144. * vcc: atm_vcc pointer
  1145. * qid: CBM queue id (1~15)
  1146. * Return:
  1147. */
  1148. static inline void set_qsb(struct atm_vcc *vcc, struct atm_qos *qos, int qid)
  1149. {
  1150. qsb_qptl_t qptl;
  1151. qsb_qvpt_t qvpt;
  1152. u32 tmp=0;
  1153. unsigned int qsb_clk;
  1154. qsb_clk = amazon_get_fpi_hz()>>1;
  1155. AMAZON_TPE_EMSG("Class=%u MAX_PCR=%u PCR=%u MIN_PCR=%u SCR=%u MBS=%u CDV=%u\n"
  1156. ,qos->txtp.traffic_class
  1157. ,qos->txtp.max_pcr
  1158. ,qos->txtp.pcr
  1159. ,qos->txtp.min_pcr
  1160. ,qos->txtp.scr
  1161. ,qos->txtp.mbs
  1162. ,qos->txtp.cdv
  1163. );
  1164. // PCR limiter
  1165. if (qos->txtp.max_pcr == 0){
  1166. qptl.bit.tprs = 0; /* 0 disables the PCR limiter */
  1167. }else {
  1168. // peak cell rate will be slightly lower than requested (maximum rate / pcr)= (qsbclock/2^3 * timestep/4)/pcr
  1169. tmp = (( (qsb_clk * g_atm_dev.qsb.tstepc)>>5)/ qos->txtp.max_pcr ) + 1;
  1170. // check if an overfow occured
  1171. if (tmp > QSB_TP_TS_MAX) {
  1172. AMAZON_TPE_EMSG("max_pcr is too small, max_pcr:%u tprs:%u\n",qos->txtp.max_pcr, tmp);
  1173. qptl.bit.tprs = QSB_TP_TS_MAX;
  1174. }else{
  1175. qptl.bit.tprs = tmp;
  1176. }
  1177. }
  1178. //WFQ
  1179. if (qos->txtp.traffic_class == ATM_CBR || qos->txtp.traffic_class ==ATM_VBR_RT){
  1180. // real time queue gets weighted fair queueing bypass
  1181. qptl.bit.twfq = 0;
  1182. }else if (qos->txtp.traffic_class ==ATM_VBR_NRT ||qos->txtp.traffic_class ==ATM_UBR_PLUS ){
  1183. // wfq calculation here are based on virtual cell rates, to reduce granularity for large rates
  1184. // wfq factor is maximum cell rate / garenteed cell rate.
  1185. //qptl.bit.twfq = g_atm_dev.qsb.min_cr * QSB_WFQ_NONUBR_MAX / qos->txtp.min_pcr;
  1186. if (qos->txtp.min_pcr == 0) {
  1187. AMAZON_TPE_EMSG("<warning> MIN_PCR should not be zero\n");
  1188. qptl.bit.twfq = QSB_WFQ_NONUBR_MAX;
  1189. }else{
  1190. tmp = QSB_GCR_MIN * QSB_WFQ_NONUBR_MAX / qos->txtp.min_pcr;
  1191. if (tmp == 0 ){
  1192. qptl.bit.twfq = 1;
  1193. }else if (tmp > QSB_WFQ_NONUBR_MAX){
  1194. AMAZON_TPE_EMSG("min_pcr is too small, min_pcr:%u twfq:%u\n",qos->txtp.min_pcr, tmp);
  1195. qptl.bit.twfq = QSB_WFQ_NONUBR_MAX;
  1196. }else{
  1197. qptl.bit.twfq = tmp;
  1198. }
  1199. }
  1200. }else if (qos->txtp.traffic_class == ATM_UBR){
  1201. // ubr bypass, twfq set to maximum value
  1202. qptl.bit.twfq = QSB_WFQ_UBR_BYPASS;
  1203. }else{
  1204. //tx is diabled, treated as UBR
  1205. AMAZON_TPE_EMSG("<warning> unsupported traffic class %u \n", qos->txtp.traffic_class);
  1206. qos->txtp.traffic_class = ATM_UBR;
  1207. qptl.bit.twfq = QSB_WFQ_UBR_BYPASS;
  1208. }
  1209. //SCR Leaky Bucket Shaper VBR.0/VBR.1
  1210. if (qos->txtp.traffic_class ==ATM_VBR_RT || qos->txtp.traffic_class ==ATM_VBR_NRT){
  1211. if (qos->txtp.scr == 0){
  1212. //SCR == 0 disable the shaper
  1213. qvpt.bit.ts = 0;
  1214. qvpt.bit.taus = 0;
  1215. }else{
  1216. //CLP
  1217. if (vcc->atm_options&ATM_ATMOPT_CLP){
  1218. //CLP1
  1219. qptl.bit.vbr = 1;
  1220. }else{
  1221. //CLP0
  1222. qptl.bit.vbr = 0;
  1223. }
  1224. //TS and TauS
  1225. tmp = (( (qsb_clk * g_atm_dev.qsb.tstepc)>>5)/ qos->txtp.scr ) + 1;
  1226. if (tmp > QSB_TP_TS_MAX) {
  1227. AMAZON_TPE_EMSG("scr is too small, scr:%u ts:%u\n",qos->txtp.scr, tmp);
  1228. qvpt.bit.ts = QSB_TP_TS_MAX;
  1229. }else{
  1230. qvpt.bit.ts = tmp;
  1231. }
  1232. tmp = (qos->txtp.mbs - 1)*(qvpt.bit.ts - qptl.bit.tprs)/64;
  1233. if (tmp > QSB_TAUS_MAX){
  1234. AMAZON_TPE_EMSG("mbs is too large, mbr:%u taus:%u\n",qos->txtp.mbs, tmp);
  1235. qvpt.bit.taus = QSB_TAUS_MAX;
  1236. }else if (tmp == 0){
  1237. qvpt.bit.taus = 1;
  1238. }else{
  1239. qvpt.bit.taus = tmp;
  1240. }
  1241. }
  1242. }else{
  1243. qvpt.w0 = 0;
  1244. }
  1245. //write the QSB Queue Parameter Table (QPT)
  1246. AMAZON_WRITE_REGISTER_L(QSB_QPT_SET_MASK,QSB_RTM_ADDR);
  1247. AMAZON_WRITE_REGISTER_L(qptl.w0, QSB_RTD_ADDR);
  1248. AMAZON_WRITE_REGISTER_L((QSB_TABLESEL_QPT<<QSB_TABLESEL_SHIFT)
  1249. | QSB_RAMAC_REG_LOW
  1250. | QSB_WRITE
  1251. | qid
  1252. ,QSB_RAMAC_ADDR);
  1253. //write the QSB Queue VBR Parameter Table (QVPT)
  1254. AMAZON_WRITE_REGISTER_L(QSB_QVPT_SET_MASK,QSB_RTM_ADDR);
  1255. AMAZON_WRITE_REGISTER_L(qvpt.w0, QSB_RTD_ADDR);
  1256. AMAZON_WRITE_REGISTER_L((QSB_TABLESEL_QVPT<<QSB_TABLESEL_SHIFT)
  1257. | QSB_RAMAC_REG_LOW
  1258. | QSB_WRITE
  1259. | qid
  1260. ,QSB_RAMAC_ADDR);
  1261. AMAZON_TPE_EMSG("tprs:%u twfq:%u ts:%u taus:%u\n",qptl.bit.tprs,qptl.bit.twfq,qvpt.bit.ts,qvpt.bit.taus);
  1262. }
  1263. /*
  1264. * Brief: create/change CBM queue descriptor
  1265. * Parameter:
  1266. * vcc: atm_vcc pointer
  1267. * qid: CBM queue id (1~15)
  1268. */
  1269. static inline void set_qd(struct atm_vcc *vcc, u32 qid)
  1270. {
  1271. u32 tx_config=0,rx_config=0;
  1272. u32 itf = (u32) vcc->itf;
  1273. u32 dma_qos=0;
  1274. u8 * qd_addr=NULL;
  1275. tx_config|=CBM_QD_W3_WM_EN|CBM_QD_W3_CLPt;
  1276. //RT: check if the connection is a real time connection
  1277. if (vcc->qos.txtp.traffic_class == ATM_CBR || vcc->qos.txtp.traffic_class == ATM_VBR_RT){
  1278. tx_config|= CBM_QD_W3_RT;
  1279. }else{
  1280. tx_config|= CBM_QD_W3_AAL5; //don't set the AAL5 flag if it is a RT service
  1281. }
  1282. rx_config = tx_config;
  1283. if(vcc->qos.aal == ATM_AAL5){
  1284. //QoS: DMA QoS according to the traffic class
  1285. switch (vcc->qos.txtp.traffic_class){
  1286. case ATM_CBR: dma_qos = CBR_DMA_QOS;break;
  1287. case ATM_VBR_RT: dma_qos = VBR_RT_DMA_QOS;break;
  1288. case ATM_VBR_NRT: dma_qos = VBR_NRT_DMA_QOS;break;
  1289. case ATM_UBR_PLUS: dma_qos = UBR_PLUS_DMA_QOS;break;
  1290. case ATM_UBR: dma_qos = UBR_DMA_QOS;break;
  1291. }
  1292. //TX: upstream, AAL5(EPD or PPD), NOINT, SBid
  1293. tx_config |= CBM_QD_W3_DIR_UP|CBM_QD_W3_INT_NOINT|(itf&CBM_QD_W3_SBID_MASK);
  1294. //RX: DMA QoS, downstream, no interrupt, AAL5(EPD, PPD), NO INT, HCR
  1295. #ifdef AMAZON_TPE_SCR
  1296. rx_config |= dma_qos|CBM_QD_W3_DIR_DOWN|CBM_QD_W3_INT_EOF;
  1297. #else
  1298. rx_config |= dma_qos|CBM_QD_W3_DIR_DOWN|CBM_QD_W3_INT_NOINT|CBM_QD_W3_HCR;
  1299. #endif
  1300. }else {
  1301. //should be AAL0
  1302. //upstream, NOINT, SBid
  1303. tx_config |= CBM_QD_W3_DIR_UP|CBM_QD_W3_INT_NOINT|(itf&CBM_QD_W3_SBID_MASK);
  1304. //RX: downstream, ACA interrupt,
  1305. rx_config |= CBM_QD_W3_DIR_DOWN|CBM_QD_W3_INT_ACA;
  1306. }
  1307. //Threshold: maximum threshold for tx/rx queue, which is adjustable in steps of 64 cells
  1308. tx_config |= ( (divide_by_64_round_up(tx_q_threshold)&0xffff)<<CBM_QD_W3_THRESHOLD_SHIFT) & CBM_QD_W3_THRESHOLD_MASK;
  1309. rx_config |= ( (divide_by_64_round_up(rx_q_threshold)&0xffff)<<CBM_QD_W3_THRESHOLD_SHIFT) & CBM_QD_W3_THRESHOLD_MASK;
  1310. qd_addr = (u8*) KSEG1ADDR((unsigned long)g_atm_dev.cbm.qd_addr);
  1311. //TX
  1312. AMAZON_WRITE_REGISTER_L(tx_config, (qd_addr+qid*CBM_QD_SIZE + 0xc));
  1313. AMAZON_WRITE_REGISTER_L(0, (qd_addr+qid*CBM_QD_SIZE + 0x8));
  1314. //RX
  1315. AMAZON_WRITE_REGISTER_L(rx_config, (qd_addr+(qid+CBM_RX_OFFSET)*CBM_QD_SIZE + 0xc));
  1316. AMAZON_WRITE_REGISTER_L(0, (qd_addr+(qid+CBM_RX_OFFSET)*CBM_QD_SIZE + 0x8));
  1317. }
  1318. /*
  1319. * Brief: add HTU table entry
  1320. * Parameter:
  1321. * vpi.vci:
  1322. * qid: CBM queue id (DEST is qid + CBM_RX_OFFSET)
  1323. * idx: entry id (starting from zero to 14)
  1324. * Return:
  1325. * 0: sucessful
  1326. * EIO: HTU table entry cannot be written
  1327. */
  1328. inline int set_htu_entry(u8 vpi, u16 vci, u8 qid, u8 idx)
  1329. {
  1330. int i = 0;
  1331. u32 tmp1=0;
  1332. while ((tmp1 = readl(HTU_RAMSTAT_ADDR))!=0 && i < 1024) i++;
  1333. if (i > 1024)
  1334. {
  1335. AMAZON_TPE_EMSG("timeout\n");
  1336. return -EIO;
  1337. }
  1338. // write address register,
  1339. AMAZON_WRITE_REGISTER_L(idx, HTU_RAMADDR_ADDR);
  1340. // configure transmit queue
  1341. tmp1 = vpi<<24|vci<<8;
  1342. tmp1|= HTU_RAMDAT1_VCON // valid connection the entry is not validated here !!!!!!!!!!!!!!!!
  1343. |HTU_RAMDAT1_VCI3 // vci3 -> oam queue
  1344. |HTU_RAMDAT1_VCI4 // vci4 -> oam queue
  1345. |HTU_RAMDAT1_VCI6 // vci6 -> rm queue
  1346. |HTU_RAMDAT1_PTI4 // pti4 -> oam queue
  1347. |HTU_RAMDAT1_PTI5; // pti5 -> oam queue
  1348. // ramdat 1 (in params & oam handling)
  1349. AMAZON_WRITE_REGISTER_L( tmp1, HTU_RAMDAT1_ADDR);
  1350. // ramdat 2 (out params & oam handling)
  1351. tmp1 = ((qid+CBM_RX_OFFSET)&HTU_RAMDAT2_QID_MASK)
  1352. |HTU_RAMDAT2_PTI6
  1353. |HTU_RAMDAT2_PTI7
  1354. |HTU_RAMDAT2_F4U
  1355. |HTU_RAMDAT2_F5U
  1356. ;
  1357. AMAZON_WRITE_REGISTER_L( tmp1, HTU_RAMDAT2_ADDR);
  1358. wmb();
  1359. // write HTU entry
  1360. AMAZON_WRITE_REGISTER_L(HTU_RAMCMD_WR, HTU_RAMCMD_ADDR);
  1361. return 0;
  1362. }
  1363. /*
  1364. * Brief: add HTU table entry
  1365. * Parameter:
  1366. * vcc: atm_vcc pointer
  1367. * qid: CBM queue id
  1368. * Return:
  1369. * 0: sucessful
  1370. * EIO: HTU table entry cannot be written
  1371. */
  1372. inline static int set_htu(struct atm_vcc *vcc, u32 qid)
  1373. {
  1374. return set_htu_entry(vcc->vpi, vcc->vci, qid, (qid - CBM_DEFAULT_Q_OFFSET));
  1375. }
  1376. /*
  1377. * Brief: allocate a queue
  1378. * Return:
  1379. * <=0 no available queues
  1380. * >0 qid
  1381. */
  1382. static int atm_allocate_q(short itf)
  1383. {
  1384. int i;
  1385. u32 tmp1=0;
  1386. int qid=0;
  1387. amazon_atm_port_t * dev;
  1388. dev = &g_atm_dev.ports[itf];
  1389. //find start queue id for this interface
  1390. for (i=0; i< itf; i++)
  1391. {
  1392. qid+= g_atm_dev.ports[i].max_conn;
  1393. }
  1394. // apply default queue offset ( oam, free cell queue, others, rm )
  1395. qid += CBM_DEFAULT_Q_OFFSET;
  1396. tmp1 = qid;
  1397. // search for a free queue
  1398. while ( (qid<tmp1+dev->max_conn)
  1399. && ( g_atm_dev.queues[qid].free != 1)) {
  1400. qid++;;
  1401. }
  1402. // if none was found, send failure message and return
  1403. if ( tmp1+dev->max_conn == qid)
  1404. {
  1405. return -EFAULT;
  1406. }
  1407. return qid;
  1408. }
  1409. /* Brief: open a aal5 or aal0 connection
  1410. */
  1411. static int atm_open(struct atm_vcc *vcc, push_back_t push)
  1412. {
  1413. int err=0;
  1414. int qid=0;
  1415. amazon_atm_port_t * port = & g_atm_dev.ports[vcc->itf];
  1416. unsigned long flags;
  1417. /***************** check bandwidth ******************/
  1418. /* 511045:linmars change ATM_VBR_NRT to use scr instead of pcr */
  1419. if ((vcc->qos.txtp.traffic_class==ATM_CBR&&vcc->qos.txtp.max_pcr>port->tx_rem_cr)
  1420. ||(vcc->qos.txtp.traffic_class==ATM_VBR_RT&&vcc->qos.txtp.max_pcr>port->tx_rem_cr)
  1421. ||(vcc->qos.txtp.traffic_class==ATM_VBR_NRT&&vcc->qos.txtp.scr>port->tx_rem_cr)
  1422. ||(vcc->qos.txtp.traffic_class==ATM_UBR_PLUS&&vcc->qos.txtp.min_pcr>port->tx_rem_cr)
  1423. ) {
  1424. AMAZON_TPE_EMSG("not enough bandwidth left (%u) cells per seconds \n",port->tx_rem_cr);
  1425. return -EINVAL;
  1426. }
  1427. if ( (qid = amazon_atm_find_vpivci(vcc->vpi, vcc->vci)) >0 ){
  1428. AMAZON_TPE_EMSG("vpi:%u vci:%u is alreay open on queue:%u\n", vcc->vpi, vcc->vci, qid);
  1429. return -EADDRINUSE;
  1430. }
  1431. /***************** allocate entry queueID for this port *****************/
  1432. if ( (qid=atm_allocate_q(vcc->itf)) <= 0){
  1433. AMAZON_TPE_EMSG("port: %u max:%u qid: %u\n", vcc->itf, port->max_conn, qid);
  1434. AMAZON_TPE_EMSG("no availabel connections for this port:%u\n",vcc->itf);
  1435. return -EINVAL;
  1436. }
  1437. /**************QSB parameters and CBM descriptors*************/
  1438. set_qsb(vcc, &vcc->qos, qid);
  1439. set_qd(vcc, qid);
  1440. mb();
  1441. err=set_htu(vcc,qid);
  1442. if (err){
  1443. AMAZON_TPE_EMSG("set htu entry fails %u\n",err);
  1444. return err;
  1445. }
  1446. /************set internal mapping*************/
  1447. local_irq_save(flags);
  1448. g_atm_dev.queues[qid].free = 0;
  1449. g_atm_dev.queues[qid].vcc = vcc;
  1450. g_atm_dev.queues[qid].push = push;
  1451. g_atm_dev.queues[qid+CBM_RX_OFFSET].free = 0;
  1452. g_atm_dev.queues[qid+CBM_RX_OFFSET].vcc = vcc;
  1453. g_atm_dev.queues[qid+CBM_RX_OFFSET].push = push;
  1454. /******************reserve bandwidth**********************/
  1455. if (vcc->qos.txtp.traffic_class == ATM_CBR){
  1456. //CBR, real time connection, reserve PCR
  1457. port->tx_cur_cr += vcc->qos.txtp.max_pcr;
  1458. port->tx_rem_cr -= vcc->qos.txtp.max_pcr;
  1459. }else if (vcc->qos.txtp.traffic_class == ATM_VBR_RT){
  1460. //VBR_RT, real time connection, reserve PCR
  1461. port->tx_cur_cr += vcc->qos.txtp.max_pcr;
  1462. port->tx_rem_cr -= vcc->qos.txtp.max_pcr;
  1463. }else if (vcc->qos.txtp.traffic_class == ATM_VBR_NRT){
  1464. //VBR_NRT, reserve SCR
  1465. port->tx_cur_cr += vcc->qos.txtp.pcr;
  1466. port->tx_rem_cr -= vcc->qos.txtp.pcr;
  1467. }else if (vcc->qos.txtp.traffic_class == ATM_UBR_PLUS){
  1468. //UBR_PLUS, reserve MCR
  1469. port->tx_cur_cr += vcc->qos.txtp.min_pcr;
  1470. port->tx_rem_cr -= vcc->qos.txtp.min_pcr;
  1471. }
  1472. local_irq_restore(flags);
  1473. return err;
  1474. }
  1475. /* Brief: Open ATM connection
  1476. * Parameters: atm_vcc - Pointer to VCC data structure
  1477. * vpi - VPI value for new connection
  1478. * vci - VCI value for new connection
  1479. *
  1480. * Return: 0 - sucessful
  1481. * -ENOMEM - No memory available
  1482. * -EINVAL - No bandwidth/queue/ or unsupported AAL type
  1483. * Description:
  1484. * This function opens an ATM connection on a specific device/interface
  1485. *
  1486. */
  1487. int amazon_atm_open(struct atm_vcc *vcc,push_back_t push)
  1488. {
  1489. int err=0;
  1490. AMAZON_TPE_DMSG("vpi %u vci %u itf %u aal %u\n"
  1491. ,vcc->vpi
  1492. ,vcc->vci
  1493. ,vcc->itf
  1494. ,vcc->qos.aal
  1495. );
  1496. AMAZON_TPE_DMSG("tx cl %u bw %u mtu %u\n"
  1497. ,vcc->qos.txtp.traffic_class
  1498. ,vcc->qos.txtp.max_pcr
  1499. ,vcc->qos.txtp.max_sdu
  1500. );
  1501. AMAZON_TPE_DMSG("rx cl %u bw %u mtu %u\n"
  1502. ,vcc->qos.rxtp.traffic_class
  1503. ,vcc->qos.rxtp.max_pcr
  1504. ,vcc->qos.rxtp.max_sdu
  1505. );
  1506. if (vcc->qos.aal == ATM_AAL5 || vcc->qos.aal == ATM_AAL0){
  1507. err = atm_open(vcc,push);
  1508. }else{
  1509. AMAZON_TPE_EMSG("unsupported aal type %u\n", vcc->qos.aal);
  1510. err = -EPROTONOSUPPORT;
  1511. };
  1512. if (err == 0 ){
  1513. //replace the default memory allocation function with our own
  1514. vcc->alloc_tx = amazon_atm_alloc_tx;
  1515. set_bit(ATM_VF_READY,&vcc->flags);
  1516. }
  1517. return err;
  1518. }
  1519. /* Brief: Send ATM OAM cell
  1520. * Parameters: atm_vcc - Pointer to VCC data structure
  1521. * skb - Pointer to sk_buff structure, that contains the data
  1522. * Return: 0 - sucessful
  1523. * -ENOMEM - No memory available
  1524. * -EINVAL - Not supported
  1525. * Description:
  1526. * This function sends a cell over and ATM connection
  1527. * We always release the skb
  1528. * TODO: flags handling (ATM_OF_IMMED, ATM_OF_INRATE)
  1529. */
  1530. int amazon_atm_send_oam(struct atm_vcc *vcc, void * cell, int flags)
  1531. {
  1532. int err=0;
  1533. int qid=0;
  1534. struct amazon_atm_cell_header * cell_header;
  1535. // Get cell header
  1536. cell_header = (struct amazon_atm_cell_header*) cell;
  1537. if ((cell_header->bit.pti == ATM_PTI_SEGF5) || (cell_header->bit.pti == ATM_PTI_E2EF5)) {
  1538. qid = amazon_atm_find_vpivci( cell_header->bit.vpi, cell_header->bit.vci);
  1539. }else if (cell_header->bit.vci == 0x3 || cell_header->bit.vci == 0x4) {
  1540. //507281:tc.chen qid = amazon_atm_find_vpi((int) cell_header->bit.vpi);
  1541. // 507281:tc.chen start
  1542. u8 f4_vpi;
  1543. f4_vpi = cell_header->bit.vpi;
  1544. qid = amazon_atm_find_vpi(f4_vpi );
  1545. // 507281:tc.chen end
  1546. }else{
  1547. //non-OAM cells, always invalid
  1548. qid = -EINVAL;
  1549. }
  1550. if (qid == -EINVAL) {
  1551. err = -EINVAL;
  1552. AMAZON_TPE_EMSG("not valid AAL0 packet\n");
  1553. }else{
  1554. //send the cell using swie
  1555. #ifdef TPE_LOOPBACK
  1556. err = amazon_atm_swin(AMAZON_ATM_OAM_Q_ID, cell);
  1557. #else
  1558. err = amazon_atm_swin(qid, cell);
  1559. #endif
  1560. }
  1561. //kfree(cell);
  1562. return err;
  1563. }
  1564. /* Brief: Send AAL5 frame through DMA
  1565. * Parameters: vpi - virtual path id
  1566. * vci - virtual circuit id
  1567. * clp - cell loss priority
  1568. * qid - CBM queue to be sent to
  1569. * skb - packet to be sent
  1570. * Return: 0 - sucessful
  1571. * -ENOMEM - No memory available
  1572. * -EINVAL - Not supported
  1573. * Description:
  1574. * This function sends a AAL5 frame over and ATM connection
  1575. * 1. make sure that the data is aligned to 4x32-bit boundary
  1576. * 2. provide the inbound data (CPCS-UU and CPI, not used here)
  1577. * 3. set CLPn
  1578. * 4. send the frame by DMA
  1579. * 5. release the buffer ???
  1580. ** use our own allocation alloc_tx
  1581. ** we make sure the alignment and additional memory
  1582. *** we always release the skb
  1583. */
  1584. int amazon_atm_dma_tx(u8 vpi, u16 vci, u8 clp, u8 qid, struct sk_buff *skb)
  1585. {
  1586. int err=0,need_pop=1;
  1587. u32 * data=NULL;
  1588. int nwrite=0;
  1589. struct sk_buff *skb_tmp;
  1590. u32 len=skb->len;
  1591. //AAL5S inbound header 8 bytes
  1592. if (skb->len > g_atm_dev.aal5.tx_max_sdu - AAL5S_INBOUND_HEADER) {
  1593. AMAZON_TPE_DMSG("tx_max_sdu:%u\n",g_atm_dev.aal5.tx_max_sdu);
  1594. AMAZON_TPE_DMSG("skb too large [%u]!\n",skb->len);
  1595. err = -EMSGSIZE;
  1596. goto atm_dma_tx_error_exit;
  1597. }
  1598. //Check the byte alignment requirement and header space
  1599. if ( ( ((u32)(skb->data)%16) !=AAL5S_INBOUND_HEADER)|| (skb_headroom(skb)<AAL5S_INBOUND_HEADER)){
  1600. //not aligned or no space for header, fall back to memcpy
  1601. skb_tmp = dev_alloc_skb(skb->len+16);
  1602. if (skb_tmp==NULL){
  1603. err = - ENOMEM;
  1604. goto atm_dma_tx_error_exit;
  1605. }
  1606. alloc_align_16(skb_tmp);
  1607. g_atm_dev.aal5.cnt_cpy++;
  1608. skb_reserve(skb_tmp,AAL5S_INBOUND_HEADER);
  1609. memcpy(skb_put(skb_tmp,skb->len), skb->data, skb->len);
  1610. amazon_atm_free_tx_skb(skb);
  1611. need_pop=0;
  1612. skb = skb_tmp;
  1613. }
  1614. //Provide AAL5S inbound header
  1615. data = (u32 *)skb_push(skb,8);
  1616. data[0] = __be32_to_cpu(vpi<<20|vci<<4|clp);
  1617. data[1] = __be32_to_cpu(g_atm_dev.aal5.padding_byte<<8|qid);
  1618. len = skb->len;
  1619. //send through DMA
  1620. AMAZON_TPE_DMSG("AAL5S header 0 %8x\n", data[0]);
  1621. AMAZON_TPE_DMSG("AAL5S header 0 %8x\n", data[1]);
  1622. AMAZON_TPE_DMSG("about to call dma_write len: %u\n", len);
  1623. nwrite=dma_device_write( &g_dma_dev,skb->data,len,skb);
  1624. if (nwrite != len) {
  1625. //DMA descriptors full
  1626. // AMAZON_TPE_EMSG("AAL5 packet drop due to DMA nwrite:%u skb->len:%u\n", nwrite,len);
  1627. AMAZON_TPE_DMSG("AAL5 packet drop due to DMA nwrite:%u skb->len:%u\n", nwrite,len);
  1628. err = -EAGAIN;
  1629. goto atm_dma_tx_drop_exit;
  1630. }
  1631. AMAZON_TPE_DMSG("just finish call dma_write\n");
  1632. //release in the "dma done" call-back
  1633. return 0;
  1634. atm_dma_tx_error_exit:
  1635. g_atm_dev.mib_counter.tx_err++;
  1636. queue_statics(qid, QS_ERR);
  1637. goto atm_dma_tx_exit;
  1638. atm_dma_tx_drop_exit:
  1639. g_atm_dev.mib_counter.tx_drop++;
  1640. queue_statics(qid, QS_SW_DROP);
  1641. atm_dma_tx_exit:
  1642. if (need_pop){
  1643. amazon_atm_free_tx_skb(skb);
  1644. }else{
  1645. dev_kfree_skb_any(skb);
  1646. }
  1647. return err;
  1648. }
  1649. /* Brief: Send AAL0/AAL5 packet
  1650. * Parameters: atm_vcc - Pointer to VCC data structure
  1651. * skb - Pointer to sk_buff structure, that contains the data
  1652. * Return: 0 - sucessful
  1653. * -ENOMEM - No memory available
  1654. * -EINVAL - Not supported
  1655. * Description:
  1656. * See amazon_atm_dma_tx
  1657. */
  1658. int amazon_atm_send(struct atm_vcc *vcc,struct sk_buff *skb)
  1659. {
  1660. int qid=0;
  1661. u8 clp=0;
  1662. int err=0;
  1663. u32 wm=0;
  1664. if (vcc == NULL || skb == NULL){
  1665. AMAZON_TPE_EMSG("invalid parameter\n");
  1666. return -EINVAL;
  1667. }
  1668. ATM_SKB(skb)->vcc = vcc;
  1669. qid = amazon_atm_get_queue(vcc);
  1670. if (valid_qid(qid) != 1) {
  1671. AMAZON_TPE_EMSG("invalid vcc!\n");
  1672. err = -EINVAL;
  1673. goto atm_send_err_exit;
  1674. }
  1675. //Send AAL0 using SWIN
  1676. if (vcc->qos.aal == ATM_AAL0){
  1677. #ifdef TPE_LOOPBACK
  1678. err=amazon_atm_swin((qid+CBM_RX_OFFSET), skb->data);
  1679. #else
  1680. err=amazon_atm_swin(qid, skb->data);
  1681. #endif
  1682. if (err){
  1683. goto atm_send_err_exit;
  1684. }
  1685. goto atm_send_exit;
  1686. }
  1687. //Should be AAl5
  1688. //MIB counter
  1689. g_atm_dev.mib_counter.tx++;
  1690. adsl_led_flash();//joelin adsl led
  1691. queue_statics(qid, QS_PKT);
  1692. #ifdef AMAZON_CHECK_LINK
  1693. //check adsl link
  1694. if (adsl_link_status == 0){
  1695. //link down
  1696. AMAZON_TPE_DMSG("ADSL link down, discarded!\n");
  1697. err=-EFAULT;
  1698. goto atm_send_drop_exit;
  1699. }
  1700. #endif
  1701. clp = (vcc->atm_options&ATM_ATMOPT_CLP)?1:0;
  1702. //check watermark first
  1703. wm = readl(CBM_WMSTAT0_ADDR);
  1704. if ( (wm & (1<<qid))
  1705. ||( (vcc->qos.txtp.traffic_class != ATM_CBR
  1706. &&vcc->qos.txtp.traffic_class != ATM_VBR_RT)
  1707. &(wm & (CBM_WM_NRT_MASK | (clp&CBM_WM_CLP1_MASK)) ))){
  1708. //wm hit: discard
  1709. AMAZON_TPE_DMSG("watermark hit, discarded!\n");
  1710. err=-EFAULT;
  1711. goto atm_send_drop_exit;
  1712. }
  1713. #ifdef TPE_LOOPBACK
  1714. return amazon_atm_dma_tx(vcc->vpi, vcc->vci,clp, (qid+CBM_RX_OFFSET),skb);
  1715. #else
  1716. return amazon_atm_dma_tx(vcc->vpi, vcc->vci,clp, qid,skb);
  1717. #endif
  1718. atm_send_exit:
  1719. amazon_atm_free_tx_skb_vcc(vcc,skb);
  1720. return 0;
  1721. atm_send_drop_exit:
  1722. g_atm_dev.mib_counter.tx_drop++;
  1723. queue_statics(qid,QS_SW_DROP);
  1724. atm_send_err_exit:
  1725. amazon_atm_free_tx_skb_vcc(vcc,skb);
  1726. return err;
  1727. }
  1728. /* Brief: Return ATM port related MIB
  1729. * Parameter: interface number
  1730. atm_cell_ifEntry_t
  1731. */
  1732. int amazon_atm_cell_mib(atm_cell_ifEntry_t* to,u32 itf)
  1733. {
  1734. g_atm_dev.mib_counter.htu_unp += readl(HTU_MIBCIUP);
  1735. to->ifInUnknownProtos = g_atm_dev.mib_counter.htu_unp;
  1736. #ifdef AMAZON_TPE_READ_ARC
  1737. u32 reg_val=0;
  1738. meiDebugRead((AR_CELL0_ADDR+itf*4),&reg_val,1);
  1739. g_atm_dev.mib_counter.rx_cells += reg_val;
  1740. reg_val=0;
  1741. meiDebugWrite((AR_CELL0_ADDR+itf*4),&reg_val,1);
  1742. to->ifHCInOctets_h = (g_atm_dev.mib_counter.rx_cells * 53)>>32;
  1743. to->ifHCInOctets_l = (g_atm_dev.mib_counter.rx_cells * 53) & 0xffff;
  1744. meiDebugRead((AT_CELL0_ADDR+itf*4),&reg_val,1);
  1745. g_atm_dev.mib_counter.tx_cells += reg_val;
  1746. reg_val=0;
  1747. meiDebugWrite((AT_CELL0_ADDR+itf*4),&reg_val,1);
  1748. to->ifHCOutOctets_h = (g_atm_dev.mib_counter.tx_cells * 53)>>32;
  1749. to->ifHCOutOctets_l = (g_atm_dev.mib_counter.rx_cells * 53) & 0xffff;
  1750. meiDebugRead((AR_CD_CNT0_ADDR+itf*4),&reg_val,1);
  1751. g_atm_dev.mib_counter.rx_err_cells += reg_val;
  1752. reg_val=0;
  1753. meiDebugWrite((AR_CD_CNT0_ADDR+itf*4),&reg_val,1);
  1754. to->ifInErrors = g_atm_dev.mib_counter.rx_err_cells;
  1755. to->ifOutErrors = 0;
  1756. #else
  1757. to->ifHCInOctets_h = 0;
  1758. to->ifHCInOctets_l = 0;
  1759. to->ifHCOutOctets_h = 0;
  1760. to->ifHCOutOctets_l = 0;
  1761. to->ifInErrors = 0;
  1762. to->ifOutErrors = 0;
  1763. #endif
  1764. return 0;
  1765. }
  1766. /* Brief: Return ATM AAL5 related MIB
  1767. * Parameter:
  1768. atm_aal5_ifEntry_t
  1769. */
  1770. int amazon_atm_aal5_mib(atm_aal5_ifEntry_t* to)
  1771. {
  1772. u32 reg_l,reg_h;
  1773. //AAL5R received Octets from ATM
  1774. reg_l = readl(AAL5_RIOL_ADDR);
  1775. reg_h = readl(AAL5_RIOM_ADDR);
  1776. g_atm_dev.mib_counter.rx_cnt_h +=reg_h;
  1777. if (reg_l + g_atm_dev.mib_counter.rx_cnt_l < reg_l){
  1778. g_atm_dev.mib_counter.rx_cnt_h++;
  1779. }
  1780. g_atm_dev.mib_counter.rx_cnt_l+= reg_l;
  1781. //AAL5S sent Octets to ATM
  1782. reg_l = readl(AAL5_SOOL_ADDR);
  1783. reg_h = readl(AAL5_SOOM_ADDR);
  1784. g_atm_dev.mib_counter.tx_cnt_h +=reg_h;
  1785. if (reg_l + g_atm_dev.mib_counter.tx_cnt_l < reg_l){
  1786. g_atm_dev.mib_counter.tx_cnt_h++;
  1787. }
  1788. g_atm_dev.mib_counter.tx_cnt_l+= reg_l;
  1789. g_atm_dev.mib_counter.tx_ppd += readl(CBM_AAL5ODIS_ADDR);
  1790. g_atm_dev.mib_counter.rx_drop += readl(CBM_AAL5IDIS_ADDR);
  1791. //store
  1792. to->ifHCInOctets_h = g_atm_dev.mib_counter.rx_cnt_h;
  1793. to->ifHCInOctets_l = g_atm_dev.mib_counter.rx_cnt_l;
  1794. to->ifHCOutOctets_h = g_atm_dev.mib_counter.tx_cnt_h;
  1795. to->ifHCOutOctets_l = g_atm_dev.mib_counter.tx_cnt_l;
  1796. to->ifOutDiscards = g_atm_dev.mib_counter.tx_drop;
  1797. to->ifInDiscards = g_atm_dev.mib_counter.rx_drop;
  1798. //Software provided counters
  1799. //packets passed to higher layer
  1800. to->ifInUcastPkts = g_atm_dev.mib_counter.rx;
  1801. //packets passed from higher layer
  1802. to->ifOutUcastPkts = g_atm_dev.mib_counter.tx;
  1803. //number of wrong downstream packets
  1804. to->ifInErrors = g_atm_dev.mib_counter.rx_err;
  1805. //number of wrong upstream packets
  1806. to->ifOutErros = g_atm_dev.mib_counter.tx_err;
  1807. return 0;
  1808. }
  1809. /* Brief: Return ATM AAL5 VCC related MIB from internale use
  1810. * Parameter:
  1811. * qid
  1812. * atm_aal5_vcc_t
  1813. */
  1814. static int __amazon_atm_vcc_mib(int qid, atm_aal5_vcc_t* to)
  1815. {
  1816. //aal5VccCrcErrors
  1817. to->aal5VccCrcErrors = g_atm_dev.queues[qid].aal5VccCrcErrors;
  1818. to->aal5VccOverSizedSDUs =g_atm_dev.queues[qid].aal5VccOverSizedSDUs;
  1819. to->aal5VccSarTimeOuts = 0; //not supported yet
  1820. return 0;
  1821. }
  1822. /* Brief: Return ATM AAL5 VCC related MIB from vpi/vci
  1823. * Parameter: atm_vcc
  1824. * atm_aal5_vcc_t
  1825. */
  1826. int amazon_atm_vcc_mib_x(int vpi, int vci,atm_aal5_vcc_t* to)
  1827. {
  1828. int qid=0;
  1829. int err=0;
  1830. qid = amazon_atm_find_vpivci(vpi, vci);
  1831. if (qid >0 ){
  1832. err = __amazon_atm_vcc_mib(qid,to);
  1833. }else{
  1834. return -EINVAL;
  1835. }
  1836. return err;
  1837. }
  1838. /* Brief: Return ATM AAL5 VCC related MIB
  1839. * Parameter: atm_vcc
  1840. * atm_aal5_vcc_t
  1841. */
  1842. int amazon_atm_vcc_mib(struct atm_vcc *vcc,atm_aal5_vcc_t* to)
  1843. {
  1844. int qid=0;
  1845. int err=0;
  1846. qid = amazon_atm_get_queue(vcc);
  1847. if (qid >0 ){
  1848. err = __amazon_atm_vcc_mib(qid,to);
  1849. }else{
  1850. return -EINVAL;
  1851. }
  1852. return err;
  1853. }
  1854. /* Brief: Close ATM connection
  1855. * Parameters: atm_vcc - Pointer to VCC data structure
  1856. * Return: no
  1857. * Description:
  1858. * This function closes the given ATM connection
  1859. */
  1860. void amazon_atm_close(struct atm_vcc *vcc){
  1861. int i;
  1862. int qid=0;
  1863. u32 tmp1;
  1864. u8 * qd_addr;
  1865. unsigned long flags;
  1866. if (vcc == NULL){
  1867. AMAZON_TPE_EMSG("invalid parameter. vcc is null\n");
  1868. return;
  1869. }
  1870. u32 itf = (u32) vcc->itf;
  1871. //release bandwidth
  1872. if (vcc->qos.txtp.traffic_class == ATM_CBR){
  1873. g_atm_dev.ports[itf].tx_rem_cr += vcc->qos.txtp.max_pcr;
  1874. g_atm_dev.ports[itf].tx_cur_cr -= vcc->qos.txtp.max_pcr;
  1875. }else if (vcc->qos.txtp.traffic_class == ATM_VBR_RT){
  1876. g_atm_dev.ports[itf].tx_rem_cr += vcc->qos.txtp.max_pcr;
  1877. g_atm_dev.ports[itf].tx_cur_cr -= vcc->qos.txtp.max_pcr;
  1878. }else if (vcc->qos.txtp.traffic_class == ATM_VBR_NRT){
  1879. g_atm_dev.ports[itf].tx_rem_cr += vcc->qos.txtp.pcr;
  1880. g_atm_dev.ports[itf].tx_cur_cr -= vcc->qos.txtp.pcr;
  1881. }else if (vcc->qos.txtp.traffic_class == ATM_UBR_PLUS){
  1882. g_atm_dev.ports[itf].tx_rem_cr += vcc->qos.txtp.min_pcr;
  1883. g_atm_dev.ports[itf].tx_cur_cr -= vcc->qos.txtp.min_pcr;
  1884. }
  1885. qid = amazon_atm_get_queue(vcc);
  1886. if (qid == -EINVAL){
  1887. AMAZON_TPE_EMSG("unknown vcc %u.%u.%u\n", vcc->itf, vcc->vpi, vcc->vci);
  1888. return;
  1889. }
  1890. local_irq_save(flags);
  1891. //Disable HTU entry
  1892. i=0;
  1893. while ((tmp1 = readl(HTU_RAMSTAT_ADDR))!=0 && i < HTU_RAM_ACCESS_MAX) i++;
  1894. if (i == HTU_RAM_ACCESS_MAX){
  1895. AMAZON_TPE_EMSG("HTU RAM ACCESS out of time\n");
  1896. }
  1897. // write address register
  1898. AMAZON_WRITE_REGISTER_L(qid - CBM_DEFAULT_Q_OFFSET, HTU_RAMADDR_ADDR);
  1899. // invalidate the connection
  1900. AMAZON_WRITE_REGISTER_L(0, HTU_RAMDAT1_ADDR);
  1901. // write command
  1902. AMAZON_WRITE_REGISTER_L(HTU_RAMCMD_WR,HTU_RAMCMD_ADDR);
  1903. qd_addr = (u8 *) KSEG1ADDR((unsigned long)g_atm_dev.cbm.qd_addr);
  1904. #ifdef AMAZON_ATM_DEBUG
  1905. tmp1 = readl(qd_addr+qid*CBM_QD_SIZE+0x8) & 0xffff;
  1906. AMAZON_TPE_DMSG("TX queue has %u cells \n", tmp1);
  1907. tmp1 = readl( qd_addr+(qid+CBM_RX_OFFSET)*CBM_QD_SIZE+0x08)&0xffff;
  1908. AMAZON_TPE_DMSG("RX queue has %u cells \n", tmp1);
  1909. #endif
  1910. // set threshold of txqueue to 0
  1911. tmp1 = readl(qd_addr+qid*CBM_QD_SIZE+0x0c);
  1912. tmp1&= (~ CBM_QD_W3_THRESHOLD_MASK);
  1913. AMAZON_WRITE_REGISTER_L(tmp1, (qd_addr+qid*CBM_QD_SIZE+0x0c));
  1914. // set threshold of rxqueue to 0
  1915. tmp1 = readl( qd_addr+(qid+CBM_RX_OFFSET)*CBM_QD_SIZE+0x0c);
  1916. tmp1&= (~ CBM_QD_W3_THRESHOLD_MASK);
  1917. AMAZON_WRITE_REGISTER_L(tmp1,(qd_addr+(qid+CBM_RX_OFFSET)*CBM_QD_SIZE+0x0c));
  1918. //clear internal mapping
  1919. amazon_atm_clear_vcc(qid);
  1920. amazon_atm_clear_vcc(qid+CBM_RX_OFFSET);
  1921. local_irq_restore(flags);
  1922. }
  1923. /* Brief: initialize internal data structure
  1924. */
  1925. static void atm_constructor(amazon_atm_dev_t * dev)
  1926. {
  1927. int i;
  1928. memset(dev,0,sizeof(amazon_atm_dev_t));
  1929. atm_init_parameters(dev);
  1930. //internal: queue "free" flag
  1931. for(i=1;i<AMAZON_ATM_MAX_QUEUE_NUM;i++) {
  1932. //dev->queues[i].vcc=NULL;
  1933. dev->queues[i].free = 1;
  1934. }
  1935. for(i=0;i<AMAZON_ATM_PORT_NUM;i++){
  1936. dev->ports[i].tx_rem_cr = dev->ports[i].tx_max_cr;
  1937. }
  1938. //MIB
  1939. atomic_set(&dev->dma_tx_free_0,1); //initially there should be free descriptors
  1940. }
  1941. /* Brief: return round up base-2 logarithm
  1942. */
  1943. static inline int get_log_2(u32 value)
  1944. {
  1945. int i=0,j=1;
  1946. while (i<11){
  1947. if (j>=value) break;
  1948. j=j<<1;
  1949. i++;
  1950. }
  1951. AMAZON_TPE_DMSG("round up base-2 logarithm of %u is %u\n", value, i);
  1952. return i;
  1953. }
  1954. /* Brief: TPE hardware initialization
  1955. * Parameter: specifiy the configurations of the hardware
  1956. */
  1957. static inline int atm_init_hard(amazon_atm_dev_t * dev)
  1958. {
  1959. int i;
  1960. u32 tmp1, tmp2, tmp3;
  1961. u8 * mem_addr=NULL;
  1962. u8 * qd_addr=NULL;
  1963. //PMU power on the module 1st
  1964. *(AMAZON_PMU_PWDCR) = (*AMAZON_PMU_PWDCR) | (AMAZON_PMU_PWDCR_TPE);
  1965. //Reset the module
  1966. *(AMAZON_RST_REQ) = (* AMAZON_RST_REQ) | (AMAZON_RST_REQ_TPE);
  1967. mb();
  1968. mdelay(100);
  1969. *(AMAZON_RST_REQ) = (* AMAZON_RST_REQ) & (~(AMAZON_RST_REQ_TPE));
  1970. mb();
  1971. unsigned long qsb_clk = amazon_get_fpi_hz()>>1;
  1972. /*********allocate & arrange memory for CBM *********/
  1973. if (dev->cbm.mem_addr == NULL){
  1974. dev->cbm.allocated = 1;
  1975. mem_addr = (u8 *)__get_free_pages(GFP_KERNEL, get_log_2(((CBM_CELL_SIZE * dev->cbm.free_cell_cnt) >>PAGE_SHIFT) + 1));
  1976. if (mem_addr != NULL){
  1977. dev->cbm.mem_addr = mem_addr;
  1978. } else {
  1979. goto init_no_mem;
  1980. }
  1981. }
  1982. if (dev->cbm.qd_addr == NULL){
  1983. #ifdef CONFIG_USE_VENUS
  1984. //to work around a bug, bit15 of QDOFF address should be 1,Aug4, 2004
  1985. //thus, we allocate 64k memory
  1986. qd_addr = (u8 *)__get_free_pages(GFP_KERNEL, 4);
  1987. if (qd_addr != NULL) {
  1988. dev->cbm.qd_addr_free = (u8*) (((unsigned long) qd_addr));
  1989. dev->cbm.qd_addr = (u8*) (((unsigned long) qd_addr) | 0x8000);
  1990. }else{
  1991. goto init_no_mem;
  1992. }
  1993. #else //CONFIG_USE_VENUS
  1994. qd_addr = (u8 *)kmalloc( CBM_QD_SIZE * AMAZON_ATM_MAX_QUEUE_NUM, GFP_KERNEL);
  1995. if (qd_addr != NULL) {
  1996. dev->cbm.qd_addr = qd_addr;
  1997. }else {
  1998. goto init_no_mem;
  1999. }
  2000. #endif //CONFIG_USE_VENUS
  2001. }
  2002. //#ifndef CONFIG_MIPS_UNCACHED
  2003. mem_addr = (u8 *)KSEG1ADDR((unsigned long)dev->cbm.mem_addr);
  2004. qd_addr = (u8 *)KSEG1ADDR((unsigned long)dev->cbm.qd_addr);
  2005. //#endif
  2006. //CBM reset cell queue memory, 64 bytes / cell
  2007. memset_io(mem_addr, 0, CBM_CELL_SIZE * dev->cbm.free_cell_cnt);
  2008. //make a link list, last 4 bytes is pointer
  2009. for(i=1;i<dev->cbm.free_cell_cnt;i++){
  2010. AMAZON_WRITE_REGISTER_L(CPHYSADDR((mem_addr + CBM_CELL_SIZE * i)),(mem_addr + CBM_CELL_SIZE * (i-1) + 0x3c));
  2011. }
  2012. //reset queue descriptor
  2013. memset_io(qd_addr, 0, CBM_QD_SIZE * AMAZON_ATM_MAX_QUEUE_NUM);
  2014. //init word 0-2 of q0 (free cell list)
  2015. //address of last cell
  2016. AMAZON_WRITE_REGISTER_L(CPHYSADDR((mem_addr + CBM_CELL_SIZE * (dev->cbm.free_cell_cnt-1))), qd_addr);
  2017. //address of first cell
  2018. AMAZON_WRITE_REGISTER_L(CPHYSADDR((mem_addr)), (qd_addr + 4));
  2019. //no. of free cells
  2020. AMAZON_WRITE_REGISTER_L(dev->cbm.free_cell_cnt,(qd_addr + 8));
  2021. //init q descriptor for OAM receiving
  2022. AMAZON_WRITE_REGISTER_L((CBM_QD_W3_INT_ACA | (divide_by_64_round_up(oam_q_threshold)&0xff)<< CBM_QD_W3_THRESHOLD_SHIFT), (qd_addr + AMAZON_ATM_OAM_Q_ID * CBM_QD_SIZE + 0x0c));
  2023. // AMAZON_WRITE_REGISTER_L((CBM_QD_W3_INT_ACA | (u32)oam_q_threshold<< CBM_QD_W3_THRESHOLD_SHIFT), (qd_addr + AMAZON_ATM_OAM_Q_ID * CBM_QD_SIZE + 0x0c));
  2024. //config CBM
  2025. //set offset address and threshold
  2026. AMAZON_WRITE_REGISTER_L(CPHYSADDR(qd_addr), CBM_QDOFF_ADDR);
  2027. AMAZON_WRITE_REGISTER_L(((dev->cbm.nrt_thr&CBM_THR_MASK)|CBM_WM_3_1), CBM_NRTTHR_ADDR);
  2028. AMAZON_WRITE_REGISTER_L(((dev->cbm.clp0_thr&CBM_THR_MASK)|CBM_WM_3_1), CBM_CLP0THR_ADDR);
  2029. AMAZON_WRITE_REGISTER_L(((dev->cbm.clp1_thr&CBM_THR_MASK)|CBM_WM_3_1), CBM_CLP1THR_ADDR);
  2030. //config interrupts
  2031. AMAZON_WRITE_REGISTER_L( CBM_IMR_MASK & (~(CBM_IMR_ACA|CBM_IMR_Q0E|CBM_IMR_Q0I|CBM_IMR_RDE|CBM_IMR_OPF|CBM_IMR_ERR
  2032. #ifdef AMAZON_ATM_DEBUG
  2033. |CBM_IMR_DISC|CBM_IMR_QFD|CBM_IMR_NFCA|CBM_IMR_CLP1TR|CBM_IMR_CLP0TR|CBM_IMR_NRTTR|CBM_IMR_QTR
  2034. #endif
  2035. #ifdef AMAZON_TPE_SCR
  2036. |CBM_IMR_EF
  2037. #endif
  2038. )), CBM_IMR0_ADDR);
  2039. AMAZON_WRITE_REGISTER_L(SRC_CLRR|SRC_TOS_MIPS | SRC_SRE_ENABLE | AMAZON_CBM_INT, CBM_SRC0_ADDR);
  2040. //HTU
  2041. //RAM entry for number of possible connections per interface
  2042. tmp1 = dev->ports[0].max_conn?dev->ports[0].max_conn-1:0;
  2043. AMAZON_WRITE_REGISTER_L(tmp1, HTU_RX0_ADDR);
  2044. for(i=1;i<AMAZON_ATM_PORT_NUM;i++){
  2045. tmp1+=dev->ports[i].max_conn;
  2046. AMAZON_WRITE_REGISTER_L(tmp1, HTU_RX0_ADDR + 4 * i);
  2047. }
  2048. dev->cbm.max_q_off = tmp1+1;
  2049. //Queue ID for OAM/RM/Other cells
  2050. AMAZON_WRITE_REGISTER_L (AMAZON_ATM_OAM_Q_ID, HTU_DESTOAM_ADDR);
  2051. AMAZON_WRITE_REGISTER_L( AMAZON_ATM_RM_Q_ID, HTU_DESTRM_ADDR);
  2052. AMAZON_WRITE_REGISTER_L( AMAZON_ATM_OTHER_Q_ID, HTU_DESTOTHER_ADDR);
  2053. //Timeout
  2054. AMAZON_WRITE_REGISTER_L((u32) HTUTIMEOUT, HTU_TIMEOUT_ADDR);
  2055. #ifdef AMAZON_ATM_DEBUG
  2056. AMAZON_WRITE_REGISTER_L((u32) HTU_ISR_MASK
  2057. &(~(HTU_ISR_NE|HTU_ISR_TORD|HTU_ISR_OTOC|HTU_ISR_ONEC|HTU_ISR_PNE|HTU_ISR_PT)), HTU_IMR0_ADDR);
  2058. AMAZON_WRITE_REGISTER_L(SRC_CLRR|SRC_TOS_MIPS|SRC_SRE_ENABLE|AMAZON_HTU_INT,HTU_SRC0_ADDR);
  2059. #endif
  2060. //QSB
  2061. //global setting, TstepC, SBL, Tau
  2062. //Tau
  2063. AMAZON_WRITE_REGISTER_L(dev->qsb.tau, QSB_TAU_ADDR);
  2064. //SBL
  2065. AMAZON_WRITE_REGISTER_L(dev->qsb.sbl, QSB_SBL_ADDR);
  2066. //tstep
  2067. AMAZON_WRITE_REGISTER_L(dev->qsb.tstepc>>1, QSB_CONFIG_ADDR);
  2068. //port settting
  2069. for(i=0;i<AMAZON_ATM_PORT_NUM;i++){
  2070. if ( (dev->ports[i].enable) && (dev->ports[i].tx_max_cr!=0) ){
  2071. tmp1 = ((qsb_clk * dev->qsb.tstepc) >>1) / dev->ports[i].tx_max_cr;
  2072. tmp2 = tmp1 / 64; //integer value of Tsb
  2073. tmp3 = tmp1%64 + 1; //fractional part of Tsb
  2074. //carry over to integer part (?)
  2075. if (tmp3 == 64) {
  2076. tmp3 = 0;
  2077. tmp2++;
  2078. }
  2079. if (tmp2 == 0){
  2080. tmp2 = 1;
  2081. tmp3 = 1;
  2082. }
  2083. //1. set mask 2. write value to data transfer register 3. start the transfer
  2084. //SCT(FracRate)
  2085. AMAZON_WRITE_REGISTER_L(QSB_SET_SCT_MASK, QSB_RTM_ADDR);
  2086. AMAZON_WRITE_REGISTER_L(tmp3,QSB_RTD_ADDR);
  2087. AMAZON_WRITE_REGISTER_L(((QSB_TABLESEL_SCT<<QSB_TABLESEL_SHIFT)|QSB_RAMAC_REG_LOW|QSB_WRITE|i),QSB_RAMAC_ADDR);
  2088. //SPT(SBV + PN + IntRage)
  2089. AMAZON_WRITE_REGISTER_L(QSB_SET_SPT_MASK, QSB_RTM_ADDR);
  2090. AMAZON_WRITE_REGISTER_L(QSB_SPT_SBVALID|tmp2|(i<<16),QSB_RTD_ADDR);
  2091. AMAZON_WRITE_REGISTER_L(((QSB_TABLESEL_SPT<<QSB_TABLESEL_SHIFT)|QSB_RAMAC_REG_LOW|QSB_WRITE|i),QSB_RAMAC_ADDR);
  2092. }
  2093. }
  2094. //SWIE: Setup Service Request Control Registers to enable interrupts
  2095. AMAZON_WRITE_REGISTER_L(SRC_CLRR|SRC_TOS_MIPS | SRC_SRE_ENABLE | AMAZON_SWIE_INT, SWIE_ISRC_ADDR);
  2096. AMAZON_WRITE_REGISTER_L(SRC_CLRR|SRC_TOS_MIPS | SRC_SRE_ENABLE | AMAZON_SWIE_INT, SWIE_ESRC_ADDR);
  2097. wmb();
  2098. #ifdef AMAZON_TPE_TEST_AAL5_INT
  2099. AMAZON_WRITE_REGISTER_L(AAL5R_ISR_FE,AAL5_RIMR0_ADDR);
  2100. AMAZON_WRITE_REGISTER_L(0, AAL5_SIMR0_ADDR);
  2101. AMAZON_WRITE_REGISTER_L(SRC_CLRR|SRC_TOS_MIPS | SRC_SRE_ENABLE | AMAZON_AAL5_INT,AAL5_SSRC0_ADDR);
  2102. AMAZON_WRITE_REGISTER_L(SRC_CLRR|SRC_TOS_MIPS | SRC_SRE_ENABLE | AMAZON_AAL5_INT,AAL5_RSRC0_ADDR);
  2103. #endif //AMAZON_TPE_TEST_AAL5_INT
  2104. AMAZON_WRITE_REGISTER_L(dev->aal5.tx_max_sdu,AAL5_SMFL_ADDR);
  2105. AMAZON_WRITE_REGISTER_L(dev->aal5.rx_max_sdu,AAL5_RMFL_ADDR);
  2106. AMAZON_WRITE_REGISTER_L(AAL5_SCMD_MODE_POLL // enable polling mode
  2107. |AAL5_SCMD_SS
  2108. |AAL5_SCMD_AR
  2109. ,AAL5_SCMD_ADDR);
  2110. //start CBM
  2111. AMAZON_WRITE_REGISTER_L(CBM_CFG_START,CBM_CFG_ADDR);
  2112. wmb();
  2113. return 0;
  2114. init_no_mem:
  2115. if (mem_addr != NULL) free_pages((unsigned long)mem_addr,get_log_2(((CBM_CELL_SIZE * dev->cbm.free_cell_cnt) >>PAGE_SHIFT) + 1));
  2116. #ifdef CONFIG_USE_VENUS
  2117. //to work around a bug, bit15 of QDOFF address should be 1
  2118. if (qd_addr != NULL) free_pages((unsigned long)qd_addr,4);
  2119. #else //CONFIG_USE_VENUS
  2120. if (qd_addr != NULL) kfree(qd_addr);
  2121. #endif //CONFIG_USE_VENUS
  2122. return -ENOMEM;
  2123. }
  2124. /*
  2125. * Brief: Create entry in /proc for status information
  2126. */
  2127. void atm_create_proc(void)
  2128. {
  2129. create_proc_read_entry("amazon_atm", 0,NULL, amazon_atm_read_procmem,(void*)PROC_ATM);
  2130. create_proc_read_entry("amazon_atm_mib", 0,NULL, amazon_atm_read_procmem,(void*)PROC_MIB);
  2131. create_proc_read_entry("amazon_atm_vcc", 0,NULL, amazon_atm_read_procmem,(void*)PROC_VCC);
  2132. #if 0
  2133. create_proc_read_entry("amazon_atm_aal5", 0,NULL, amazon_atm_read_procmem,(void*)PROC_AAL5);
  2134. create_proc_read_entry("amazon_atm_cbm", 0,NULL, amazon_atm_read_procmem,(void*)PROC_CBM);
  2135. create_proc_read_entry("amazon_atm_htu", 0,NULL, amazon_atm_read_procmem,(void*)PROC_HTU);
  2136. create_proc_read_entry("amazon_atm_qsb", 0,NULL, amazon_atm_read_procmem,(void*)PROC_QSB);
  2137. create_proc_read_entry("amazon_atm_swie", 0,NULL, amazon_atm_read_procmem,(void*)PROC_SWIE);
  2138. #endif
  2139. }
  2140. /*
  2141. * Brief: Delete entry in /proc for status information
  2142. */
  2143. void atm_delete_proc(void)
  2144. {
  2145. remove_proc_entry("amazon_atm", NULL);
  2146. remove_proc_entry("amazon_atm_mib", NULL);
  2147. remove_proc_entry("amazon_atm_vcc", NULL);
  2148. #if 0
  2149. remove_proc_entry("amazon_atm_aal5", NULL);
  2150. remove_proc_entry("amazon_atm_cbm", NULL);
  2151. remove_proc_entry("amazon_atm_htu", NULL);
  2152. remove_proc_entry("amazon_atm_qsb", NULL);
  2153. remove_proc_entry("amazon_atm_swie", NULL);
  2154. #endif
  2155. }
  2156. /* Brief: Initialize ATM module
  2157. * Parameters: no
  2158. * Return: &g_atm_dev - sucessful
  2159. * NULL - fails:
  2160. * 1. invalid parameter
  2161. * 2. No memory available
  2162. * Description:
  2163. * This function configure the TPE components according to the input info,
  2164. * -CBM
  2165. * -HTU
  2166. * -QSB
  2167. * -AAL5
  2168. *
  2169. */
  2170. amazon_atm_dev_t * amazon_atm_create(void)
  2171. {
  2172. int i;
  2173. AMAZON_TPE_DMSG("atm_init\n");
  2174. /************initialize global data structure****************/
  2175. atm_constructor(&g_atm_dev);
  2176. /***********allocate kernel resources****************/
  2177. //bottom halfs for SWEX
  2178. swex_start_task.routine = amazon_atm_swex;
  2179. swex_start_task.data = NULL;
  2180. swex_complete_task.routine = amazon_atm_swex_push;
  2181. swex_complete_task.data = NULL;
  2182. #ifdef AMAZON_TPE_SCR
  2183. a5r_task.routine = amazon_atm_a5r;
  2184. a5r_task.data = NULL;
  2185. #endif //AMAZON_TPE_SCR
  2186. //SWIN semaphore
  2187. sema_init(&(g_atm_dev.swie.in_sem), 1);
  2188. //SWIE lock
  2189. clear_bit(SWIE_LOCK, &(g_atm_dev.swie.lock));
  2190. //SWIE wait queue
  2191. init_waitqueue_head(&(g_atm_dev.swie.sleep));
  2192. atm_create_proc();
  2193. //register DMA
  2194. memset(&g_dma_dev,0,sizeof(struct dma_device_info));
  2195. strcpy(g_dma_dev.device_name,"TPE");
  2196. g_dma_dev.weight=1;
  2197. g_dma_dev.num_tx_chan=2;
  2198. g_dma_dev.num_rx_chan=2;
  2199. g_dma_dev.ack=1;
  2200. g_dma_dev.tx_burst_len=4;
  2201. g_dma_dev.rx_burst_len=4;
  2202. //DMA TX
  2203. for(i=0;i<1;i++){
  2204. g_dma_dev.tx_chan[i].weight=QOS_DEFAULT_WGT;
  2205. g_dma_dev.tx_chan[i].desc_num=10;
  2206. g_dma_dev.tx_chan[i].packet_size=g_atm_dev.aal5.tx_max_sdu + AAL5S_INBOUND_HEADER;
  2207. g_dma_dev.tx_chan[i].control=1;
  2208. }
  2209. //DMA RX
  2210. for(i=0;i<2;i++){
  2211. g_dma_dev.rx_chan[i].weight=QOS_DEFAULT_WGT;
  2212. /* BingTao's suggestion, change from 5->10 will prevent packet loss in NO_TX_INT mode */
  2213. g_dma_dev.rx_chan[i].desc_num=10;
  2214. g_dma_dev.rx_chan[i].packet_size=(g_atm_dev.aal5.rx_max_sdu + AAL5R_TRAILER_LEN+0x10f)&(~0xf);
  2215. g_dma_dev.rx_chan[i].control=1;
  2216. }
  2217. g_dma_dev.intr_handler=amazon_atm_dma_handler;
  2218. g_dma_dev.buffer_alloc=amazon_atm_alloc_rx;
  2219. g_dma_dev.buffer_free=amazon_atm_free_tx;
  2220. dma_device_register(&g_dma_dev);
  2221. /***********intialize the atm hardware ****************/
  2222. if ( atm_init_hard(&g_atm_dev) != 0){
  2223. return NULL;
  2224. }
  2225. //start CBM
  2226. AMAZON_WRITE_REGISTER_L(CBM_CFG_START,CBM_CFG_ADDR);
  2227. wmb();
  2228. //Start HTU
  2229. AMAZON_WRITE_REGISTER_L(HTU_CFG_START ,HTU_CFG_ADDR);
  2230. wmb();
  2231. // Register interrupts for insertion and extraction
  2232. request_irq(AMAZON_SWIE_INT, amazon_atm_swie_isr, IRQF_DISABLED, "tpe_swie", NULL);
  2233. request_irq(AMAZON_CBM_INT, amazon_atm_cbm_isr, IRQF_DISABLED, "tpe_cbm", NULL);
  2234. #ifdef AMAZON_ATM_DEBUG
  2235. request_irq(AMAZON_HTU_INT , amazon_atm_htu_isr, IRQF_DISABLED, "tpe_htu", NULL);
  2236. #endif
  2237. #ifdef AMAZON_TPE_TEST_AAL5_INT
  2238. request_irq(AMAZON_AAL5_INT, amazon_atm_aal5_isr, IRQF_DISABLED, "tpe_aal5", NULL);
  2239. #endif
  2240. return &g_atm_dev;
  2241. }
  2242. /* Brief: clean up atm
  2243. * Parameters: no
  2244. * Return: no
  2245. * Description:
  2246. * Disable the device.
  2247. */
  2248. void amazon_atm_cleanup(void){
  2249. int i;
  2250. clear_bit(SWIE_LOCK, &(g_atm_dev.swie.lock));
  2251. wake_up(&g_atm_dev.swie.sleep);
  2252. up(&g_atm_dev.swie.in_sem);
  2253. // diable SWIE interrupts
  2254. AMAZON_WRITE_REGISTER_L(0, SWIE_ISRC_ADDR);
  2255. AMAZON_WRITE_REGISTER_L(0, SWIE_ESRC_ADDR);
  2256. wmb();
  2257. // Disable schedulers ( including interrupts )-----------------------
  2258. for (i = 0; i < AMAZON_ATM_PORT_NUM; i++);
  2259. {
  2260. AMAZON_WRITE_REGISTER_L(QSB_SET_SPT_SBVALID_MASK, QSB_RTM_ADDR);
  2261. AMAZON_WRITE_REGISTER_L( 0 ,QSB_RTD_ADDR);
  2262. AMAZON_WRITE_REGISTER_L( (QSB_TABLESEL_SPT<<QSB_TABLESEL_SHIFT)
  2263. | QSB_RAMAC_REG_LOW
  2264. | QSB_WRITE
  2265. | i,
  2266. QSB_RAMAC_ADDR);
  2267. }
  2268. // disable QSB_Interrupts
  2269. AMAZON_WRITE_REGISTER_L( 0, QSB_IMR_ADDR);
  2270. AMAZON_WRITE_REGISTER_L( 0, QSB_SRC_ADDR);
  2271. // disable CBM interrupts
  2272. AMAZON_WRITE_REGISTER_L( 0 , CBM_IMR0_ADDR);
  2273. AMAZON_WRITE_REGISTER_L( 0 , CBM_SRC0_ADDR);
  2274. // set CBM start bit to 0
  2275. AMAZON_WRITE_REGISTER_L(0,CBM_CFG_ADDR);
  2276. // request hardware extraction of queue 0, wich should force the CBM
  2277. // to recognize that the start bit is not set
  2278. AMAZON_WRITE_REGISTER_L(CBM_HWEXPAR_PN_A5, CBM_HWEXPAR0_ADDR);
  2279. // write frame extraction command into the hw extract command register
  2280. AMAZON_WRITE_REGISTER_L(CBM_HWEXCMD_FE0, CBM_HWEXCMD_ADDR);
  2281. // disable htu
  2282. // disable all HTU interrupts
  2283. AMAZON_WRITE_REGISTER_L(0 ,HTU_IMR0_ADDR);
  2284. AMAZON_WRITE_REGISTER_L(0 ,HTU_SRC0_ADDR);
  2285. if (g_atm_dev.cbm.allocated){
  2286. free_pages((unsigned long)g_atm_dev.cbm.mem_addr, get_log_2(((CBM_CELL_SIZE * g_atm_dev.cbm.free_cell_cnt) >>PAGE_SHIFT)+1));
  2287. #ifdef CONFIG_USE_VENUS
  2288. //to work around a bug, bit15 of QDOFF address should be 1
  2289. free_pages((unsigned long)g_atm_dev.cbm.qd_addr_free,4);
  2290. #else //CONFIG_USE_VENUS
  2291. kfree(g_atm_dev.cbm.qd_addr);
  2292. #endif //CONFIG_USE_VENUS
  2293. }
  2294. atm_delete_proc();
  2295. // free interrupts for insertion and extraction
  2296. dma_device_unregister(&g_dma_dev);
  2297. free_irq(AMAZON_SWIE_INT, NULL);
  2298. free_irq(AMAZON_CBM_INT, NULL);
  2299. #ifdef AMAZON_ATM_DEBUG
  2300. free_irq(AMAZON_HTU_INT, NULL);
  2301. #endif
  2302. #ifdef AMAZON_TPE_TEST_AAL5_INT
  2303. free_irq(AMAZON_AAL5_INT, NULL);
  2304. #endif
  2305. }
  2306. /************************ ATM network interface ***********************************************/
  2307. /* Brief: getsockopt
  2308. */
  2309. int amazon_atm_getsockopt(struct atm_vcc *vcc, int level, int optname, char *optval, int optlen)
  2310. {
  2311. int err=0;
  2312. atm_aal5_vcc_t mib_vcc;
  2313. AMAZON_TPE_DMSG("1\n");
  2314. switch (optname){
  2315. case SO_AMAZON_ATM_MIB_VCC:
  2316. AMAZON_TPE_DMSG("2\n");
  2317. err = amazon_atm_vcc_mib(vcc, &mib_vcc);
  2318. AMAZON_TPE_DMSG("%u\n",mib_vcc.aal5VccCrcErrors);
  2319. err = copy_to_user((void *)optval,&mib_vcc, sizeof(mib_vcc));
  2320. AMAZON_TPE_DMSG("err %u\n",err);
  2321. break;
  2322. default:
  2323. return -EFAULT;
  2324. }
  2325. return err;
  2326. }
  2327. /* Brief: IOCTL
  2328. */
  2329. int amazon_atm_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
  2330. {
  2331. int err=0;
  2332. //MIB
  2333. atm_cell_ifEntry_t mib_cell;
  2334. atm_aal5_ifEntry_t mib_aal5;
  2335. atm_aal5_vcc_x_t mib_vcc;
  2336. if (_IOC_TYPE(cmd) != AMAZON_ATM_IOC_MAGIC) return -ENOTTY;
  2337. if (_IOC_NR(cmd) > AMAZON_ATM_IOC_MAXNR) return -ENOTTY;
  2338. if (_IOC_DIR(cmd) & _IOC_READ)
  2339. err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
  2340. else if (_IOC_DIR(cmd) & _IOC_WRITE)
  2341. err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
  2342. if (err) {
  2343. AMAZON_TPE_EMSG("acess verification fails \n");
  2344. return -EFAULT;
  2345. }
  2346. switch(cmd) {
  2347. case AMAZON_ATM_MIB_CELL:
  2348. err = amazon_atm_cell_mib(&mib_cell,(u32)arg);
  2349. if (err==0){
  2350. err = __copy_to_user((void *)arg,&mib_cell,sizeof(mib_cell));
  2351. }else{
  2352. AMAZON_TPE_EMSG("cannot get MIB ATM_CELL\n");
  2353. }
  2354. break;
  2355. case AMAZON_ATM_MIB_AAL5:
  2356. err = amazon_atm_aal5_mib(&mib_aal5);
  2357. if (err==0){
  2358. err=__copy_to_user(arg, &mib_aal5, sizeof(mib_aal5));
  2359. }else{
  2360. AMAZON_TPE_EMSG("cannot get MIB ATM_AAL5\n");
  2361. }
  2362. break;
  2363. case AMAZON_ATM_MIB_VCC:
  2364. err=__copy_from_user(&mib_vcc,arg, sizeof(mib_vcc));
  2365. AMAZON_TPE_DMSG("return of copy_from_user %x\n",err);
  2366. err = amazon_atm_vcc_mib_x(mib_vcc.vpi, mib_vcc.vci, &(mib_vcc.mib_vcc));
  2367. if (err==0){
  2368. err=__copy_to_user(arg, &mib_vcc, sizeof(mib_vcc));
  2369. }else{
  2370. AMAZON_TPE_EMSG("cannot get MIB ATM_VCC\n");
  2371. }
  2372. default:
  2373. return -ENOTTY;
  2374. }
  2375. return err;
  2376. }
  2377. /* Brief: return a link list of OAM related time stamp info
  2378. * Parameter: none
  2379. * Return:
  2380. a link list of "struct oam_last_activity" data
  2381. * Description:
  2382. Each time, a F4/F5 cell or AAL5 packet is received, the time stamp is updated.
  2383. Through this call, u get a list of this time stamp for all active connection.
  2384. Please note that u have read-only access.
  2385. */
  2386. const struct oam_last_activity* get_oam_time_stamp()
  2387. {
  2388. int i,j;
  2389. for(i=CBM_DEFAULT_Q_OFFSET+CBM_RX_OFFSET,j=0;i<CBM_RX_OFFSET+CBM_DEFAULT_Q_OFFSET+AMAZON_ATM_MAX_VCC_NUM;i++){
  2390. if (g_atm_dev.queues[i].free != 1 && g_atm_dev.queues[i].vcc != NULL){
  2391. //active connection
  2392. if (j !=0 ){
  2393. g_oam_time_stamp[j-1].next = &g_oam_time_stamp[j];
  2394. }
  2395. g_oam_time_stamp[j].vpi = g_atm_dev.queues[i].vcc->vpi;
  2396. g_oam_time_stamp[j].vci = g_atm_dev.queues[i].vcc->vci;
  2397. g_oam_time_stamp[j].stamp = g_atm_dev.queues[i].access_time;
  2398. g_oam_time_stamp[j].next = NULL;
  2399. j++;
  2400. }
  2401. }
  2402. if (j==0) {
  2403. return NULL;
  2404. }else{
  2405. return g_oam_time_stamp;
  2406. }
  2407. }
  2408. /* Brief: call back routine for rx
  2409. * Parameter:
  2410. * vcc atm_vcc pointer
  2411. * skb data if no error
  2412. err error flag, 0: no error, 1:error
  2413. * Return:
  2414. * 0
  2415. * <>0 cannot push up
  2416. * Description:
  2417. * release the packet if cannot push up
  2418. */
  2419. static int amazon_atm_net_push(struct atm_vcc *vcc,struct sk_buff *skb, int err)
  2420. {
  2421. if (err){
  2422. if (vcc && vcc->stats) {
  2423. atomic_inc(&vcc->stats->rx_err);
  2424. }
  2425. }else{
  2426. ATM_SKB(skb)->vcc = vcc;
  2427. if (!atm_charge(vcc, skb->truesize)){
  2428. //no space this vcc
  2429. AMAZON_TPE_EMSG("no space for this vcc\n");
  2430. dev_kfree_skb_any(skb);
  2431. return -ENOMEM;
  2432. }
  2433. atomic_inc(&vcc->stats->rx);
  2434. AMAZON_TPE_DMSG("push to vcc\n");
  2435. vcc->push(vcc,skb);
  2436. }
  2437. return 0;
  2438. }
  2439. int amazon_atm_net_send_oam(struct atm_vcc*vcc, void *cell, int flags)
  2440. {
  2441. return amazon_atm_send_oam(vcc,cell,flags);
  2442. }
  2443. int amazon_atm_net_send(struct atm_vcc *vcc,struct sk_buff *skb)
  2444. {
  2445. int err=0;
  2446. if (vcc->qos.aal == ATM_AAL0 || vcc->qos.aal == ATM_AAL5) {
  2447. err=amazon_atm_send(vcc,skb);
  2448. }else{
  2449. //not supported
  2450. err = -EPROTONOSUPPORT;
  2451. }
  2452. if (err){
  2453. atomic_inc(&vcc->stats->tx_err);
  2454. }else{
  2455. atomic_inc(&vcc->stats->tx);
  2456. }
  2457. AMAZON_TPE_DMSG("sent, tx_inuse:%u\n", atomic_read(&vcc->tx_inuse));
  2458. return err;
  2459. }
  2460. int amazon_atm_net_open(struct atm_vcc *vcc,short vpi, int vci)
  2461. {
  2462. vcc->itf = (int) vcc->dev->dev_data;
  2463. vcc->vpi = vpi;
  2464. vcc->vci = vci;
  2465. return(amazon_atm_open(vcc,amazon_atm_net_push));
  2466. }
  2467. static int amazon_atm_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flgs)
  2468. {
  2469. int qid;
  2470. if (vcc == NULL || qos == NULL){
  2471. AMAZON_TPE_EMSG("invalid parameters\n");
  2472. return -EINVAL;
  2473. }
  2474. qid = amazon_atm_get_queue(vcc);
  2475. if (valid_qid(qid) != 1) {
  2476. AMAZON_TPE_EMSG("no vcc connection opened\n");
  2477. return -EINVAL;
  2478. }
  2479. set_qsb(vcc,qos,qid);
  2480. return 0;
  2481. }
  2482. static struct atmdev_ops amazon_atm_ops = {
  2483. open: amazon_atm_net_open,
  2484. close: amazon_atm_close,
  2485. ioctl: amazon_atm_ioctl,
  2486. send: amazon_atm_net_send,
  2487. send_oam: amazon_atm_net_send_oam,
  2488. // getsockopt: amazon_atm_getsockopt,
  2489. change_qos: amazon_atm_change_qos,
  2490. // proc_read: amazon_atm_proc_read,
  2491. owner: THIS_MODULE,
  2492. }; // ATM device callback functions
  2493. /*
  2494. * brief "/proc" function
  2495. */
  2496. int amazon_atm_read_procmem(char *buf, char **start, off_t offset,int count, int *eof, void *data)
  2497. {
  2498. int buf_off=0; /* for buf */
  2499. int i=0,j=0;
  2500. int type= (u32)data;//which module
  2501. atm_aal5_ifEntry_t mib_aal5;
  2502. atm_cell_ifEntry_t mib_cell;
  2503. atm_aal5_vcc_t mib_vcc;
  2504. switch(type){
  2505. case PROC_MIB:
  2506. //MIB counter
  2507. amazon_atm_aal5_mib(&mib_aal5);
  2508. //TX:
  2509. buf_off+=sprintf(buf+buf_off,"\n============= AAL5 Upstream =========\n");
  2510. buf_off+=sprintf(buf+buf_off,"received %u (pkts) from upper layer\n", mib_aal5.ifOutUcastPkts);
  2511. buf_off+=sprintf(buf+buf_off,"errors: %u (pkts)\n",mib_aal5.ifOutErros);
  2512. buf_off+=sprintf(buf+buf_off,"discards: %u (ptks)\n", mib_aal5.ifOutDiscards);
  2513. buf_off+=sprintf(buf+buf_off,"transmitted: %x-%x (bytes) \n",
  2514. mib_aal5.ifHCOutOctets_h, mib_aal5.ifHCOutOctets_l);
  2515. //RX:
  2516. buf_off+=sprintf(buf+buf_off,"\n============= AAL5 Downstream =========\n");
  2517. buf_off+=sprintf(buf+buf_off,"received %x-%x (bytes)\n",
  2518. mib_aal5.ifHCInOctets_h,mib_aal5.ifHCInOctets_l);
  2519. buf_off+=sprintf(buf+buf_off,"discards: %u (ptks)\n",mib_aal5.ifInDiscards);
  2520. buf_off+=sprintf(buf+buf_off,"errors: %u (ptks)\n",mib_aal5.ifInErrors);
  2521. buf_off+=sprintf(buf+buf_off,"passed %u (ptks) to upper layer\n",mib_aal5.ifInUcastPkts);
  2522. //Cell level
  2523. buf_off+=sprintf(buf+buf_off,"\n============= ATM Cell =========\n");
  2524. amazon_atm_cell_mib(&mib_cell,0);
  2525. #ifdef AMAZON_TPE_READ_ARC
  2526. buf_off+=sprintf(buf+buf_off,"Port 0: downstream received: %x-%x (bytes)\n",mib_cell.ifHCInOctets_h,mib_cell.ifHCInOctets_l);
  2527. buf_off+=sprintf(buf+buf_off,"Port 0: upstream transmitted: %x-%x (bytes)\n",mib_cell.ifHCOutOctets_h,mib_cell.ifHCOutOctets_l);
  2528. buf_off+=sprintf(buf+buf_off,"Port 0: downstream errors: %u (cells)\n",mib_cell.ifInErrors);
  2529. amazon_atm_cell_mib(&mib_cell,1);
  2530. buf_off+=sprintf(buf+buf_off,"Port 1: downstream received: %x-%x (bytes)\n",mib_cell.ifHCInOctets_h,mib_cell.ifHCInOctets_l);
  2531. buf_off+=sprintf(buf+buf_off,"Port 1: upstream transmitted: %x-%x (bytes)\n",mib_cell.ifHCOutOctets_h,mib_cell.ifHCOutOctets_l);
  2532. buf_off+=sprintf(buf+buf_off,"Port 1: downstream errors: %u (cells)\n",mib_cell.ifInErrors);
  2533. #endif
  2534. buf_off+=sprintf(buf+buf_off,"HTU discards: %u (cells)\n",mib_cell.ifInUnknownProtos);
  2535. buf_off+=sprintf(buf+buf_off,"\n====== Specials =====\n");
  2536. buf_off+=sprintf(buf+buf_off,"AAL5S PPD: %u (cells)\n",g_atm_dev.mib_counter.tx_ppd);
  2537. #ifdef AMAZON_TPE_SCR
  2538. buf_off+=sprintf(buf+buf_off,"Reassembly wait: %u \n",g_a5r_wait);
  2539. #endif
  2540. break;
  2541. case PROC_ATM:
  2542. //Interface (Port)
  2543. buf_off+=sprintf(buf+buf_off,"[Interfaces]\n");
  2544. for(i=0;i<AMAZON_ATM_PORT_NUM;i++){
  2545. if (g_atm_dev.ports[i].enable==0){
  2546. buf_off+=sprintf(buf+buf_off,"\tport[%u] not in use\n",i);
  2547. }else{
  2548. buf_off+=sprintf(buf+buf_off,"\tport[%u]\n\t\tmax_conn=%u\n"
  2549. ,i
  2550. ,g_atm_dev.ports[i].max_conn
  2551. );
  2552. buf_off+=sprintf(buf+buf_off,"\t\ttx_max=%u\n\t\trem=%u\n\t\tcur=%u\n"
  2553. ,g_atm_dev.ports[i].tx_max_cr
  2554. ,g_atm_dev.ports[i].tx_rem_cr
  2555. ,g_atm_dev.ports[i].tx_cur_cr
  2556. );
  2557. }
  2558. }
  2559. //Units Info
  2560. //AAL5
  2561. buf_off+=sprintf(buf+buf_off,"[AAL5]\n\tpad=%c(%x)\n\trx_mtu=%u\n\ttx_mtu=%u\n"
  2562. ,g_atm_dev.aal5.padding_byte
  2563. ,g_atm_dev.aal5.padding_byte
  2564. ,g_atm_dev.aal5.rx_max_sdu
  2565. ,g_atm_dev.aal5.tx_max_sdu
  2566. );
  2567. //CBM
  2568. buf_off+=sprintf(buf+buf_off,
  2569. "[CBM]\n\tnrt_thr=%u\n\tclp0_thr=%u\n\tclp1_thr=%u\n\ttx_q_threshold=%u\n\trx_q_threshold=%u\n\toam_q_threshold=%u\n\tfree_cell_cnt=%u\n"
  2570. ,g_atm_dev.cbm.nrt_thr
  2571. ,g_atm_dev.cbm.clp0_thr
  2572. ,g_atm_dev.cbm.clp1_thr
  2573. ,tx_q_threshold
  2574. ,rx_q_threshold
  2575. ,oam_q_threshold
  2576. ,g_atm_dev.cbm.free_cell_cnt
  2577. );
  2578. //QSB
  2579. buf_off+=sprintf(buf+buf_off,"[QSB]\n\ttau=%u\n\ttstepc=%u\n\tsbl=%u\n"
  2580. ,g_atm_dev.qsb.tau
  2581. ,g_atm_dev.qsb.tstepc
  2582. ,g_atm_dev.qsb.sbl
  2583. );
  2584. buf_off+=sprintf(buf+buf_off,"[Debugging]\n\taal5_need_copy=%u\n",g_atm_dev.aal5.cnt_cpy);
  2585. break;
  2586. case PROC_VCC:
  2587. for(i=CBM_DEFAULT_Q_OFFSET,j=0;i<g_atm_dev.cbm.max_q_off+CBM_DEFAULT_Q_OFFSET;i++){
  2588. if (g_atm_dev.queues[i].free!=1){
  2589. buf_off+=sprintf(buf+buf_off,"vcc[%u]\n\tvpi=%u vci=%u itf=%u qid=%u access_time=%u.%u\n"
  2590. ,j++
  2591. ,g_atm_dev.queues[i].vcc->vpi
  2592. ,g_atm_dev.queues[i].vcc->vci
  2593. ,g_atm_dev.queues[i].vcc->itf
  2594. ,i
  2595. ,(u32)g_atm_dev.queues[i+CBM_RX_OFFSET].access_time.tv_sec
  2596. ,(u32)g_atm_dev.queues[i+CBM_RX_OFFSET].access_time.tv_usec
  2597. );
  2598. buf_off+=sprintf(buf+buf_off,"\tqos_tx class=%u max_pcr=%u pcr=%u min_pcr=%u scr=%u mbs=%u cdv=%u\n"
  2599. ,g_atm_dev.queues[i].vcc->qos.txtp.traffic_class
  2600. ,g_atm_dev.queues[i].vcc->qos.txtp.max_pcr
  2601. ,g_atm_dev.queues[i].vcc->qos.txtp.pcr
  2602. ,g_atm_dev.queues[i].vcc->qos.txtp.min_pcr
  2603. ,g_atm_dev.queues[i].vcc->qos.txtp.scr
  2604. ,g_atm_dev.queues[i].vcc->qos.txtp.mbs
  2605. ,g_atm_dev.queues[i].vcc->qos.txtp.cdv
  2606. );
  2607. buf_off+=sprintf(buf+buf_off,"\tqos_rx class=%u max_pcr=%u pcr=%u min_pcr=%u scr=%u mbs=%u cdv=%u\n"
  2608. ,g_atm_dev.queues[i].vcc->qos.rxtp.traffic_class
  2609. ,g_atm_dev.queues[i].vcc->qos.rxtp.max_pcr
  2610. ,g_atm_dev.queues[i].vcc->qos.rxtp.pcr
  2611. ,g_atm_dev.queues[i].vcc->qos.rxtp.min_pcr
  2612. ,g_atm_dev.queues[i].vcc->qos.rxtp.scr
  2613. ,g_atm_dev.queues[i].vcc->qos.rxtp.mbs
  2614. ,g_atm_dev.queues[i].vcc->qos.rxtp.cdv
  2615. );
  2616. __amazon_atm_vcc_mib((i+CBM_RX_OFFSET),&mib_vcc);
  2617. buf_off+=sprintf(buf+buf_off,"\tCRC error=%u\n", mib_vcc.aal5VccCrcErrors);
  2618. buf_off+=sprintf(buf+buf_off,"\toversized packet=%u\n", mib_vcc.aal5VccOverSizedSDUs);
  2619. #ifdef AMAZON_ATM_DEBUG
  2620. if ( valid_qid(i+CBM_RX_OFFSET)){
  2621. buf_off+=sprintf(buf+buf_off,"\tdownstream statics\n" );
  2622. buf_off+=sprintf(buf+buf_off,"\t\tpackets=%u\n",g_atm_dev.queues[i+CBM_RX_OFFSET].qs[QS_PKT]);
  2623. buf_off+=sprintf(buf+buf_off,"\t\terr_packets=%u\n",g_atm_dev.queues[i+CBM_RX_OFFSET].qs[QS_ERR] );
  2624. buf_off+=sprintf(buf+buf_off,"\t\tsw_dropped=%u\n",g_atm_dev.queues[i+CBM_RX_OFFSET].qs[QS_SW_DROP] );
  2625. }
  2626. buf_off+=sprintf(buf+buf_off,"\tupstream statics\n" );
  2627. buf_off+=sprintf(buf+buf_off,"\t\tpackets=%u\n",g_atm_dev.queues[i].qs[QS_PKT]);
  2628. buf_off+=sprintf(buf+buf_off,"\t\terr_packets=%u\n",g_atm_dev.queues[i].qs[QS_ERR] );
  2629. buf_off+=sprintf(buf+buf_off,"\t\thw_dropped=%u\n",g_atm_dev.queues[i].qs[QS_HW_DROP] );
  2630. buf_off+=sprintf(buf+buf_off,"\t\tsw_dropped=%u\n",g_atm_dev.queues[i].qs[QS_SW_DROP] );
  2631. #endif
  2632. }
  2633. }
  2634. break;
  2635. default:
  2636. break;
  2637. }
  2638. if(buf_off>0) *eof = 1;
  2639. return buf_off;
  2640. }
  2641. #ifdef AMAZON_TPE_AAL5_RECOVERY
  2642. extern int (*tpe_reset)(void);
  2643. extern int (*tpe_start)(void);
  2644. extern int (*tpe_inject)(void);
  2645. /* Brief: Reset TPE hardware
  2646. * Description
  2647. * This is a wordaround for AAL5 bug. It tries to reset TPE.
  2648. * take care of software
  2649. * setup all previous connection
  2650. */
  2651. int amazon_tpe_reset(void)
  2652. {
  2653. struct atm_vcc * vcc;
  2654. int err=0;
  2655. int i;
  2656. u8 * qd_addr;
  2657. u32 reg_l, reg_h;
  2658. unsigned int a_cfg_value=0;
  2659. unsigned int a_cfg_old_value=0;
  2660. atm_aal5_ifEntry_t mib_aal5;
  2661. atm_cell_ifEntry_t mib_cell;
  2662. //make sure all cells transmitting out first
  2663. //Segmentation done
  2664. amazon_atm_aal5_mib(&mib_aal5);
  2665. reg_l = g_atm_dev.mib_counter.tx_cnt_l;
  2666. reg_h = g_atm_dev.mib_counter.tx_cnt_h;
  2667. while(1){
  2668. mdelay(10);
  2669. amazon_atm_aal5_mib(&mib_aal5);
  2670. if( (reg_l == g_atm_dev.mib_counter.tx_cnt_l) && (reg_h == g_atm_dev.mib_counter.tx_cnt_h) ){
  2671. break;
  2672. }
  2673. AMAZON_TPE_DMSG("AAL5 Segmentation still in progress!\n");
  2674. reg_l = g_atm_dev.mib_counter.tx_cnt_l;
  2675. reg_h = g_atm_dev.mib_counter.tx_cnt_h;
  2676. }
  2677. //QSB done
  2678. qd_addr = (u8 *) KSEG1ADDR((unsigned long)g_atm_dev.cbm.qd_addr);
  2679. for (i=1;i<15;i++){
  2680. while ( (err=readl(qd_addr+i*CBM_QD_SIZE+0x8)&0xffff) !=0 ){
  2681. mdelay(20);
  2682. AMAZON_TPE_DMSG("queue %u not empty (%u)\n",i,err);
  2683. }
  2684. }
  2685. //insurance for interfaces between Aware and CARB
  2686. mdelay(100);
  2687. amazon_atm_cell_mib(&mib_cell,0);
  2688. amazon_atm_cell_mib(&mib_cell,1);
  2689. amazon_atm_aal5_mib(&mib_aal5);
  2690. mb();
  2691. while ( (AMAZON_READ_REGISTER_L(AR_CELLRDY_BC0) != 0 ) || (AMAZON_READ_REGISTER_L(AR_CELLRDY_BC0) != 0 ) ){
  2692. AMAZON_TPE_EMSG("\nwaiting for AWARE");
  2693. AMAZON_TPE_EMSG(" BC0 %u ", AMAZON_READ_REGISTER_L(AR_CELLRDY_BC0));
  2694. AMAZON_TPE_EMSG(" BC1 %u ", AMAZON_READ_REGISTER_L(AR_CELLRDY_BC1));
  2695. AMAZON_TPE_EMSG("\n");
  2696. mdelay(1);
  2697. }
  2698. // disable AAI module
  2699. meiDebugRead(A_CFG_ADDR,&a_cfg_value,1);
  2700. a_cfg_old_value=a_cfg_value;
  2701. a_cfg_value &= (~(0x2800));
  2702. meiDebugWrite(A_CFG_ADDR,&a_cfg_value,1);
  2703. //clear buffer
  2704. a_cfg_value = 0x1;
  2705. meiDebugWrite(AR_CB0_STATUS_ADDR,&a_cfg_value,1);
  2706. meiDebugWrite(AR_CB1_STATUS_ADDR,&a_cfg_value,1);
  2707. if ( atm_init_hard(&g_atm_dev) != 0){
  2708. return -EIO;
  2709. }
  2710. sema_init(&(g_atm_dev.swie.in_sem), 1);
  2711. //SWIE lock
  2712. clear_bit(SWIE_LOCK, &(g_atm_dev.swie.lock));
  2713. //SWIE wait queue
  2714. init_waitqueue_head(&(g_atm_dev.swie.sleep));
  2715. for (i=CBM_DEFAULT_Q_OFFSET;i<AMAZON_ATM_MAX_QUEUE_NUM/2;i++) {
  2716. vcc = g_atm_dev.queues[i].vcc;
  2717. if (vcc != NULL){
  2718. set_qsb(vcc, &vcc->qos, i);
  2719. set_qd(vcc, i);
  2720. mb();
  2721. err=set_htu(vcc,i);
  2722. if (err){
  2723. AMAZON_TPE_EMSG("set htu entry fails %u\n",err);
  2724. }
  2725. }
  2726. }
  2727. meiDebugWrite(A_CFG_ADDR,&a_cfg_old_value,1);
  2728. #if 0
  2729. //reset DFE
  2730. *(AMAZON_RST_REQ) = (* AMAZON_RST_REQ) | (AMAZON_RST_REQ_DFE);
  2731. mb();
  2732. *(AMAZON_RST_REQ) = (* AMAZON_RST_REQ) & (~AMAZON_RST_REQ_DFE);
  2733. mb();
  2734. #endif
  2735. return 0;
  2736. }
  2737. /* Brief: Send a ATM EoP packet to save DMA channel
  2738. */
  2739. int amazon_tpe_inject_debug_cell(void)
  2740. {
  2741. //Send a ATM cell to save DMA channel
  2742. u8 qid;
  2743. unsigned char atm_cell[48];
  2744. qid = 0x11;
  2745. AMAZON_TPE_DMSG("qid = %d\n",qid);
  2746. memset(atm_cell,0,48);
  2747. atm_cell[3] = 0x2;
  2748. if ( amazon_atm_swin(qid,atm_cell)) {
  2749. AMAZON_TPE_EMSG("cannot insert EoP cell\n");
  2750. return -1;
  2751. }
  2752. return 0;
  2753. }
  2754. /* Brief: start HTU (TPE)
  2755. */
  2756. int amazon_tpe_start(void)
  2757. {
  2758. AMAZON_WRITE_REGISTER_L(HTU_CFG_START ,HTU_CFG_ADDR);
  2759. wmb();
  2760. return 0;
  2761. }
  2762. #endif //AMAZON_TPE_AAL5_RECOVERY
  2763. #ifdef AMAZON_CHECK_LINK
  2764. extern int (*adsl_link_notify)(int);
  2765. /* Brief: notify link status of ADSL link
  2766. * Parameters: 0 link down
  2767. * 1 link up
  2768. * Returns: 0 OK
  2769. * Details: called by MEI driver
  2770. * should update status and inform upper layer
  2771. */
  2772. int amazon_tpe_link_notify(int status)
  2773. {
  2774. adsl_link_status = status;
  2775. AMAZON_TPE_DMSG("link status %s\n",(status==1)?"Up":"Down");
  2776. if (status == 0){
  2777. //wait until no cells in upstream queues
  2778. set_current_state(TASK_INTERRUPTIBLE);
  2779. schedule_timeout(2*HZ);
  2780. }
  2781. return 0;
  2782. }
  2783. #endif //ifdef AMAZON_CHECK_LINK
  2784. /*
  2785. * Brief: Initialize ATM module
  2786. *
  2787. * Return Value: ENOMEM - No memory available
  2788. * EBUSY - Cannot register atm device
  2789. * ERESTARTSYS - Process interrupted by other signal
  2790. * 0 - OK, module initialized
  2791. *
  2792. * Description:
  2793. * This function registers an atm device for all UTOPIA devices.
  2794. * It also allocates memory for the private device data structures
  2795. */
  2796. int __init amazon_atm_net_init(void)
  2797. {
  2798. int i;
  2799. int err=0;
  2800. amazon_atm_dev_t *dev = NULL;
  2801. if ((dev=amazon_atm_create()) != NULL){
  2802. for(i=0;i<AMAZON_ATM_PORT_NUM;i++){
  2803. if (!dev->ports[i].enable){
  2804. amazon_atm_devs[i] = NULL;
  2805. continue;
  2806. }
  2807. amazon_atm_devs[i] =atm_dev_register("amazon_atm",&amazon_atm_ops,-1,0UL);
  2808. if (amazon_atm_devs[i] == NULL){
  2809. AMAZON_TPE_EMSG("atm_dev_register fails\n");
  2810. err = -EIO;
  2811. goto amazon_atm_net_init_exit;
  2812. }else{
  2813. AMAZON_TPE_DMSG("registering device %u\n",i);
  2814. amazon_atm_devs[i]->ci_range.vpi_bits = 8;
  2815. amazon_atm_devs[i]->ci_range.vci_bits = 16;
  2816. amazon_atm_devs[i]->link_rate = dev->ports[i].tx_max_cr;
  2817. amazon_atm_devs[i]->dev_data = (void *) i;
  2818. }
  2819. }
  2820. }else{
  2821. err = -ENOMEM;
  2822. AMAZON_TPE_EMSG("cannot init atm device\n");
  2823. goto amazon_atm_net_init_exit;
  2824. }
  2825. #ifdef AMAZON_TPE_AAL5_RECOVERY
  2826. tpe_reset = & amazon_tpe_reset;
  2827. tpe_start = & amazon_tpe_start;
  2828. tpe_inject = & amazon_tpe_inject_debug_cell;
  2829. #endif //AMAZON_TPE_AAL5_RECOVERY
  2830. #ifdef AMAZON_CHECK_LINK
  2831. adsl_link_notify=amazon_tpe_link_notify;
  2832. #endif //AMAZON_CHECK_LINK
  2833. amazon_atm_net_init_exit:
  2834. return err;
  2835. }
  2836. void __exit amazon_atm_net_cleanup(void)
  2837. {
  2838. int i;
  2839. amazon_atm_cleanup();
  2840. for(i=0;i<AMAZON_ATM_PORT_NUM;i++){
  2841. if (amazon_atm_devs[i] != NULL){
  2842. AMAZON_TPE_DMSG("unregister dev %u\n",i);
  2843. atm_dev_deregister(amazon_atm_devs[i]);
  2844. }
  2845. }
  2846. return;
  2847. }
  2848. EXPORT_SYMBOL(get_oam_time_stamp);
  2849. MODULE_LICENSE ("GPL");
  2850. MODULE_AUTHOR("Infineon IFAP DC COM [email protected]");
  2851. MODULE_DESCRIPTION("AMAZON ATM driver");
  2852. module_init(amazon_atm_net_init);
  2853. module_exit(amazon_atm_net_cleanup);