wanxlfw.S 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  1. .psize 0
  2. /*
  3. wanXL serial card driver for Linux
  4. card firmware part
  5. Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl>
  6. This program is free software; you can redistribute it and/or modify it
  7. under the terms of version 2 of the GNU General Public License
  8. as published by the Free Software Foundation.
  9. DPRAM BDs:
  10. 0x000 - 0x050 TX#0 0x050 - 0x140 RX#0
  11. 0x140 - 0x190 TX#1 0x190 - 0x280 RX#1
  12. 0x280 - 0x2D0 TX#2 0x2D0 - 0x3C0 RX#2
  13. 0x3C0 - 0x410 TX#3 0x410 - 0x500 RX#3
  14. 000 5FF 1536 Bytes Dual-Port RAM User Data / BDs
  15. 600 6FF 256 Bytes Dual-Port RAM User Data / BDs
  16. 700 7FF 256 Bytes Dual-Port RAM User Data / BDs
  17. C00 CBF 192 Bytes Dual-Port RAM Parameter RAM Page 1
  18. D00 DBF 192 Bytes Dual-Port RAM Parameter RAM Page 2
  19. E00 EBF 192 Bytes Dual-Port RAM Parameter RAM Page 3
  20. F00 FBF 192 Bytes Dual-Port RAM Parameter RAM Page 4
  21. local interrupts level
  22. NMI 7
  23. PIT timer, CPM (RX/TX complete) 4
  24. PCI9060 DMA and PCI doorbells 3
  25. Cable - not used 1
  26. */
  27. #include <linux/hdlc.h>
  28. #include "wanxl.h"
  29. /* memory addresses and offsets */
  30. MAX_RAM_SIZE = 16 * 1024 * 1024 // max RAM supported by hardware
  31. PCI9060_VECTOR = 0x0000006C
  32. CPM_IRQ_BASE = 0x40
  33. ERROR_VECTOR = CPM_IRQ_BASE * 4
  34. SCC1_VECTOR = (CPM_IRQ_BASE + 0x1E) * 4
  35. SCC2_VECTOR = (CPM_IRQ_BASE + 0x1D) * 4
  36. SCC3_VECTOR = (CPM_IRQ_BASE + 0x1C) * 4
  37. SCC4_VECTOR = (CPM_IRQ_BASE + 0x1B) * 4
  38. CPM_IRQ_LEVEL = 4
  39. TIMER_IRQ = 128
  40. TIMER_IRQ_LEVEL = 4
  41. PITR_CONST = 0x100 + 16 // 1 Hz timer
  42. MBAR = 0x0003FF00
  43. VALUE_WINDOW = 0x40000000
  44. ORDER_WINDOW = 0xC0000000
  45. PLX = 0xFFF90000
  46. CSRA = 0xFFFB0000
  47. CSRB = 0xFFFB0002
  48. CSRC = 0xFFFB0004
  49. CSRD = 0xFFFB0006
  50. STATUS_CABLE_LL = 0x2000
  51. STATUS_CABLE_DTR = 0x1000
  52. DPRBASE = 0xFFFC0000
  53. SCC1_BASE = DPRBASE + 0xC00
  54. MISC_BASE = DPRBASE + 0xCB0
  55. SCC2_BASE = DPRBASE + 0xD00
  56. SCC3_BASE = DPRBASE + 0xE00
  57. SCC4_BASE = DPRBASE + 0xF00
  58. // offset from SCCx_BASE
  59. // SCC_xBASE contain offsets from DPRBASE and must be divisible by 8
  60. SCC_RBASE = 0 // 16-bit RxBD base address
  61. SCC_TBASE = 2 // 16-bit TxBD base address
  62. SCC_RFCR = 4 // 8-bit Rx function code
  63. SCC_TFCR = 5 // 8-bit Tx function code
  64. SCC_MRBLR = 6 // 16-bit maximum Rx buffer length
  65. SCC_C_MASK = 0x34 // 32-bit CRC constant
  66. SCC_C_PRES = 0x38 // 32-bit CRC preset
  67. SCC_MFLR = 0x46 // 16-bit max Rx frame length (without flags)
  68. REGBASE = DPRBASE + 0x1000
  69. PICR = REGBASE + 0x026 // 16-bit periodic irq control
  70. PITR = REGBASE + 0x02A // 16-bit periodic irq timing
  71. OR1 = REGBASE + 0x064 // 32-bit RAM bank #1 options
  72. CICR = REGBASE + 0x540 // 32(24)-bit CP interrupt config
  73. CIMR = REGBASE + 0x548 // 32-bit CP interrupt mask
  74. CISR = REGBASE + 0x54C // 32-bit CP interrupts in-service
  75. PADIR = REGBASE + 0x550 // 16-bit PortA data direction bitmap
  76. PAPAR = REGBASE + 0x552 // 16-bit PortA pin assignment bitmap
  77. PAODR = REGBASE + 0x554 // 16-bit PortA open drain bitmap
  78. PADAT = REGBASE + 0x556 // 16-bit PortA data register
  79. PCDIR = REGBASE + 0x560 // 16-bit PortC data direction bitmap
  80. PCPAR = REGBASE + 0x562 // 16-bit PortC pin assignment bitmap
  81. PCSO = REGBASE + 0x564 // 16-bit PortC special options
  82. PCDAT = REGBASE + 0x566 // 16-bit PortC data register
  83. PCINT = REGBASE + 0x568 // 16-bit PortC interrupt control
  84. CR = REGBASE + 0x5C0 // 16-bit Command register
  85. SCC1_REGS = REGBASE + 0x600
  86. SCC2_REGS = REGBASE + 0x620
  87. SCC3_REGS = REGBASE + 0x640
  88. SCC4_REGS = REGBASE + 0x660
  89. SICR = REGBASE + 0x6EC // 32-bit SI clock route
  90. // offset from SCCx_REGS
  91. SCC_GSMR_L = 0x00 // 32 bits
  92. SCC_GSMR_H = 0x04 // 32 bits
  93. SCC_PSMR = 0x08 // 16 bits
  94. SCC_TODR = 0x0C // 16 bits
  95. SCC_DSR = 0x0E // 16 bits
  96. SCC_SCCE = 0x10 // 16 bits
  97. SCC_SCCM = 0x14 // 16 bits
  98. SCC_SCCS = 0x17 // 8 bits
  99. #if QUICC_MEMCPY_USES_PLX
  100. .macro memcpy_from_pci src, dest, len // len must be < 8 MB
  101. addl #3, \len
  102. andl #0xFFFFFFFC, \len // always copy n * 4 bytes
  103. movel \src, PLX_DMA_0_PCI
  104. movel \dest, PLX_DMA_0_LOCAL
  105. movel \len, PLX_DMA_0_LENGTH
  106. movel #0x0103, PLX_DMA_CMD_STS // start channel 0 transfer
  107. bsr memcpy_from_pci_run
  108. .endm
  109. .macro memcpy_to_pci src, dest, len
  110. addl #3, \len
  111. andl #0xFFFFFFFC, \len // always copy n * 4 bytes
  112. movel \src, PLX_DMA_1_LOCAL
  113. movel \dest, PLX_DMA_1_PCI
  114. movel \len, PLX_DMA_1_LENGTH
  115. movel #0x0301, PLX_DMA_CMD_STS // start channel 1 transfer
  116. bsr memcpy_to_pci_run
  117. .endm
  118. #else
  119. .macro memcpy src, dest, len // len must be < 65536 bytes
  120. movel %d7, -(%sp) // src and dest must be < 256 MB
  121. movel \len, %d7 // bits 0 and 1
  122. lsrl #2, \len
  123. andl \len, \len
  124. beq 99f // only 0 - 3 bytes
  125. subl #1, \len // for dbf
  126. 98: movel (\src)+, (\dest)+
  127. dbfw \len, 98b
  128. 99: movel %d7, \len
  129. btstl #1, \len
  130. beq 99f
  131. movew (\src)+, (\dest)+
  132. 99: btstl #0, \len
  133. beq 99f
  134. moveb (\src)+, (\dest)+
  135. 99:
  136. movel (%sp)+, %d7
  137. .endm
  138. .macro memcpy_from_pci src, dest, len
  139. addl #VALUE_WINDOW, \src
  140. memcpy \src, \dest, \len
  141. .endm
  142. .macro memcpy_to_pci src, dest, len
  143. addl #VALUE_WINDOW, \dest
  144. memcpy \src, \dest, \len
  145. .endm
  146. #endif
  147. .macro wait_for_command
  148. 99: btstl #0, CR
  149. bne 99b
  150. .endm
  151. /****************************** card initialization *******************/
  152. .text
  153. .global _start
  154. _start: bra init
  155. .org _start + 4
  156. ch_status_addr: .long 0, 0, 0, 0
  157. rx_descs_addr: .long 0
  158. init:
  159. #if DETECT_RAM
  160. movel OR1, %d0
  161. andl #0xF00007FF, %d0 // mask AMxx bits
  162. orl #0xFFFF800 & ~(MAX_RAM_SIZE - 1), %d0 // update RAM bank size
  163. movel %d0, OR1
  164. #endif
  165. addl #VALUE_WINDOW, rx_descs_addr // PCI addresses of shared data
  166. clrl %d0 // D0 = 4 * port
  167. init_1: tstl ch_status_addr(%d0)
  168. beq init_2
  169. addl #VALUE_WINDOW, ch_status_addr(%d0)
  170. init_2: addl #4, %d0
  171. cmpl #4 * 4, %d0
  172. bne init_1
  173. movel #pci9060_interrupt, PCI9060_VECTOR
  174. movel #error_interrupt, ERROR_VECTOR
  175. movel #port_interrupt_1, SCC1_VECTOR
  176. movel #port_interrupt_2, SCC2_VECTOR
  177. movel #port_interrupt_3, SCC3_VECTOR
  178. movel #port_interrupt_4, SCC4_VECTOR
  179. movel #timer_interrupt, TIMER_IRQ * 4
  180. movel #0x78000000, CIMR // only SCCx IRQs from CPM
  181. movew #(TIMER_IRQ_LEVEL << 8) + TIMER_IRQ, PICR // interrupt from PIT
  182. movew #PITR_CONST, PITR
  183. // SCC1=SCCa SCC2=SCCb SCC3=SCCc SCC4=SCCd prio=4 HP=-1 IRQ=64-79
  184. movel #0xD41F40 + (CPM_IRQ_LEVEL << 13), CICR
  185. movel #0x543, PLX_DMA_0_MODE // 32-bit, Ready, Burst, IRQ
  186. movel #0x543, PLX_DMA_1_MODE
  187. movel #0x0, PLX_DMA_0_DESC // from PCI to local
  188. movel #0x8, PLX_DMA_1_DESC // from local to PCI
  189. movel #0x101, PLX_DMA_CMD_STS // enable both DMA channels
  190. // enable local IRQ, DMA, doorbells and PCI IRQ
  191. orl #0x000F0300, PLX_INTERRUPT_CS
  192. #if DETECT_RAM
  193. bsr ram_test
  194. #else
  195. movel #1, PLX_MAILBOX_5 // non-zero value = init complete
  196. #endif
  197. bsr check_csr
  198. movew #0xFFFF, PAPAR // all pins are clocks/data
  199. clrw PADIR // first function
  200. clrw PCSO // CD and CTS always active
  201. /****************************** main loop *****************************/
  202. main: movel channel_stats, %d7 // D7 = doorbell + irq status
  203. clrl channel_stats
  204. tstl %d7
  205. bne main_1
  206. // nothing to do - wait for next event
  207. stop #0x2200 // supervisor + IRQ level 2
  208. movew #0x2700, %sr // disable IRQs again
  209. bra main
  210. main_1: clrl %d0 // D0 = 4 * port
  211. clrl %d6 // D6 = doorbell to host value
  212. main_l: btstl #DOORBELL_TO_CARD_CLOSE_0, %d7
  213. beq main_op
  214. bclrl #DOORBELL_TO_CARD_OPEN_0, %d7 // in case both bits are set
  215. bsr close_port
  216. main_op:
  217. btstl #DOORBELL_TO_CARD_OPEN_0, %d7
  218. beq main_cl
  219. bsr open_port
  220. main_cl:
  221. btstl #DOORBELL_TO_CARD_TX_0, %d7
  222. beq main_txend
  223. bsr tx
  224. main_txend:
  225. btstl #TASK_SCC_0, %d7
  226. beq main_next
  227. bsr tx_end
  228. bsr rx
  229. main_next:
  230. lsrl #1, %d7 // port status for next port
  231. addl #4, %d0 // D0 = 4 * next port
  232. cmpl #4 * 4, %d0
  233. bne main_l
  234. movel %d6, PLX_DOORBELL_FROM_CARD // signal the host
  235. bra main
  236. /****************************** open port *****************************/
  237. open_port: // D0 = 4 * port, D6 = doorbell to host
  238. movel ch_status_addr(%d0), %a0 // A0 = port status address
  239. tstl STATUS_OPEN(%a0)
  240. bne open_port_ret // port already open
  241. movel #1, STATUS_OPEN(%a0) // confirm the port is open
  242. // setup BDs
  243. clrl tx_in(%d0)
  244. clrl tx_out(%d0)
  245. clrl tx_count(%d0)
  246. clrl rx_in(%d0)
  247. movel SICR, %d1 // D1 = clock settings in SICR
  248. andl clocking_mask(%d0), %d1
  249. cmpl #CLOCK_TXFROMRX, STATUS_CLOCKING(%a0)
  250. bne open_port_clock_ext
  251. orl clocking_txfromrx(%d0), %d1
  252. bra open_port_set_clock
  253. open_port_clock_ext:
  254. orl clocking_ext(%d0), %d1
  255. open_port_set_clock:
  256. movel %d1, SICR // update clock settings in SICR
  257. orw #STATUS_CABLE_DTR, csr_output(%d0) // DTR on
  258. bsr check_csr // call with disabled timer interrupt
  259. // Setup TX descriptors
  260. movel first_buffer(%d0), %d1 // D1 = starting buffer address
  261. movel tx_first_bd(%d0), %a1 // A1 = starting TX BD address
  262. movel #TX_BUFFERS - 2, %d2 // D2 = TX_BUFFERS - 1 counter
  263. movel #0x18000000, %d3 // D3 = initial TX BD flags: Int + Last
  264. cmpl #PARITY_NONE, STATUS_PARITY(%a0)
  265. beq open_port_tx_loop
  266. bsetl #26, %d3 // TX BD flag: Transmit CRC
  267. open_port_tx_loop:
  268. movel %d3, (%a1)+ // TX flags + length
  269. movel %d1, (%a1)+ // buffer address
  270. addl #BUFFER_LENGTH, %d1
  271. dbfw %d2, open_port_tx_loop
  272. bsetl #29, %d3 // TX BD flag: Wrap (last BD)
  273. movel %d3, (%a1)+ // Final TX flags + length
  274. movel %d1, (%a1)+ // buffer address
  275. // Setup RX descriptors // A1 = starting RX BD address
  276. movel #RX_BUFFERS - 2, %d2 // D2 = RX_BUFFERS - 1 counter
  277. open_port_rx_loop:
  278. movel #0x90000000, (%a1)+ // RX flags + length
  279. movel %d1, (%a1)+ // buffer address
  280. addl #BUFFER_LENGTH, %d1
  281. dbfw %d2, open_port_rx_loop
  282. movel #0xB0000000, (%a1)+ // Final RX flags + length
  283. movel %d1, (%a1)+ // buffer address
  284. // Setup port parameters
  285. movel scc_base_addr(%d0), %a1 // A1 = SCC_BASE address
  286. movel scc_reg_addr(%d0), %a2 // A2 = SCC_REGS address
  287. movel #0xFFFF, SCC_SCCE(%a2) // clear status bits
  288. movel #0x0000, SCC_SCCM(%a2) // interrupt mask
  289. movel tx_first_bd(%d0), %d1
  290. movew %d1, SCC_TBASE(%a1) // D1 = offset of first TxBD
  291. addl #TX_BUFFERS * 8, %d1
  292. movew %d1, SCC_RBASE(%a1) // D1 = offset of first RxBD
  293. moveb #0x8, SCC_RFCR(%a1) // Intel mode, 1000
  294. moveb #0x8, SCC_TFCR(%a1)
  295. // Parity settings
  296. cmpl #PARITY_CRC16_PR1_CCITT, STATUS_PARITY(%a0)
  297. bne open_port_parity_1
  298. clrw SCC_PSMR(%a2) // CRC16-CCITT
  299. movel #0xF0B8, SCC_C_MASK(%a1)
  300. movel #0xFFFF, SCC_C_PRES(%a1)
  301. movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC
  302. movew #2, parity_bytes(%d0)
  303. bra open_port_2
  304. open_port_parity_1:
  305. cmpl #PARITY_CRC32_PR1_CCITT, STATUS_PARITY(%a0)
  306. bne open_port_parity_2
  307. movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT
  308. movel #0xDEBB20E3, SCC_C_MASK(%a1)
  309. movel #0xFFFFFFFF, SCC_C_PRES(%a1)
  310. movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC
  311. movew #4, parity_bytes(%d0)
  312. bra open_port_2
  313. open_port_parity_2:
  314. cmpl #PARITY_CRC16_PR0_CCITT, STATUS_PARITY(%a0)
  315. bne open_port_parity_3
  316. clrw SCC_PSMR(%a2) // CRC16-CCITT preset 0
  317. movel #0xF0B8, SCC_C_MASK(%a1)
  318. clrl SCC_C_PRES(%a1)
  319. movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC
  320. movew #2, parity_bytes(%d0)
  321. bra open_port_2
  322. open_port_parity_3:
  323. cmpl #PARITY_CRC32_PR0_CCITT, STATUS_PARITY(%a0)
  324. bne open_port_parity_4
  325. movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT preset 0
  326. movel #0xDEBB20E3, SCC_C_MASK(%a1)
  327. clrl SCC_C_PRES(%a1)
  328. movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC
  329. movew #4, parity_bytes(%d0)
  330. bra open_port_2
  331. open_port_parity_4:
  332. clrw SCC_PSMR(%a2) // no parity
  333. movel #0xF0B8, SCC_C_MASK(%a1)
  334. movel #0xFFFF, SCC_C_PRES(%a1)
  335. movew #HDLC_MAX_MRU, SCC_MFLR(%a1) // 0 bytes for CRC
  336. clrw parity_bytes(%d0)
  337. open_port_2:
  338. movel #0x00000003, SCC_GSMR_H(%a2) // RTSM
  339. cmpl #ENCODING_NRZI, STATUS_ENCODING(%a0)
  340. bne open_port_nrz
  341. movel #0x10040900, SCC_GSMR_L(%a2) // NRZI: TCI Tend RECN+TENC=1
  342. bra open_port_3
  343. open_port_nrz:
  344. movel #0x10040000, SCC_GSMR_L(%a2) // NRZ: TCI Tend RECN+TENC=0
  345. open_port_3:
  346. movew #BUFFER_LENGTH, SCC_MRBLR(%a1)
  347. movel %d0, %d1
  348. lsll #4, %d1 // D1 bits 7 and 6 = port
  349. orl #1, %d1
  350. movew %d1, CR // Init SCC RX and TX params
  351. wait_for_command
  352. // TCI Tend ENR ENT
  353. movew #0x001F, SCC_SCCM(%a2) // TXE RXF BSY TXB RXB interrupts
  354. orl #0x00000030, SCC_GSMR_L(%a2) // enable SCC
  355. open_port_ret:
  356. rts
  357. /****************************** close port ****************************/
  358. close_port: // D0 = 4 * port, D6 = doorbell to host
  359. movel scc_reg_addr(%d0), %a0 // A0 = SCC_REGS address
  360. clrw SCC_SCCM(%a0) // no SCC interrupts
  361. andl #0xFFFFFFCF, SCC_GSMR_L(%a0) // Disable ENT and ENR
  362. andw #~STATUS_CABLE_DTR, csr_output(%d0) // DTR off
  363. bsr check_csr // call with disabled timer interrupt
  364. movel ch_status_addr(%d0), %d1
  365. clrl STATUS_OPEN(%d1) // confirm the port is closed
  366. rts
  367. /****************************** transmit packet ***********************/
  368. // queue packets for transmission
  369. tx: // D0 = 4 * port, D6 = doorbell to host
  370. cmpl #TX_BUFFERS, tx_count(%d0)
  371. beq tx_ret // all DB's = descs in use
  372. movel tx_out(%d0), %d1
  373. movel %d1, %d2 // D1 = D2 = tx_out BD# = desc#
  374. mulul #DESC_LENGTH, %d2 // D2 = TX desc offset
  375. addl ch_status_addr(%d0), %d2
  376. addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address
  377. cmpl #PACKET_FULL, (%d2) // desc status
  378. bne tx_ret
  379. // queue it
  380. movel 4(%d2), %a0 // PCI address
  381. lsll #3, %d1 // BD is 8-bytes long
  382. addl tx_first_bd(%d0), %d1 // D1 = current tx_out BD addr
  383. movel 4(%d1), %a1 // A1 = dest address
  384. movel 8(%d2), %d2 // D2 = length
  385. movew %d2, 2(%d1) // length into BD
  386. memcpy_from_pci %a0, %a1, %d2
  387. bsetl #31, (%d1) // CP go ahead
  388. // update tx_out and tx_count
  389. movel tx_out(%d0), %d1
  390. addl #1, %d1
  391. cmpl #TX_BUFFERS, %d1
  392. bne tx_1
  393. clrl %d1
  394. tx_1: movel %d1, tx_out(%d0)
  395. addl #1, tx_count(%d0)
  396. bra tx
  397. tx_ret: rts
  398. /****************************** packet received ***********************/
  399. // Service receive buffers // D0 = 4 * port, D6 = doorbell to host
  400. rx: movel rx_in(%d0), %d1 // D1 = rx_in BD#
  401. lsll #3, %d1 // BD is 8-bytes long
  402. addl rx_first_bd(%d0), %d1 // D1 = current rx_in BD address
  403. movew (%d1), %d2 // D2 = RX BD flags
  404. btstl #15, %d2
  405. bne rx_ret // BD still empty
  406. btstl #1, %d2
  407. bne rx_overrun
  408. tstw parity_bytes(%d0)
  409. bne rx_parity
  410. bclrl #2, %d2 // do not test for CRC errors
  411. rx_parity:
  412. andw #0x0CBC, %d2 // mask status bits
  413. cmpw #0x0C00, %d2 // correct frame
  414. bne rx_bad_frame
  415. clrl %d3
  416. movew 2(%d1), %d3
  417. subw parity_bytes(%d0), %d3 // D3 = packet length
  418. cmpw #HDLC_MAX_MRU, %d3
  419. bgt rx_bad_frame
  420. rx_good_frame:
  421. movel rx_out, %d2
  422. mulul #DESC_LENGTH, %d2
  423. addl rx_descs_addr, %d2 // D2 = RX desc address
  424. cmpl #PACKET_EMPTY, (%d2) // desc stat
  425. bne rx_overrun
  426. movel %d3, 8(%d2)
  427. movel 4(%d1), %a0 // A0 = source address
  428. movel 4(%d2), %a1
  429. tstl %a1
  430. beq rx_ignore_data
  431. memcpy_to_pci %a0, %a1, %d3
  432. rx_ignore_data:
  433. movel packet_full(%d0), (%d2) // update desc stat
  434. // update D6 and rx_out
  435. bsetl #DOORBELL_FROM_CARD_RX, %d6 // signal host that RX completed
  436. movel rx_out, %d2
  437. addl #1, %d2
  438. cmpl #RX_QUEUE_LENGTH, %d2
  439. bne rx_1
  440. clrl %d2
  441. rx_1: movel %d2, rx_out
  442. rx_free_bd:
  443. andw #0xF000, (%d1) // clear CM and error bits
  444. bsetl #31, (%d1) // free BD
  445. // update rx_in
  446. movel rx_in(%d0), %d1
  447. addl #1, %d1
  448. cmpl #RX_BUFFERS, %d1
  449. bne rx_2
  450. clrl %d1
  451. rx_2: movel %d1, rx_in(%d0)
  452. bra rx
  453. rx_overrun:
  454. movel ch_status_addr(%d0), %d2
  455. addl #1, STATUS_RX_OVERRUNS(%d2)
  456. bra rx_free_bd
  457. rx_bad_frame:
  458. movel ch_status_addr(%d0), %d2
  459. addl #1, STATUS_RX_FRAME_ERRORS(%d2)
  460. bra rx_free_bd
  461. rx_ret: rts
  462. /****************************** packet transmitted ********************/
  463. // Service transmit buffers // D0 = 4 * port, D6 = doorbell to host
  464. tx_end: tstl tx_count(%d0)
  465. beq tx_end_ret // TX buffers already empty
  466. movel tx_in(%d0), %d1
  467. movel %d1, %d2 // D1 = D2 = tx_in BD# = desc#
  468. lsll #3, %d1 // BD is 8-bytes long
  469. addl tx_first_bd(%d0), %d1 // D1 = current tx_in BD address
  470. movew (%d1), %d3 // D3 = TX BD flags
  471. btstl #15, %d3
  472. bne tx_end_ret // BD still being transmitted
  473. // update D6, tx_in and tx_count
  474. orl bell_tx(%d0), %d6 // signal host that TX desc freed
  475. subl #1, tx_count(%d0)
  476. movel tx_in(%d0), %d1
  477. addl #1, %d1
  478. cmpl #TX_BUFFERS, %d1
  479. bne tx_end_1
  480. clrl %d1
  481. tx_end_1:
  482. movel %d1, tx_in(%d0)
  483. // free host's descriptor
  484. mulul #DESC_LENGTH, %d2 // D2 = TX desc offset
  485. addl ch_status_addr(%d0), %d2
  486. addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address
  487. btstl #1, %d3
  488. bne tx_end_underrun
  489. movel #PACKET_SENT, (%d2)
  490. bra tx_end
  491. tx_end_underrun:
  492. movel #PACKET_UNDERRUN, (%d2)
  493. bra tx_end
  494. tx_end_ret: rts
  495. /****************************** PLX PCI9060 DMA memcpy ****************/
  496. #if QUICC_MEMCPY_USES_PLX
  497. // called with interrupts disabled
  498. memcpy_from_pci_run:
  499. movel %d0, -(%sp)
  500. movew %sr, -(%sp)
  501. memcpy_1:
  502. movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly
  503. btstl #4, %d0 // transfer done?
  504. bne memcpy_end
  505. stop #0x2200 // enable PCI9060 interrupts
  506. movew #0x2700, %sr // disable interrupts again
  507. bra memcpy_1
  508. memcpy_to_pci_run:
  509. movel %d0, -(%sp)
  510. movew %sr, -(%sp)
  511. memcpy_2:
  512. movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly
  513. btstl #12, %d0 // transfer done?
  514. bne memcpy_end
  515. stop #0x2200 // enable PCI9060 interrupts
  516. movew #0x2700, %sr // disable interrupts again
  517. bra memcpy_2
  518. memcpy_end:
  519. movew (%sp)+, %sr
  520. movel (%sp)+, %d0
  521. rts
  522. #endif
  523. /****************************** PLX PCI9060 interrupt *****************/
  524. pci9060_interrupt:
  525. movel %d0, -(%sp)
  526. movel PLX_DOORBELL_TO_CARD, %d0
  527. movel %d0, PLX_DOORBELL_TO_CARD // confirm all requests
  528. orl %d0, channel_stats
  529. movel #0x0909, PLX_DMA_CMD_STS // clear DMA ch #0 and #1 interrupts
  530. movel (%sp)+, %d0
  531. rte
  532. /****************************** SCC interrupts ************************/
  533. port_interrupt_1:
  534. orl #0, SCC1_REGS + SCC_SCCE; // confirm SCC events
  535. orl #1 << TASK_SCC_0, channel_stats
  536. movel #0x40000000, CISR
  537. rte
  538. port_interrupt_2:
  539. orl #0, SCC2_REGS + SCC_SCCE; // confirm SCC events
  540. orl #1 << TASK_SCC_1, channel_stats
  541. movel #0x20000000, CISR
  542. rte
  543. port_interrupt_3:
  544. orl #0, SCC3_REGS + SCC_SCCE; // confirm SCC events
  545. orl #1 << TASK_SCC_2, channel_stats
  546. movel #0x10000000, CISR
  547. rte
  548. port_interrupt_4:
  549. orl #0, SCC4_REGS + SCC_SCCE; // confirm SCC events
  550. orl #1 << TASK_SCC_3, channel_stats
  551. movel #0x08000000, CISR
  552. rte
  553. error_interrupt:
  554. rte
  555. /****************************** cable and PM routine ******************/
  556. // modified registers: none
  557. check_csr:
  558. movel %d0, -(%sp)
  559. movel %d1, -(%sp)
  560. movel %d2, -(%sp)
  561. movel %a0, -(%sp)
  562. movel %a1, -(%sp)
  563. clrl %d0 // D0 = 4 * port
  564. movel #CSRA, %a0 // A0 = CSR address
  565. check_csr_loop:
  566. movew (%a0), %d1 // D1 = CSR input bits
  567. andl #0xE7, %d1 // PM and cable sense bits (no DCE bit)
  568. cmpw #STATUS_CABLE_V35 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
  569. bne check_csr_1
  570. movew #0x0E08, %d1
  571. bra check_csr_valid
  572. check_csr_1:
  573. cmpw #STATUS_CABLE_X21 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
  574. bne check_csr_2
  575. movew #0x0408, %d1
  576. bra check_csr_valid
  577. check_csr_2:
  578. cmpw #STATUS_CABLE_V24 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
  579. bne check_csr_3
  580. movew #0x0208, %d1
  581. bra check_csr_valid
  582. check_csr_3:
  583. cmpw #STATUS_CABLE_EIA530 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
  584. bne check_csr_disable
  585. movew #0x0D08, %d1
  586. bra check_csr_valid
  587. check_csr_disable:
  588. movew #0x0008, %d1 // D1 = disable everything
  589. movew #0x80E7, %d2 // D2 = input mask: ignore DSR
  590. bra check_csr_write
  591. check_csr_valid: // D1 = mode and IRQ bits
  592. movew csr_output(%d0), %d2
  593. andw #0x3000, %d2 // D2 = requested LL and DTR bits
  594. orw %d2, %d1 // D1 = all requested output bits
  595. movew #0x80FF, %d2 // D2 = input mask: include DSR
  596. check_csr_write:
  597. cmpw old_csr_output(%d0), %d1
  598. beq check_csr_input
  599. movew %d1, old_csr_output(%d0)
  600. movew %d1, (%a0) // Write CSR output bits
  601. check_csr_input:
  602. movew (PCDAT), %d1
  603. andw dcd_mask(%d0), %d1
  604. beq check_csr_dcd_on // DCD and CTS signals are negated
  605. movew (%a0), %d1 // D1 = CSR input bits
  606. andw #~STATUS_CABLE_DCD, %d1 // DCD off
  607. bra check_csr_previous
  608. check_csr_dcd_on:
  609. movew (%a0), %d1 // D1 = CSR input bits
  610. orw #STATUS_CABLE_DCD, %d1 // DCD on
  611. check_csr_previous:
  612. andw %d2, %d1 // input mask
  613. movel ch_status_addr(%d0), %a1
  614. cmpl STATUS_CABLE(%a1), %d1 // check for change
  615. beq check_csr_next
  616. movel %d1, STATUS_CABLE(%a1) // update status
  617. movel bell_cable(%d0), PLX_DOORBELL_FROM_CARD // signal the host
  618. check_csr_next:
  619. addl #2, %a0 // next CSR register
  620. addl #4, %d0 // D0 = 4 * next port
  621. cmpl #4 * 4, %d0
  622. bne check_csr_loop
  623. movel (%sp)+, %a1
  624. movel (%sp)+, %a0
  625. movel (%sp)+, %d2
  626. movel (%sp)+, %d1
  627. movel (%sp)+, %d0
  628. rts
  629. /****************************** timer interrupt ***********************/
  630. timer_interrupt:
  631. bsr check_csr
  632. rte
  633. /****************************** RAM sizing and test *******************/
  634. #if DETECT_RAM
  635. ram_test:
  636. movel #0x12345678, %d1 // D1 = test value
  637. movel %d1, (128 * 1024 - 4)
  638. movel #128 * 1024, %d0 // D0 = RAM size tested
  639. ram_test_size:
  640. cmpl #MAX_RAM_SIZE, %d0
  641. beq ram_test_size_found
  642. movel %d0, %a0
  643. addl #128 * 1024 - 4, %a0
  644. cmpl (%a0), %d1
  645. beq ram_test_size_check
  646. ram_test_next_size:
  647. lsll #1, %d0
  648. bra ram_test_size
  649. ram_test_size_check:
  650. eorl #0xFFFFFFFF, %d1
  651. movel %d1, (128 * 1024 - 4)
  652. cmpl (%a0), %d1
  653. bne ram_test_next_size
  654. ram_test_size_found: // D0 = RAM size
  655. movel %d0, %a0 // A0 = fill ptr
  656. subl #firmware_end + 4, %d0
  657. lsrl #2, %d0
  658. movel %d0, %d1 // D1 = DBf counter
  659. ram_test_fill:
  660. movel %a0, -(%a0)
  661. dbfw %d1, ram_test_fill
  662. subl #0x10000, %d1
  663. cmpl #0xFFFFFFFF, %d1
  664. bne ram_test_fill
  665. ram_test_loop: // D0 = DBf counter
  666. cmpl (%a0)+, %a0
  667. dbnew %d0, ram_test_loop
  668. bne ram_test_found_bad
  669. subl #0x10000, %d0
  670. cmpl #0xFFFFFFFF, %d0
  671. bne ram_test_loop
  672. bra ram_test_all_ok
  673. ram_test_found_bad:
  674. subl #4, %a0
  675. ram_test_all_ok:
  676. movel %a0, PLX_MAILBOX_5
  677. rts
  678. #endif
  679. /****************************** constants *****************************/
  680. scc_reg_addr:
  681. .long SCC1_REGS, SCC2_REGS, SCC3_REGS, SCC4_REGS
  682. scc_base_addr:
  683. .long SCC1_BASE, SCC2_BASE, SCC3_BASE, SCC4_BASE
  684. tx_first_bd:
  685. .long DPRBASE
  686. .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8
  687. .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 2
  688. .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 3
  689. rx_first_bd:
  690. .long DPRBASE + TX_BUFFERS * 8
  691. .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8
  692. .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 2
  693. .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 3
  694. first_buffer:
  695. .long BUFFERS_ADDR
  696. .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH
  697. .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 2
  698. .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 3
  699. bell_tx:
  700. .long 1 << DOORBELL_FROM_CARD_TX_0, 1 << DOORBELL_FROM_CARD_TX_1
  701. .long 1 << DOORBELL_FROM_CARD_TX_2, 1 << DOORBELL_FROM_CARD_TX_3
  702. bell_cable:
  703. .long 1 << DOORBELL_FROM_CARD_CABLE_0, 1 << DOORBELL_FROM_CARD_CABLE_1
  704. .long 1 << DOORBELL_FROM_CARD_CABLE_2, 1 << DOORBELL_FROM_CARD_CABLE_3
  705. packet_full:
  706. .long PACKET_FULL, PACKET_FULL + 1, PACKET_FULL + 2, PACKET_FULL + 3
  707. clocking_ext:
  708. .long 0x0000002C, 0x00003E00, 0x002C0000, 0x3E000000
  709. clocking_txfromrx:
  710. .long 0x0000002D, 0x00003F00, 0x002D0000, 0x3F000000
  711. clocking_mask:
  712. .long 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
  713. dcd_mask:
  714. .word 0x020, 0, 0x080, 0, 0x200, 0, 0x800
  715. .ascii "wanXL firmware\n"
  716. .asciz "Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl>\n"
  717. /****************************** variables *****************************/
  718. .align 4
  719. channel_stats: .long 0
  720. tx_in: .long 0, 0, 0, 0 // transmitted
  721. tx_out: .long 0, 0, 0, 0 // received from host for transmission
  722. tx_count: .long 0, 0, 0, 0 // currently in transmit queue
  723. rx_in: .long 0, 0, 0, 0 // received from port
  724. rx_out: .long 0 // transmitted to host
  725. parity_bytes: .word 0, 0, 0, 0, 0, 0, 0 // only 4 words are used
  726. csr_output: .word 0
  727. old_csr_output: .word 0, 0, 0, 0, 0, 0, 0
  728. .align 4
  729. firmware_end: // must be dword-aligned