wanxlfw.S 23 KB

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