3 wanXL serial card driver for Linux
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.
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
32 PIT timer, CPM (RX/TX complete) 4
33 PCI9060 DMA and PCI doorbells 3
37 #include <linux/hdlc.h>
38 #include <linux/hdlc/ioctl.h>
41 /* memory addresses and offsets */
43 MAX_RAM_SIZE = 16 * 1024 * 1024 // max RAM supported by hardware
45 PCI9060_VECTOR = 0x0000006C
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
55 PITR_CONST = 0x100 + 16 // 1 Hz timer
59 VALUE_WINDOW = 0x40000000
60 ORDER_WINDOW = 0xC0000000
68 STATUS_CABLE_LL = 0x2000
69 STATUS_CABLE_DTR = 0x1000
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
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
136 .macro memcpy_to_pci src, dest, 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
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
153 beq 99f // only 0 - 3 bytes
154 subl #1, \len // for dbf
155 98: movel (\src)+, (\dest)+
160 movew (\src)+, (\dest)+
163 moveb (\src)+, (\dest)+
168 .macro memcpy_from_pci src, dest, len
169 addl #VALUE_WINDOW, \src
170 memcpy \src, \dest, \len
173 .macro memcpy_to_pci src, dest, len
174 addl #VALUE_WINDOW, \dest
175 memcpy \src, \dest, \len
180 .macro wait_for_command
188 /****************************** card initialization *******************/
194 ch_status_addr: .long 0, 0, 0, 0
195 rx_descs_addr: .long 0
200 andl #0xF00007FF, %d0 // mask AMxx bits
201 orl #0xFFFF800 & ~(MAX_RAM_SIZE - 1), %d0 // update RAM bank size
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)
209 addl #VALUE_WINDOW, ch_status_addr(%d0)
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
239 movel #1, PLX_MAILBOX_5 // non-zero value = init complete
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
255 // nothing to do - wait for next event
256 stop #0x2200 // supervisor + IRQ level 2
257 movew #0x2700, %sr // disable IRQs again
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
265 bclrl #DOORBELL_TO_CARD_OPEN_0, %d7 // in case both bits are set
268 btstl #DOORBELL_TO_CARD_OPEN_0, %d7
272 btstl #DOORBELL_TO_CARD_TX_0, %d7
276 btstl #TASK_SCC_0, %d7
282 lsrl #1, %d7 // port status for next port
283 addl #4, %d0 // D0 = 4 * next port
286 movel %d6, PLX_DOORBELL_FROM_CARD // signal the host
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
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
311 orl clocking_ext(%d0), %d1
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
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
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)
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)
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)
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)
387 movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC
388 movew #2, parity_bytes(%d0)
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)
397 movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC
398 movew #4, parity_bytes(%d0)
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)
409 movel #0x00000003, SCC_GSMR_H(%a2) // RTSM
410 cmpl #ENCODING_NRZI, STATUS_ENCODING(%a0)
412 movel #0x10040900, SCC_GSMR_L(%a2) // NRZI: TCI Tend RECN+TENC=1
416 movel #0x10040000, SCC_GSMR_L(%a2) // NRZ: TCI Tend RECN+TENC=0
418 movew #BUFFER_LENGTH, SCC_MRBLR(%a1)
420 lsll #4, %d1 // D1 bits 7 and 6 = port
422 movew %d1, CR // Init SCC RX and TX params
426 movew #0x001F, SCC_SCCM(%a2) // TXE RXF BSY TXB RXB interrupts
427 orl #0x00000030, SCC_GSMR_L(%a2) // enable SCC
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
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
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
475 cmpl #TX_BUFFERS, %d1
478 tx_1: movel %d1, tx_out(%d0)
480 addl #1, tx_count(%d0)
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
494 bne rx_ret // BD still empty
499 tstw parity_bytes(%d0)
501 bclrl #2, %d2 // do not test for CRC errors
503 andw #0x0CBC, %d2 // mask status bits
504 cmpw #0x0C00, %d2 // correct frame
508 subw parity_bytes(%d0), %d3 // D3 = packet length
509 cmpw #HDLC_MAX_MRU, %d3
514 mulul #DESC_LENGTH, %d2
515 addl rx_descs_addr, %d2 // D2 = RX desc address
516 cmpl #PACKET_EMPTY, (%d2) // desc stat
520 movel 4(%d1), %a0 // A0 = source address
524 memcpy_to_pci %a0, %a1, %d3
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
532 cmpl #RX_QUEUE_LENGTH, %d2
535 rx_1: movel %d2, rx_out
538 andw #0xF000, (%d1) // clear CM and error bits
539 bsetl #31, (%d1) // free BD
541 movel rx_in(%d0), %d1
543 cmpl #RX_BUFFERS, %d1
546 rx_2: movel %d1, rx_in(%d0)
550 movel ch_status_addr(%d0), %d2
551 addl #1, STATUS_RX_OVERRUNS(%d2)
555 movel ch_status_addr(%d0), %d2
556 addl #1, STATUS_RX_FRAME_ERRORS(%d2)
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
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
581 cmpl #TX_BUFFERS, %d1
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
593 movel #PACKET_SENT, (%d2)
597 movel #PACKET_UNDERRUN, (%d2)
603 /****************************** PLX PCI9060 DMA memcpy ****************/
605 #if QUICC_MEMCPY_USES_PLX
606 // called with interrupts disabled
611 movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly
612 btstl #4, %d0 // transfer done?
614 stop #0x2200 // enable PCI9060 interrupts
615 movew #0x2700, %sr // disable interrupts again
622 movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly
623 btstl #12, %d0 // transfer done?
625 stop #0x2200 // enable PCI9060 interrupts
626 movew #0x2700, %sr // disable interrupts again
640 /****************************** PLX PCI9060 interrupt *****************/
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
654 /****************************** SCC interrupts ************************/
657 orl #0, SCC1_REGS + SCC_SCCE; // confirm SCC events
658 orl #1 << TASK_SCC_0, channel_stats
659 movel #0x40000000, CISR
663 orl #0, SCC2_REGS + SCC_SCCE; // confirm SCC events
664 orl #1 << TASK_SCC_1, channel_stats
665 movel #0x20000000, CISR
669 orl #0, SCC3_REGS + SCC_SCCE; // confirm SCC events
670 orl #1 << TASK_SCC_2, channel_stats
671 movel #0x10000000, CISR
675 orl #0, SCC4_REGS + SCC_SCCE; // confirm SCC events
676 orl #1 << TASK_SCC_3, channel_stats
677 movel #0x08000000, CISR
684 /****************************** cable and PM routine ******************/
685 // modified registers: none
693 clrl %d0 // D0 = 4 * port
694 movel #CSRA, %a0 // A0 = CSR address
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
705 cmpw #STATUS_CABLE_X21 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
711 cmpw #STATUS_CABLE_V24 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
717 cmpw #STATUS_CABLE_EIA530 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
718 bne check_csr_disable
723 movew #0x0008, %d1 // D1 = disable everything
724 movew #0x80E7, %d2 // D2 = input mask: ignore DSR
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
734 cmpw old_csr_output(%d0), %d1
736 movew %d1, old_csr_output(%d0)
737 movew %d1, (%a0) // Write CSR output bits
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
748 movew (%a0), %d1 // D1 = CSR input bits
749 orw #STATUS_CABLE_DCD, %d1 // DCD on
751 andw %d2, %d1 // input mask
752 movel ch_status_addr(%d0), %a1
753 cmpl STATUS_CABLE(%a1), %d1 // check for change
755 movel %d1, STATUS_CABLE(%a1) // update status
756 movel bell_cable(%d0), PLX_DOORBELL_FROM_CARD // signal the host
759 addl #2, %a0 // next CSR register
760 addl #4, %d0 // D0 = 4 * next port
772 /****************************** timer interrupt ***********************/
779 /****************************** RAM sizing and test *******************/
782 movel #0x12345678, %d1 // D1 = test value
783 movel %d1, (128 * 1024 - 4)
784 movel #128 * 1024, %d0 // D0 = RAM size tested
786 cmpl #MAX_RAM_SIZE, %d0
787 beq ram_test_size_found
789 addl #128 * 1024 - 4, %a0
791 beq ram_test_size_check
797 eorl #0xFFFFFFFF, %d1
798 movel %d1, (128 * 1024 - 4)
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
806 movel %d0, %d1 // D1 = DBf counter
809 dbfw %d1, ram_test_fill
811 cmpl #0xFFFFFFFF, %d1
814 ram_test_loop: // D0 = DBf counter
816 dbnew %d0, ram_test_loop
817 bne ram_test_found_bad
819 cmpl #0xFFFFFFFF, %d0
826 movel %a0, PLX_MAILBOX_5
831 /****************************** constants *****************************/
834 .long SCC1_REGS, SCC2_REGS, SCC3_REGS, SCC4_REGS
836 .long SCC1_BASE, SCC2_BASE, SCC3_BASE, SCC4_BASE
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
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
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
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
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
865 .long PACKET_FULL, PACKET_FULL + 1, PACKET_FULL + 2, PACKET_FULL + 3
868 .long 0x0000002C, 0x00003E00, 0x002C0000, 0x3E000000
870 .long 0x0000002D, 0x00003F00, 0x002D0000, 0x3F000000
872 .long 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
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 *****************************/
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
894 old_csr_output: .word 0, 0, 0, 0, 0, 0, 0
896 firmware_end: // must be dword-aligned