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