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>
40 /* memory addresses and offsets */
42 MAX_RAM_SIZE = 16 * 1024 * 1024 // max RAM supported by hardware
44 PCI9060_VECTOR = 0x0000006C
46 ERROR_VECTOR = CPM_IRQ_BASE * 4
47 SCC1_VECTOR = (CPM_IRQ_BASE + 0x1E) * 4
48 SCC2_VECTOR = (CPM_IRQ_BASE + 0x1D) * 4
49 SCC3_VECTOR = (CPM_IRQ_BASE + 0x1C) * 4
50 SCC4_VECTOR = (CPM_IRQ_BASE + 0x1B) * 4
54 PITR_CONST = 0x100 + 16 // 1 Hz timer
58 VALUE_WINDOW = 0x40000000
59 ORDER_WINDOW = 0xC0000000
67 STATUS_CABLE_LL = 0x2000
68 STATUS_CABLE_DTR = 0x1000
72 SCC1_BASE = DPRBASE + 0xC00
73 MISC_BASE = DPRBASE + 0xCB0
74 SCC2_BASE = DPRBASE + 0xD00
75 SCC3_BASE = DPRBASE + 0xE00
76 SCC4_BASE = DPRBASE + 0xF00
78 // offset from SCCx_BASE
79 // SCC_xBASE contain offsets from DPRBASE and must be divisible by 8
80 SCC_RBASE = 0 // 16-bit RxBD base address
81 SCC_TBASE = 2 // 16-bit TxBD base address
82 SCC_RFCR = 4 // 8-bit Rx function code
83 SCC_TFCR = 5 // 8-bit Tx function code
84 SCC_MRBLR = 6 // 16-bit maximum Rx buffer length
85 SCC_C_MASK = 0x34 // 32-bit CRC constant
86 SCC_C_PRES = 0x38 // 32-bit CRC preset
87 SCC_MFLR = 0x46 // 16-bit max Rx frame length (without flags)
89 REGBASE = DPRBASE + 0x1000
90 PICR = REGBASE + 0x026 // 16-bit periodic irq control
91 PITR = REGBASE + 0x02A // 16-bit periodic irq timing
92 OR1 = REGBASE + 0x064 // 32-bit RAM bank #1 options
93 CICR = REGBASE + 0x540 // 32(24)-bit CP interrupt config
94 CIMR = REGBASE + 0x548 // 32-bit CP interrupt mask
95 CISR = REGBASE + 0x54C // 32-bit CP interrupts in-service
96 PADIR = REGBASE + 0x550 // 16-bit PortA data direction bitmap
97 PAPAR = REGBASE + 0x552 // 16-bit PortA pin assignment bitmap
98 PAODR = REGBASE + 0x554 // 16-bit PortA open drain bitmap
99 PADAT = REGBASE + 0x556 // 16-bit PortA data register
101 PCDIR = REGBASE + 0x560 // 16-bit PortC data direction bitmap
102 PCPAR = REGBASE + 0x562 // 16-bit PortC pin assignment bitmap
103 PCSO = REGBASE + 0x564 // 16-bit PortC special options
104 PCDAT = REGBASE + 0x566 // 16-bit PortC data register
105 PCINT = REGBASE + 0x568 // 16-bit PortC interrupt control
106 CR = REGBASE + 0x5C0 // 16-bit Command register
108 SCC1_REGS = REGBASE + 0x600
109 SCC2_REGS = REGBASE + 0x620
110 SCC3_REGS = REGBASE + 0x640
111 SCC4_REGS = REGBASE + 0x660
112 SICR = REGBASE + 0x6EC // 32-bit SI clock route
114 // offset from SCCx_REGS
115 SCC_GSMR_L = 0x00 // 32 bits
116 SCC_GSMR_H = 0x04 // 32 bits
117 SCC_PSMR = 0x08 // 16 bits
118 SCC_TODR = 0x0C // 16 bits
119 SCC_DSR = 0x0E // 16 bits
120 SCC_SCCE = 0x10 // 16 bits
121 SCC_SCCM = 0x14 // 16 bits
122 SCC_SCCS = 0x17 // 8 bits
124 #if QUICC_MEMCPY_USES_PLX
125 .macro memcpy_from_pci src, dest, len // len must be < 8 MB
127 andl #0xFFFFFFFC, \len // always copy n * 4 bytes
128 movel \src, PLX_DMA_0_PCI
129 movel \dest, PLX_DMA_0_LOCAL
130 movel \len, PLX_DMA_0_LENGTH
131 movel #0x0103, PLX_DMA_CMD_STS // start channel 0 transfer
132 bsr memcpy_from_pci_run
135 .macro memcpy_to_pci src, dest, len
137 andl #0xFFFFFFFC, \len // always copy n * 4 bytes
138 movel \src, PLX_DMA_1_LOCAL
139 movel \dest, PLX_DMA_1_PCI
140 movel \len, PLX_DMA_1_LENGTH
141 movel #0x0301, PLX_DMA_CMD_STS // start channel 1 transfer
142 bsr memcpy_to_pci_run
147 .macro memcpy src, dest, len // len must be < 65536 bytes
148 movel %d7, -(%sp) // src and dest must be < 256 MB
149 movel \len, %d7 // bits 0 and 1
152 beq 99f // only 0 - 3 bytes
153 subl #1, \len // for dbf
154 98: movel (\src)+, (\dest)+
159 movew (\src)+, (\dest)+
162 moveb (\src)+, (\dest)+
167 .macro memcpy_from_pci src, dest, len
168 addl #VALUE_WINDOW, \src
169 memcpy \src, \dest, \len
172 .macro memcpy_to_pci src, dest, len
173 addl #VALUE_WINDOW, \dest
174 memcpy \src, \dest, \len
179 .macro wait_for_command
187 /****************************** card initialization *******************/
193 ch_status_addr: .long 0, 0, 0, 0
194 rx_descs_addr: .long 0
199 andl #0xF00007FF, %d0 // mask AMxx bits
200 orl #0xFFFF800 & ~(MAX_RAM_SIZE - 1), %d0 // update RAM bank size
204 addl #VALUE_WINDOW, rx_descs_addr // PCI addresses of shared data
205 clrl %d0 // D0 = 4 * port
206 init_1: tstl ch_status_addr(%d0)
208 addl #VALUE_WINDOW, ch_status_addr(%d0)
213 movel #pci9060_interrupt, PCI9060_VECTOR
214 movel #error_interrupt, ERROR_VECTOR
215 movel #port_interrupt_1, SCC1_VECTOR
216 movel #port_interrupt_2, SCC2_VECTOR
217 movel #port_interrupt_3, SCC3_VECTOR
218 movel #port_interrupt_4, SCC4_VECTOR
219 movel #timer_interrupt, TIMER_IRQ * 4
221 movel #0x78000000, CIMR // only SCCx IRQs from CPM
222 movew #(TIMER_IRQ_LEVEL << 8) + TIMER_IRQ, PICR // interrupt from PIT
223 movew #PITR_CONST, PITR
225 // SCC1=SCCa SCC2=SCCb SCC3=SCCc SCC4=SCCd prio=4 HP=-1 IRQ=64-79
226 movel #0xD41F40 + (CPM_IRQ_LEVEL << 13), CICR
227 movel #0x543, PLX_DMA_0_MODE // 32-bit, Ready, Burst, IRQ
228 movel #0x543, PLX_DMA_1_MODE
229 movel #0x0, PLX_DMA_0_DESC // from PCI to local
230 movel #0x8, PLX_DMA_1_DESC // from local to PCI
231 movel #0x101, PLX_DMA_CMD_STS // enable both DMA channels
232 // enable local IRQ, DMA, doorbells and PCI IRQ
233 orl #0x000F0300, PLX_INTERRUPT_CS
238 movel #1, PLX_MAILBOX_5 // non-zero value = init complete
242 movew #0xFFFF, PAPAR // all pins are clocks/data
243 clrw PADIR // first function
244 clrw PCSO // CD and CTS always active
247 /****************************** main loop *****************************/
249 main: movel channel_stats, %d7 // D7 = doorbell + irq status
254 // nothing to do - wait for next event
255 stop #0x2200 // supervisor + IRQ level 2
256 movew #0x2700, %sr // disable IRQs again
259 main_1: clrl %d0 // D0 = 4 * port
260 clrl %d6 // D6 = doorbell to host value
262 main_l: btstl #DOORBELL_TO_CARD_CLOSE_0, %d7
264 bclrl #DOORBELL_TO_CARD_OPEN_0, %d7 // in case both bits are set
267 btstl #DOORBELL_TO_CARD_OPEN_0, %d7
271 btstl #DOORBELL_TO_CARD_TX_0, %d7
275 btstl #TASK_SCC_0, %d7
281 lsrl #1, %d7 // port status for next port
282 addl #4, %d0 // D0 = 4 * next port
285 movel %d6, PLX_DOORBELL_FROM_CARD // signal the host
289 /****************************** open port *****************************/
291 open_port: // D0 = 4 * port, D6 = doorbell to host
292 movel ch_status_addr(%d0), %a0 // A0 = port status address
293 tstl STATUS_OPEN(%a0)
294 bne open_port_ret // port already open
295 movel #1, STATUS_OPEN(%a0) // confirm the port is open
302 movel SICR, %d1 // D1 = clock settings in SICR
303 andl clocking_mask(%d0), %d1
304 cmpl #CLOCK_TXFROMRX, STATUS_CLOCKING(%a0)
305 bne open_port_clock_ext
306 orl clocking_txfromrx(%d0), %d1
307 bra open_port_set_clock
310 orl clocking_ext(%d0), %d1
312 movel %d1, SICR // update clock settings in SICR
314 orw #STATUS_CABLE_DTR, csr_output(%d0) // DTR on
315 bsr check_csr // call with disabled timer interrupt
317 // Setup TX descriptors
318 movel first_buffer(%d0), %d1 // D1 = starting buffer address
319 movel tx_first_bd(%d0), %a1 // A1 = starting TX BD address
320 movel #TX_BUFFERS - 2, %d2 // D2 = TX_BUFFERS - 1 counter
321 movel #0x18000000, %d3 // D3 = initial TX BD flags: Int + Last
322 cmpl #PARITY_NONE, STATUS_PARITY(%a0)
323 beq open_port_tx_loop
324 bsetl #26, %d3 // TX BD flag: Transmit CRC
326 movel %d3, (%a1)+ // TX flags + length
327 movel %d1, (%a1)+ // buffer address
328 addl #BUFFER_LENGTH, %d1
329 dbfw %d2, open_port_tx_loop
331 bsetl #29, %d3 // TX BD flag: Wrap (last BD)
332 movel %d3, (%a1)+ // Final TX flags + length
333 movel %d1, (%a1)+ // buffer address
335 // Setup RX descriptors // A1 = starting RX BD address
336 movel #RX_BUFFERS - 2, %d2 // D2 = RX_BUFFERS - 1 counter
338 movel #0x90000000, (%a1)+ // RX flags + length
339 movel %d1, (%a1)+ // buffer address
340 addl #BUFFER_LENGTH, %d1
341 dbfw %d2, open_port_rx_loop
343 movel #0xB0000000, (%a1)+ // Final RX flags + length
344 movel %d1, (%a1)+ // buffer address
346 // Setup port parameters
347 movel scc_base_addr(%d0), %a1 // A1 = SCC_BASE address
348 movel scc_reg_addr(%d0), %a2 // A2 = SCC_REGS address
350 movel #0xFFFF, SCC_SCCE(%a2) // clear status bits
351 movel #0x0000, SCC_SCCM(%a2) // interrupt mask
353 movel tx_first_bd(%d0), %d1
354 movew %d1, SCC_TBASE(%a1) // D1 = offset of first TxBD
355 addl #TX_BUFFERS * 8, %d1
356 movew %d1, SCC_RBASE(%a1) // D1 = offset of first RxBD
357 moveb #0x8, SCC_RFCR(%a1) // Intel mode, 1000
358 moveb #0x8, SCC_TFCR(%a1)
361 cmpl #PARITY_CRC16_PR1_CCITT, STATUS_PARITY(%a0)
362 bne open_port_parity_1
363 clrw SCC_PSMR(%a2) // CRC16-CCITT
364 movel #0xF0B8, SCC_C_MASK(%a1)
365 movel #0xFFFF, SCC_C_PRES(%a1)
366 movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC
367 movew #2, parity_bytes(%d0)
371 cmpl #PARITY_CRC32_PR1_CCITT, STATUS_PARITY(%a0)
372 bne open_port_parity_2
373 movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT
374 movel #0xDEBB20E3, SCC_C_MASK(%a1)
375 movel #0xFFFFFFFF, SCC_C_PRES(%a1)
376 movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC
377 movew #4, parity_bytes(%d0)
381 cmpl #PARITY_CRC16_PR0_CCITT, STATUS_PARITY(%a0)
382 bne open_port_parity_3
383 clrw SCC_PSMR(%a2) // CRC16-CCITT preset 0
384 movel #0xF0B8, SCC_C_MASK(%a1)
386 movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC
387 movew #2, parity_bytes(%d0)
391 cmpl #PARITY_CRC32_PR0_CCITT, STATUS_PARITY(%a0)
392 bne open_port_parity_4
393 movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT preset 0
394 movel #0xDEBB20E3, SCC_C_MASK(%a1)
396 movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC
397 movew #4, parity_bytes(%d0)
401 clrw SCC_PSMR(%a2) // no parity
402 movel #0xF0B8, SCC_C_MASK(%a1)
403 movel #0xFFFF, SCC_C_PRES(%a1)
404 movew #HDLC_MAX_MRU, SCC_MFLR(%a1) // 0 bytes for CRC
405 clrw parity_bytes(%d0)
408 movel #0x00000003, SCC_GSMR_H(%a2) // RTSM
409 cmpl #ENCODING_NRZI, STATUS_ENCODING(%a0)
411 movel #0x10040900, SCC_GSMR_L(%a2) // NRZI: TCI Tend RECN+TENC=1
415 movel #0x10040000, SCC_GSMR_L(%a2) // NRZ: TCI Tend RECN+TENC=0
417 movew #BUFFER_LENGTH, SCC_MRBLR(%a1)
419 lsll #4, %d1 // D1 bits 7 and 6 = port
421 movew %d1, CR // Init SCC RX and TX params
425 movew #0x001F, SCC_SCCM(%a2) // TXE RXF BSY TXB RXB interrupts
426 orl #0x00000030, SCC_GSMR_L(%a2) // enable SCC
431 /****************************** close port ****************************/
433 close_port: // D0 = 4 * port, D6 = doorbell to host
434 movel scc_reg_addr(%d0), %a0 // A0 = SCC_REGS address
435 clrw SCC_SCCM(%a0) // no SCC interrupts
436 andl #0xFFFFFFCF, SCC_GSMR_L(%a0) // Disable ENT and ENR
438 andw #~STATUS_CABLE_DTR, csr_output(%d0) // DTR off
439 bsr check_csr // call with disabled timer interrupt
441 movel ch_status_addr(%d0), %d1
442 clrl STATUS_OPEN(%d1) // confirm the port is closed
446 /****************************** transmit packet ***********************/
447 // queue packets for transmission
448 tx: // D0 = 4 * port, D6 = doorbell to host
449 cmpl #TX_BUFFERS, tx_count(%d0)
450 beq tx_ret // all DB's = descs in use
452 movel tx_out(%d0), %d1
453 movel %d1, %d2 // D1 = D2 = tx_out BD# = desc#
454 mulul #DESC_LENGTH, %d2 // D2 = TX desc offset
455 addl ch_status_addr(%d0), %d2
456 addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address
457 cmpl #PACKET_FULL, (%d2) // desc status
461 movel 4(%d2), %a0 // PCI address
462 lsll #3, %d1 // BD is 8-bytes long
463 addl tx_first_bd(%d0), %d1 // D1 = current tx_out BD addr
465 movel 4(%d1), %a1 // A1 = dest address
466 movel 8(%d2), %d2 // D2 = length
467 movew %d2, 2(%d1) // length into BD
468 memcpy_from_pci %a0, %a1, %d2
469 bsetl #31, (%d1) // CP go ahead
471 // update tx_out and tx_count
472 movel tx_out(%d0), %d1
474 cmpl #TX_BUFFERS, %d1
477 tx_1: movel %d1, tx_out(%d0)
479 addl #1, tx_count(%d0)
485 /****************************** packet received ***********************/
487 // Service receive buffers // D0 = 4 * port, D6 = doorbell to host
488 rx: movel rx_in(%d0), %d1 // D1 = rx_in BD#
489 lsll #3, %d1 // BD is 8-bytes long
490 addl rx_first_bd(%d0), %d1 // D1 = current rx_in BD address
491 movew (%d1), %d2 // D2 = RX BD flags
493 bne rx_ret // BD still empty
498 tstw parity_bytes(%d0)
500 bclrl #2, %d2 // do not test for CRC errors
502 andw #0x0CBC, %d2 // mask status bits
503 cmpw #0x0C00, %d2 // correct frame
507 subw parity_bytes(%d0), %d3 // D3 = packet length
508 cmpw #HDLC_MAX_MRU, %d3
513 mulul #DESC_LENGTH, %d2
514 addl rx_descs_addr, %d2 // D2 = RX desc address
515 cmpl #PACKET_EMPTY, (%d2) // desc stat
519 movel 4(%d1), %a0 // A0 = source address
523 memcpy_to_pci %a0, %a1, %d3
525 movel packet_full(%d0), (%d2) // update desc stat
527 // update D6 and rx_out
528 bsetl #DOORBELL_FROM_CARD_RX, %d6 // signal host that RX completed
531 cmpl #RX_QUEUE_LENGTH, %d2
534 rx_1: movel %d2, rx_out
537 andw #0xF000, (%d1) // clear CM and error bits
538 bsetl #31, (%d1) // free BD
540 movel rx_in(%d0), %d1
542 cmpl #RX_BUFFERS, %d1
545 rx_2: movel %d1, rx_in(%d0)
549 movel ch_status_addr(%d0), %d2
550 addl #1, STATUS_RX_OVERRUNS(%d2)
554 movel ch_status_addr(%d0), %d2
555 addl #1, STATUS_RX_FRAME_ERRORS(%d2)
561 /****************************** packet transmitted ********************/
563 // Service transmit buffers // D0 = 4 * port, D6 = doorbell to host
564 tx_end: tstl tx_count(%d0)
565 beq tx_end_ret // TX buffers already empty
567 movel tx_in(%d0), %d1
568 movel %d1, %d2 // D1 = D2 = tx_in BD# = desc#
569 lsll #3, %d1 // BD is 8-bytes long
570 addl tx_first_bd(%d0), %d1 // D1 = current tx_in BD address
571 movew (%d1), %d3 // D3 = TX BD flags
573 bne tx_end_ret // BD still being transmitted
575 // update D6, tx_in and tx_count
576 orl bell_tx(%d0), %d6 // signal host that TX desc freed
577 subl #1, tx_count(%d0)
578 movel tx_in(%d0), %d1
580 cmpl #TX_BUFFERS, %d1
584 movel %d1, tx_in(%d0)
586 // free host's descriptor
587 mulul #DESC_LENGTH, %d2 // D2 = TX desc offset
588 addl ch_status_addr(%d0), %d2
589 addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address
592 movel #PACKET_SENT, (%d2)
596 movel #PACKET_UNDERRUN, (%d2)
602 /****************************** PLX PCI9060 DMA memcpy ****************/
604 #if QUICC_MEMCPY_USES_PLX
605 // called with interrupts disabled
610 movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly
611 btstl #4, %d0 // transfer done?
613 stop #0x2200 // enable PCI9060 interrupts
614 movew #0x2700, %sr // disable interrupts again
621 movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly
622 btstl #12, %d0 // transfer done?
624 stop #0x2200 // enable PCI9060 interrupts
625 movew #0x2700, %sr // disable interrupts again
639 /****************************** PLX PCI9060 interrupt *****************/
644 movel PLX_DOORBELL_TO_CARD, %d0
645 movel %d0, PLX_DOORBELL_TO_CARD // confirm all requests
646 orl %d0, channel_stats
648 movel #0x0909, PLX_DMA_CMD_STS // clear DMA ch #0 and #1 interrupts
653 /****************************** SCC interrupts ************************/
656 orl #0, SCC1_REGS + SCC_SCCE; // confirm SCC events
657 orl #1 << TASK_SCC_0, channel_stats
658 movel #0x40000000, CISR
662 orl #0, SCC2_REGS + SCC_SCCE; // confirm SCC events
663 orl #1 << TASK_SCC_1, channel_stats
664 movel #0x20000000, CISR
668 orl #0, SCC3_REGS + SCC_SCCE; // confirm SCC events
669 orl #1 << TASK_SCC_2, channel_stats
670 movel #0x10000000, CISR
674 orl #0, SCC4_REGS + SCC_SCCE; // confirm SCC events
675 orl #1 << TASK_SCC_3, channel_stats
676 movel #0x08000000, CISR
683 /****************************** cable and PM routine ******************/
684 // modified registers: none
692 clrl %d0 // D0 = 4 * port
693 movel #CSRA, %a0 // A0 = CSR address
696 movew (%a0), %d1 // D1 = CSR input bits
697 andl #0xE7, %d1 // PM and cable sense bits (no DCE bit)
698 cmpw #STATUS_CABLE_V35 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
704 cmpw #STATUS_CABLE_X21 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
710 cmpw #STATUS_CABLE_V24 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
716 cmpw #STATUS_CABLE_EIA530 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
717 bne check_csr_disable
722 movew #0x0008, %d1 // D1 = disable everything
723 movew #0x80E7, %d2 // D2 = input mask: ignore DSR
726 check_csr_valid: // D1 = mode and IRQ bits
727 movew csr_output(%d0), %d2
728 andw #0x3000, %d2 // D2 = requested LL and DTR bits
729 orw %d2, %d1 // D1 = all requested output bits
730 movew #0x80FF, %d2 // D2 = input mask: include DSR
733 cmpw old_csr_output(%d0), %d1
735 movew %d1, old_csr_output(%d0)
736 movew %d1, (%a0) // Write CSR output bits
740 andw dcd_mask(%d0), %d1
741 beq check_csr_dcd_on // DCD and CTS signals are negated
742 movew (%a0), %d1 // D1 = CSR input bits
743 andw #~STATUS_CABLE_DCD, %d1 // DCD off
744 bra check_csr_previous
747 movew (%a0), %d1 // D1 = CSR input bits
748 orw #STATUS_CABLE_DCD, %d1 // DCD on
750 andw %d2, %d1 // input mask
751 movel ch_status_addr(%d0), %a1
752 cmpl STATUS_CABLE(%a1), %d1 // check for change
754 movel %d1, STATUS_CABLE(%a1) // update status
755 movel bell_cable(%d0), PLX_DOORBELL_FROM_CARD // signal the host
758 addl #2, %a0 // next CSR register
759 addl #4, %d0 // D0 = 4 * next port
771 /****************************** timer interrupt ***********************/
778 /****************************** RAM sizing and test *******************/
781 movel #0x12345678, %d1 // D1 = test value
782 movel %d1, (128 * 1024 - 4)
783 movel #128 * 1024, %d0 // D0 = RAM size tested
785 cmpl #MAX_RAM_SIZE, %d0
786 beq ram_test_size_found
788 addl #128 * 1024 - 4, %a0
790 beq ram_test_size_check
796 eorl #0xFFFFFFFF, %d1
797 movel %d1, (128 * 1024 - 4)
799 bne ram_test_next_size
801 ram_test_size_found: // D0 = RAM size
802 movel %d0, %a0 // A0 = fill ptr
803 subl #firmware_end + 4, %d0
805 movel %d0, %d1 // D1 = DBf counter
808 dbfw %d1, ram_test_fill
810 cmpl #0xFFFFFFFF, %d1
813 ram_test_loop: // D0 = DBf counter
815 dbnew %d0, ram_test_loop
816 bne ram_test_found_bad
818 cmpl #0xFFFFFFFF, %d0
825 movel %a0, PLX_MAILBOX_5
830 /****************************** constants *****************************/
833 .long SCC1_REGS, SCC2_REGS, SCC3_REGS, SCC4_REGS
835 .long SCC1_BASE, SCC2_BASE, SCC3_BASE, SCC4_BASE
839 .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8
840 .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 2
841 .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 3
844 .long DPRBASE + TX_BUFFERS * 8
845 .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8
846 .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 2
847 .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 3
851 .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH
852 .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 2
853 .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 3
856 .long 1 << DOORBELL_FROM_CARD_TX_0, 1 << DOORBELL_FROM_CARD_TX_1
857 .long 1 << DOORBELL_FROM_CARD_TX_2, 1 << DOORBELL_FROM_CARD_TX_3
860 .long 1 << DOORBELL_FROM_CARD_CABLE_0, 1 << DOORBELL_FROM_CARD_CABLE_1
861 .long 1 << DOORBELL_FROM_CARD_CABLE_2, 1 << DOORBELL_FROM_CARD_CABLE_3
864 .long PACKET_FULL, PACKET_FULL + 1, PACKET_FULL + 2, PACKET_FULL + 3
867 .long 0x0000002C, 0x00003E00, 0x002C0000, 0x3E000000
869 .long 0x0000002D, 0x00003F00, 0x002D0000, 0x3F000000
871 .long 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
873 .word 0x020, 0, 0x080, 0, 0x200, 0, 0x800
875 .ascii "wanXL firmware\n"
876 .asciz "Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl>\n"
879 /****************************** variables *****************************/
882 channel_stats: .long 0
884 tx_in: .long 0, 0, 0, 0 // transmitted
885 tx_out: .long 0, 0, 0, 0 // received from host for transmission
886 tx_count: .long 0, 0, 0, 0 // currently in transmit queue
888 rx_in: .long 0, 0, 0, 0 // received from port
889 rx_out: .long 0 // transmitted to host
890 parity_bytes: .word 0, 0, 0, 0, 0, 0, 0 // only 4 words are used
893 old_csr_output: .word 0, 0, 0, 0, 0, 0, 0
895 firmware_end: // must be dword-aligned