0001
0002 .psize 0
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <linux/hdlc.h>
0036 #include <linux/hdlc/ioctl.h>
0037 #include "wanxl.h"
0038
0039
0040
0041 MAX_RAM_SIZE = 16 * 1024 * 1024 // max RAM supported by hardware
0042
0043 PCI9060_VECTOR = 0x0000006C
0044 CPM_IRQ_BASE = 0x40
0045 ERROR_VECTOR = CPM_IRQ_BASE * 4
0046 SCC1_VECTOR = (CPM_IRQ_BASE + 0x1E) * 4
0047 SCC2_VECTOR = (CPM_IRQ_BASE + 0x1D) * 4
0048 SCC3_VECTOR = (CPM_IRQ_BASE + 0x1C) * 4
0049 SCC4_VECTOR = (CPM_IRQ_BASE + 0x1B) * 4
0050 CPM_IRQ_LEVEL = 4
0051 TIMER_IRQ = 128
0052 TIMER_IRQ_LEVEL = 4
0053 PITR_CONST = 0x100 + 16 // 1 Hz timer
0054
0055 MBAR = 0x0003FF00
0056
0057 VALUE_WINDOW = 0x40000000
0058 ORDER_WINDOW = 0xC0000000
0059
0060 PLX = 0xFFF90000
0061
0062 CSRA = 0xFFFB0000
0063 CSRB = 0xFFFB0002
0064 CSRC = 0xFFFB0004
0065 CSRD = 0xFFFB0006
0066 STATUS_CABLE_LL = 0x2000
0067 STATUS_CABLE_DTR = 0x1000
0068
0069 DPRBASE = 0xFFFC0000
0070
0071 SCC1_BASE = DPRBASE + 0xC00
0072 MISC_BASE = DPRBASE + 0xCB0
0073 SCC2_BASE = DPRBASE + 0xD00
0074 SCC3_BASE = DPRBASE + 0xE00
0075 SCC4_BASE = DPRBASE + 0xF00
0076
0077 // offset from SCCx_BASE
0078 // SCC_xBASE contain offsets from DPRBASE and must be divisible by 8
0079 SCC_RBASE = 0 // 16-bit RxBD base address
0080 SCC_TBASE = 2 // 16-bit TxBD base address
0081 SCC_RFCR = 4 // 8-bit Rx function code
0082 SCC_TFCR = 5 // 8-bit Tx function code
0083 SCC_MRBLR = 6 // 16-bit maximum Rx buffer length
0084 SCC_C_MASK = 0x34 // 32-bit CRC constant
0085 SCC_C_PRES = 0x38 // 32-bit CRC preset
0086 SCC_MFLR = 0x46 // 16-bit max Rx frame length (without flags)
0087
0088 REGBASE = DPRBASE + 0x1000
0089 PICR = REGBASE + 0x026 // 16-bit periodic irq control
0090 PITR = REGBASE + 0x02A // 16-bit periodic irq timing
0091 OR1 = REGBASE + 0x064 // 32-bit RAM bank #1 options
0092 CICR = REGBASE + 0x540 // 32(24)-bit CP interrupt config
0093 CIMR = REGBASE + 0x548 // 32-bit CP interrupt mask
0094 CISR = REGBASE + 0x54C // 32-bit CP interrupts in-service
0095 PADIR = REGBASE + 0x550 // 16-bit PortA data direction bitmap
0096 PAPAR = REGBASE + 0x552 // 16-bit PortA pin assignment bitmap
0097 PAODR = REGBASE + 0x554 // 16-bit PortA open drain bitmap
0098 PADAT = REGBASE + 0x556 // 16-bit PortA data register
0099
0100 PCDIR = REGBASE + 0x560 // 16-bit PortC data direction bitmap
0101 PCPAR = REGBASE + 0x562 // 16-bit PortC pin assignment bitmap
0102 PCSO = REGBASE + 0x564 // 16-bit PortC special options
0103 PCDAT = REGBASE + 0x566 // 16-bit PortC data register
0104 PCINT = REGBASE + 0x568 // 16-bit PortC interrupt control
0105 CR = REGBASE + 0x5C0 // 16-bit Command register
0106
0107 SCC1_REGS = REGBASE + 0x600
0108 SCC2_REGS = REGBASE + 0x620
0109 SCC3_REGS = REGBASE + 0x640
0110 SCC4_REGS = REGBASE + 0x660
0111 SICR = REGBASE + 0x6EC // 32-bit SI clock route
0112
0113 // offset from SCCx_REGS
0114 SCC_GSMR_L = 0x00 // 32 bits
0115 SCC_GSMR_H = 0x04 // 32 bits
0116 SCC_PSMR = 0x08 // 16 bits
0117 SCC_TODR = 0x0C // 16 bits
0118 SCC_DSR = 0x0E // 16 bits
0119 SCC_SCCE = 0x10 // 16 bits
0120 SCC_SCCM = 0x14 // 16 bits
0121 SCC_SCCS = 0x17 // 8 bits
0122
0123 #if QUICC_MEMCPY_USES_PLX
0124 .macro memcpy_from_pci src, dest, len // len must be < 8 MB
0125 addl #3, \len
0126 andl #0xFFFFFFFC, \len // always copy n * 4 bytes
0127 movel \src, PLX_DMA_0_PCI
0128 movel \dest, PLX_DMA_0_LOCAL
0129 movel \len, PLX_DMA_0_LENGTH
0130 movel #0x0103, PLX_DMA_CMD_STS // start channel 0 transfer
0131 bsr memcpy_from_pci_run
0132 .endm
0133
0134 .macro memcpy_to_pci src, dest, len
0135 addl #3, \len
0136 andl #0xFFFFFFFC, \len // always copy n * 4 bytes
0137 movel \src, PLX_DMA_1_LOCAL
0138 movel \dest, PLX_DMA_1_PCI
0139 movel \len, PLX_DMA_1_LENGTH
0140 movel #0x0301, PLX_DMA_CMD_STS // start channel 1 transfer
0141 bsr memcpy_to_pci_run
0142 .endm
0143
0144 #else
0145
0146 .macro memcpy src, dest, len // len must be < 65536 bytes
0147 movel %d7, -(%sp) // src and dest must be < 256 MB
0148 movel \len, %d7 // bits 0 and 1
0149 lsrl #2, \len
0150 andl \len, \len
0151 beq 99f // only 0 - 3 bytes
0152 subl #1, \len // for dbf
0153 98: movel (\src)+, (\dest)+
0154 dbfw \len, 98b
0155 99: movel %d7, \len
0156 btstl #1, \len
0157 beq 99f
0158 movew (\src)+, (\dest)+
0159 99: btstl #0, \len
0160 beq 99f
0161 moveb (\src)+, (\dest)+
0162 99:
0163 movel (%sp)+, %d7
0164 .endm
0165
0166 .macro memcpy_from_pci src, dest, len
0167 addl #VALUE_WINDOW, \src
0168 memcpy \src, \dest, \len
0169 .endm
0170
0171 .macro memcpy_to_pci src, dest, len
0172 addl #VALUE_WINDOW, \dest
0173 memcpy \src, \dest, \len
0174 .endm
0175 #endif
0176
0177
0178 .macro wait_for_command
0179 99: btstl #0, CR
0180 bne 99b
0181 .endm
0182
0183
0184
0185
0186
0187 .text
0188 .global _start
0189 _start: bra init
0190
0191 .org _start + 4
0192 ch_status_addr: .long 0, 0, 0, 0
0193 rx_descs_addr: .long 0
0194
0195 init:
0196 #if DETECT_RAM
0197 movel OR1, %d0
0198 andl #0xF00007FF, %d0 // mask AMxx bits
0199 orl #0xFFFF800 & ~(MAX_RAM_SIZE - 1), %d0 // update RAM bank size
0200 movel %d0, OR1
0201 #endif
0202
0203 addl #VALUE_WINDOW, rx_descs_addr // PCI addresses of shared data
0204 clrl %d0 // D0 = 4 * port
0205 init_1: tstl ch_status_addr(%d0)
0206 beq init_2
0207 addl #VALUE_WINDOW, ch_status_addr(%d0)
0208 init_2: addl #4, %d0
0209 cmpl #4 * 4, %d0
0210 bne init_1
0211
0212 movel #pci9060_interrupt, PCI9060_VECTOR
0213 movel #error_interrupt, ERROR_VECTOR
0214 movel #port_interrupt_1, SCC1_VECTOR
0215 movel #port_interrupt_2, SCC2_VECTOR
0216 movel #port_interrupt_3, SCC3_VECTOR
0217 movel #port_interrupt_4, SCC4_VECTOR
0218 movel #timer_interrupt, TIMER_IRQ * 4
0219
0220 movel #0x78000000, CIMR // only SCCx IRQs from CPM
0221 movew #(TIMER_IRQ_LEVEL << 8) + TIMER_IRQ, PICR // interrupt from PIT
0222 movew #PITR_CONST, PITR
0223
0224 // SCC1=SCCa SCC2=SCCb SCC3=SCCc SCC4=SCCd prio=4 HP=-1 IRQ=64-79
0225 movel #0xD41F40 + (CPM_IRQ_LEVEL << 13), CICR
0226 movel #0x543, PLX_DMA_0_MODE // 32-bit, Ready, Burst, IRQ
0227 movel #0x543, PLX_DMA_1_MODE
0228 movel #0x0, PLX_DMA_0_DESC // from PCI to local
0229 movel #0x8, PLX_DMA_1_DESC // from local to PCI
0230 movel #0x101, PLX_DMA_CMD_STS // enable both DMA channels
0231 // enable local IRQ, DMA, doorbells and PCI IRQ
0232 orl #0x000F0300, PLX_INTERRUPT_CS
0233
0234 #if DETECT_RAM
0235 bsr ram_test
0236 #else
0237 movel #1, PLX_MAILBOX_5 // non-zero value = init complete
0238 #endif
0239 bsr check_csr
0240
0241 movew #0xFFFF, PAPAR // all pins are clocks/data
0242 clrw PADIR // first function
0243 clrw PCSO // CD and CTS always active
0244
0245
0246
0247
0248 main: movel channel_stats, %d7 // D7 = doorbell + irq status
0249 clrl channel_stats
0250
0251 tstl %d7
0252 bne main_1
0253 // nothing to do - wait for next event
0254 stop #0x2200 // supervisor + IRQ level 2
0255 movew #0x2700, %sr // disable IRQs again
0256 bra main
0257
0258 main_1: clrl %d0 // D0 = 4 * port
0259 clrl %d6 // D6 = doorbell to host value
0260
0261 main_l: btstl #DOORBELL_TO_CARD_CLOSE_0, %d7
0262 beq main_op
0263 bclrl #DOORBELL_TO_CARD_OPEN_0, %d7 // in case both bits are set
0264 bsr close_port
0265 main_op:
0266 btstl #DOORBELL_TO_CARD_OPEN_0, %d7
0267 beq main_cl
0268 bsr open_port
0269 main_cl:
0270 btstl #DOORBELL_TO_CARD_TX_0, %d7
0271 beq main_txend
0272 bsr tx
0273 main_txend:
0274 btstl #TASK_SCC_0, %d7
0275 beq main_next
0276 bsr tx_end
0277 bsr rx
0278
0279 main_next:
0280 lsrl #1, %d7 // port status for next port
0281 addl #4, %d0 // D0 = 4 * next port
0282 cmpl #4 * 4, %d0
0283 bne main_l
0284 movel %d6, PLX_DOORBELL_FROM_CARD // signal the host
0285 bra main
0286
0287
0288
0289
0290 open_port: // D0 = 4 * port, D6 = doorbell to host
0291 movel ch_status_addr(%d0), %a0 // A0 = port status address
0292 tstl STATUS_OPEN(%a0)
0293 bne open_port_ret // port already open
0294 movel #1, STATUS_OPEN(%a0) // confirm the port is open
0295 // setup BDs
0296 clrl tx_in(%d0)
0297 clrl tx_out(%d0)
0298 clrl tx_count(%d0)
0299 clrl rx_in(%d0)
0300
0301 movel SICR, %d1 // D1 = clock settings in SICR
0302 andl clocking_mask(%d0), %d1
0303 cmpl #CLOCK_TXFROMRX, STATUS_CLOCKING(%a0)
0304 bne open_port_clock_ext
0305 orl clocking_txfromrx(%d0), %d1
0306 bra open_port_set_clock
0307
0308 open_port_clock_ext:
0309 orl clocking_ext(%d0), %d1
0310 open_port_set_clock:
0311 movel %d1, SICR // update clock settings in SICR
0312
0313 orw #STATUS_CABLE_DTR, csr_output(%d0) // DTR on
0314 bsr check_csr // call with disabled timer interrupt
0315
0316 // Setup TX descriptors
0317 movel first_buffer(%d0), %d1 // D1 = starting buffer address
0318 movel tx_first_bd(%d0), %a1 // A1 = starting TX BD address
0319 movel #TX_BUFFERS - 2, %d2 // D2 = TX_BUFFERS - 1 counter
0320 movel #0x18000000, %d3 // D3 = initial TX BD flags: Int + Last
0321 cmpl #PARITY_NONE, STATUS_PARITY(%a0)
0322 beq open_port_tx_loop
0323 bsetl #26, %d3 // TX BD flag: Transmit CRC
0324 open_port_tx_loop:
0325 movel %d3, (%a1)+ // TX flags + length
0326 movel %d1, (%a1)+ // buffer address
0327 addl #BUFFER_LENGTH, %d1
0328 dbfw %d2, open_port_tx_loop
0329
0330 bsetl #29, %d3 // TX BD flag: Wrap (last BD)
0331 movel %d3, (%a1)+ // Final TX flags + length
0332 movel %d1, (%a1)+ // buffer address
0333
0334 // Setup RX descriptors // A1 = starting RX BD address
0335 movel #RX_BUFFERS - 2, %d2 // D2 = RX_BUFFERS - 1 counter
0336 open_port_rx_loop:
0337 movel #0x90000000, (%a1)+ // RX flags + length
0338 movel %d1, (%a1)+ // buffer address
0339 addl #BUFFER_LENGTH, %d1
0340 dbfw %d2, open_port_rx_loop
0341
0342 movel #0xB0000000, (%a1)+ // Final RX flags + length
0343 movel %d1, (%a1)+ // buffer address
0344
0345 // Setup port parameters
0346 movel scc_base_addr(%d0), %a1 // A1 = SCC_BASE address
0347 movel scc_reg_addr(%d0), %a2 // A2 = SCC_REGS address
0348
0349 movel #0xFFFF, SCC_SCCE(%a2) // clear status bits
0350 movel #0x0000, SCC_SCCM(%a2) // interrupt mask
0351
0352 movel tx_first_bd(%d0), %d1
0353 movew %d1, SCC_TBASE(%a1) // D1 = offset of first TxBD
0354 addl #TX_BUFFERS * 8, %d1
0355 movew %d1, SCC_RBASE(%a1) // D1 = offset of first RxBD
0356 moveb #0x8, SCC_RFCR(%a1) // Intel mode, 1000
0357 moveb #0x8, SCC_TFCR(%a1)
0358
0359 // Parity settings
0360 cmpl #PARITY_CRC16_PR1_CCITT, STATUS_PARITY(%a0)
0361 bne open_port_parity_1
0362 clrw SCC_PSMR(%a2) // CRC16-CCITT
0363 movel #0xF0B8, SCC_C_MASK(%a1)
0364 movel #0xFFFF, SCC_C_PRES(%a1)
0365 movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC
0366 movew #2, parity_bytes(%d0)
0367 bra open_port_2
0368
0369 open_port_parity_1:
0370 cmpl #PARITY_CRC32_PR1_CCITT, STATUS_PARITY(%a0)
0371 bne open_port_parity_2
0372 movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT
0373 movel #0xDEBB20E3, SCC_C_MASK(%a1)
0374 movel #0xFFFFFFFF, SCC_C_PRES(%a1)
0375 movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC
0376 movew #4, parity_bytes(%d0)
0377 bra open_port_2
0378
0379 open_port_parity_2:
0380 cmpl #PARITY_CRC16_PR0_CCITT, STATUS_PARITY(%a0)
0381 bne open_port_parity_3
0382 clrw SCC_PSMR(%a2) // CRC16-CCITT preset 0
0383 movel #0xF0B8, SCC_C_MASK(%a1)
0384 clrl SCC_C_PRES(%a1)
0385 movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC
0386 movew #2, parity_bytes(%d0)
0387 bra open_port_2
0388
0389 open_port_parity_3:
0390 cmpl #PARITY_CRC32_PR0_CCITT, STATUS_PARITY(%a0)
0391 bne open_port_parity_4
0392 movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT preset 0
0393 movel #0xDEBB20E3, SCC_C_MASK(%a1)
0394 clrl SCC_C_PRES(%a1)
0395 movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC
0396 movew #4, parity_bytes(%d0)
0397 bra open_port_2
0398
0399 open_port_parity_4:
0400 clrw SCC_PSMR(%a2) // no parity
0401 movel #0xF0B8, SCC_C_MASK(%a1)
0402 movel #0xFFFF, SCC_C_PRES(%a1)
0403 movew #HDLC_MAX_MRU, SCC_MFLR(%a1) // 0 bytes for CRC
0404 clrw parity_bytes(%d0)
0405
0406 open_port_2:
0407 movel #0x00000003, SCC_GSMR_H(%a2) // RTSM
0408 cmpl #ENCODING_NRZI, STATUS_ENCODING(%a0)
0409 bne open_port_nrz
0410 movel #0x10040900, SCC_GSMR_L(%a2) // NRZI: TCI Tend RECN+TENC=1
0411 bra open_port_3
0412
0413 open_port_nrz:
0414 movel #0x10040000, SCC_GSMR_L(%a2) // NRZ: TCI Tend RECN+TENC=0
0415 open_port_3:
0416 movew #BUFFER_LENGTH, SCC_MRBLR(%a1)
0417 movel %d0, %d1
0418 lsll #4, %d1 // D1 bits 7 and 6 = port
0419 orl #1, %d1
0420 movew %d1, CR // Init SCC RX and TX params
0421 wait_for_command
0422
0423 // TCI Tend ENR ENT
0424 movew #0x001F, SCC_SCCM(%a2) // TXE RXF BSY TXB RXB interrupts
0425 orl #0x00000030, SCC_GSMR_L(%a2) // enable SCC
0426 open_port_ret:
0427 rts
0428
0429
0430
0431
0432 close_port: // D0 = 4 * port, D6 = doorbell to host
0433 movel scc_reg_addr(%d0), %a0 // A0 = SCC_REGS address
0434 clrw SCC_SCCM(%a0) // no SCC interrupts
0435 andl #0xFFFFFFCF, SCC_GSMR_L(%a0) // Disable ENT and ENR
0436
0437 andw #~STATUS_CABLE_DTR, csr_output(%d0) // DTR off
0438 bsr check_csr // call with disabled timer interrupt
0439
0440 movel ch_status_addr(%d0), %d1
0441 clrl STATUS_OPEN(%d1) // confirm the port is closed
0442 rts
0443
0444
0445
0446 // queue packets for transmission
0447 tx: // D0 = 4 * port, D6 = doorbell to host
0448 cmpl #TX_BUFFERS, tx_count(%d0)
0449 beq tx_ret // all DB's = descs in use
0450
0451 movel tx_out(%d0), %d1
0452 movel %d1, %d2 // D1 = D2 = tx_out BD# = desc#
0453 mulul #DESC_LENGTH, %d2 // D2 = TX desc offset
0454 addl ch_status_addr(%d0), %d2
0455 addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address
0456 cmpl #PACKET_FULL, (%d2) // desc status
0457 bne tx_ret
0458
0459 // queue it
0460 movel 4(%d2), %a0 // PCI address
0461 lsll #3, %d1 // BD is 8-bytes long
0462 addl tx_first_bd(%d0), %d1 // D1 = current tx_out BD addr
0463
0464 movel 4(%d1), %a1 // A1 = dest address
0465 movel 8(%d2), %d2 // D2 = length
0466 movew %d2, 2(%d1) // length into BD
0467 memcpy_from_pci %a0, %a1, %d2
0468 bsetl #31, (%d1) // CP go ahead
0469
0470 // update tx_out and tx_count
0471 movel tx_out(%d0), %d1
0472 addl #1, %d1
0473 cmpl #TX_BUFFERS, %d1
0474 bne tx_1
0475 clrl %d1
0476 tx_1: movel %d1, tx_out(%d0)
0477
0478 addl #1, tx_count(%d0)
0479 bra tx
0480
0481 tx_ret: rts
0482
0483
0484
0485
0486 // Service receive buffers // D0 = 4 * port, D6 = doorbell to host
0487 rx: movel rx_in(%d0), %d1 // D1 = rx_in BD#
0488 lsll #3, %d1 // BD is 8-bytes long
0489 addl rx_first_bd(%d0), %d1 // D1 = current rx_in BD address
0490 movew (%d1), %d2 // D2 = RX BD flags
0491 btstl #15, %d2
0492 bne rx_ret // BD still empty
0493
0494 btstl #1, %d2
0495 bne rx_overrun
0496
0497 tstw parity_bytes(%d0)
0498 bne rx_parity
0499 bclrl #2, %d2 // do not test for CRC errors
0500 rx_parity:
0501 andw #0x0CBC, %d2 // mask status bits
0502 cmpw #0x0C00, %d2 // correct frame
0503 bne rx_bad_frame
0504 clrl %d3
0505 movew 2(%d1), %d3
0506 subw parity_bytes(%d0), %d3 // D3 = packet length
0507 cmpw #HDLC_MAX_MRU, %d3
0508 bgt rx_bad_frame
0509
0510 rx_good_frame:
0511 movel rx_out, %d2
0512 mulul #DESC_LENGTH, %d2
0513 addl rx_descs_addr, %d2 // D2 = RX desc address
0514 cmpl #PACKET_EMPTY, (%d2) // desc stat
0515 bne rx_overrun
0516
0517 movel %d3, 8(%d2)
0518 movel 4(%d1), %a0 // A0 = source address
0519 movel 4(%d2), %a1
0520 tstl %a1
0521 beq rx_ignore_data
0522 memcpy_to_pci %a0, %a1, %d3
0523 rx_ignore_data:
0524 movel packet_full(%d0), (%d2) // update desc stat
0525
0526 // update D6 and rx_out
0527 bsetl #DOORBELL_FROM_CARD_RX, %d6 // signal host that RX completed
0528 movel rx_out, %d2
0529 addl #1, %d2
0530 cmpl #RX_QUEUE_LENGTH, %d2
0531 bne rx_1
0532 clrl %d2
0533 rx_1: movel %d2, rx_out
0534
0535 rx_free_bd:
0536 andw #0xF000, (%d1) // clear CM and error bits
0537 bsetl #31, (%d1) // free BD
0538 // update rx_in
0539 movel rx_in(%d0), %d1
0540 addl #1, %d1
0541 cmpl #RX_BUFFERS, %d1
0542 bne rx_2
0543 clrl %d1
0544 rx_2: movel %d1, rx_in(%d0)
0545 bra rx
0546
0547 rx_overrun:
0548 movel ch_status_addr(%d0), %d2
0549 addl #1, STATUS_RX_OVERRUNS(%d2)
0550 bra rx_free_bd
0551
0552 rx_bad_frame:
0553 movel ch_status_addr(%d0), %d2
0554 addl #1, STATUS_RX_FRAME_ERRORS(%d2)
0555 bra rx_free_bd
0556
0557 rx_ret: rts
0558
0559
0560
0561
0562 // Service transmit buffers // D0 = 4 * port, D6 = doorbell to host
0563 tx_end: tstl tx_count(%d0)
0564 beq tx_end_ret // TX buffers already empty
0565
0566 movel tx_in(%d0), %d1
0567 movel %d1, %d2 // D1 = D2 = tx_in BD# = desc#
0568 lsll #3, %d1 // BD is 8-bytes long
0569 addl tx_first_bd(%d0), %d1 // D1 = current tx_in BD address
0570 movew (%d1), %d3 // D3 = TX BD flags
0571 btstl #15, %d3
0572 bne tx_end_ret // BD still being transmitted
0573
0574 // update D6, tx_in and tx_count
0575 orl bell_tx(%d0), %d6 // signal host that TX desc freed
0576 subl #1, tx_count(%d0)
0577 movel tx_in(%d0), %d1
0578 addl #1, %d1
0579 cmpl #TX_BUFFERS, %d1
0580 bne tx_end_1
0581 clrl %d1
0582 tx_end_1:
0583 movel %d1, tx_in(%d0)
0584
0585 // free host's descriptor
0586 mulul #DESC_LENGTH, %d2 // D2 = TX desc offset
0587 addl ch_status_addr(%d0), %d2
0588 addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address
0589 btstl #1, %d3
0590 bne tx_end_underrun
0591 movel #PACKET_SENT, (%d2)
0592 bra tx_end
0593
0594 tx_end_underrun:
0595 movel #PACKET_UNDERRUN, (%d2)
0596 bra tx_end
0597
0598 tx_end_ret: rts
0599
0600
0601
0602
0603 #if QUICC_MEMCPY_USES_PLX
0604 // called with interrupts disabled
0605 memcpy_from_pci_run:
0606 movel %d0, -(%sp)
0607 movew %sr, -(%sp)
0608 memcpy_1:
0609 movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly
0610 btstl #4, %d0 // transfer done?
0611 bne memcpy_end
0612 stop #0x2200 // enable PCI9060 interrupts
0613 movew #0x2700, %sr // disable interrupts again
0614 bra memcpy_1
0615
0616 memcpy_to_pci_run:
0617 movel %d0, -(%sp)
0618 movew %sr, -(%sp)
0619 memcpy_2:
0620 movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly
0621 btstl #12, %d0 // transfer done?
0622 bne memcpy_end
0623 stop #0x2200 // enable PCI9060 interrupts
0624 movew #0x2700, %sr // disable interrupts again
0625 bra memcpy_2
0626
0627 memcpy_end:
0628 movew (%sp)+, %sr
0629 movel (%sp)+, %d0
0630 rts
0631 #endif
0632
0633
0634
0635
0636
0637
0638
0639
0640 pci9060_interrupt:
0641 movel %d0, -(%sp)
0642
0643 movel PLX_DOORBELL_TO_CARD, %d0
0644 movel %d0, PLX_DOORBELL_TO_CARD // confirm all requests
0645 orl %d0, channel_stats
0646
0647 movel #0x0909, PLX_DMA_CMD_STS // clear DMA ch #0 and #1 interrupts
0648
0649 movel (%sp)+, %d0
0650 rte
0651
0652
0653
0654 port_interrupt_1:
0655 orl #0, SCC1_REGS + SCC_SCCE; // confirm SCC events
0656 orl #1 << TASK_SCC_0, channel_stats
0657 movel #0x40000000, CISR
0658 rte
0659
0660 port_interrupt_2:
0661 orl #0, SCC2_REGS + SCC_SCCE; // confirm SCC events
0662 orl #1 << TASK_SCC_1, channel_stats
0663 movel #0x20000000, CISR
0664 rte
0665
0666 port_interrupt_3:
0667 orl #0, SCC3_REGS + SCC_SCCE; // confirm SCC events
0668 orl #1 << TASK_SCC_2, channel_stats
0669 movel #0x10000000, CISR
0670 rte
0671
0672 port_interrupt_4:
0673 orl #0, SCC4_REGS + SCC_SCCE; // confirm SCC events
0674 orl #1 << TASK_SCC_3, channel_stats
0675 movel #0x08000000, CISR
0676 rte
0677
0678 error_interrupt:
0679 rte
0680
0681
0682
0683 // modified registers: none
0684 check_csr:
0685 movel %d0, -(%sp)
0686 movel %d1, -(%sp)
0687 movel %d2, -(%sp)
0688 movel %a0, -(%sp)
0689 movel %a1, -(%sp)
0690
0691 clrl %d0 // D0 = 4 * port
0692 movel #CSRA, %a0 // A0 = CSR address
0693
0694 check_csr_loop:
0695 movew (%a0), %d1 // D1 = CSR input bits
0696 andl #0xE7, %d1 // PM and cable sense bits (no DCE bit)
0697 cmpw #STATUS_CABLE_V35 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
0698 bne check_csr_1
0699 movew #0x0E08, %d1
0700 bra check_csr_valid
0701
0702 check_csr_1:
0703 cmpw #STATUS_CABLE_X21 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
0704 bne check_csr_2
0705 movew #0x0408, %d1
0706 bra check_csr_valid
0707
0708 check_csr_2:
0709 cmpw #STATUS_CABLE_V24 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
0710 bne check_csr_3
0711 movew #0x0208, %d1
0712 bra check_csr_valid
0713
0714 check_csr_3:
0715 cmpw #STATUS_CABLE_EIA530 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1
0716 bne check_csr_disable
0717 movew #0x0D08, %d1
0718 bra check_csr_valid
0719
0720 check_csr_disable:
0721 movew #0x0008, %d1 // D1 = disable everything
0722 movew #0x80E7, %d2 // D2 = input mask: ignore DSR
0723 bra check_csr_write
0724
0725 check_csr_valid: // D1 = mode and IRQ bits
0726 movew csr_output(%d0), %d2
0727 andw #0x3000, %d2 // D2 = requested LL and DTR bits
0728 orw %d2, %d1 // D1 = all requested output bits
0729 movew #0x80FF, %d2 // D2 = input mask: include DSR
0730
0731 check_csr_write:
0732 cmpw old_csr_output(%d0), %d1
0733 beq check_csr_input
0734 movew %d1, old_csr_output(%d0)
0735 movew %d1, (%a0) // Write CSR output bits
0736
0737 check_csr_input:
0738 movew (PCDAT), %d1
0739 andw dcd_mask(%d0), %d1
0740 beq check_csr_dcd_on // DCD and CTS signals are negated
0741 movew (%a0), %d1 // D1 = CSR input bits
0742 andw #~STATUS_CABLE_DCD, %d1 // DCD off
0743 bra check_csr_previous
0744
0745 check_csr_dcd_on:
0746 movew (%a0), %d1 // D1 = CSR input bits
0747 orw #STATUS_CABLE_DCD, %d1 // DCD on
0748 check_csr_previous:
0749 andw %d2, %d1 // input mask
0750 movel ch_status_addr(%d0), %a1
0751 cmpl STATUS_CABLE(%a1), %d1 // check for change
0752 beq check_csr_next
0753 movel %d1, STATUS_CABLE(%a1) // update status
0754 movel bell_cable(%d0), PLX_DOORBELL_FROM_CARD // signal the host
0755
0756 check_csr_next:
0757 addl #2, %a0 // next CSR register
0758 addl #4, %d0 // D0 = 4 * next port
0759 cmpl #4 * 4, %d0
0760 bne check_csr_loop
0761
0762 movel (%sp)+, %a1
0763 movel (%sp)+, %a0
0764 movel (%sp)+, %d2
0765 movel (%sp)+, %d1
0766 movel (%sp)+, %d0
0767 rts
0768
0769
0770
0771
0772 timer_interrupt:
0773 bsr check_csr
0774 rte
0775
0776
0777
0778 #if DETECT_RAM
0779 ram_test:
0780 movel #0x12345678, %d1 // D1 = test value
0781 movel %d1, (128 * 1024 - 4)
0782 movel #128 * 1024, %d0 // D0 = RAM size tested
0783 ram_test_size:
0784 cmpl #MAX_RAM_SIZE, %d0
0785 beq ram_test_size_found
0786 movel %d0, %a0
0787 addl #128 * 1024 - 4, %a0
0788 cmpl (%a0), %d1
0789 beq ram_test_size_check
0790 ram_test_next_size:
0791 lsll #1, %d0
0792 bra ram_test_size
0793
0794 ram_test_size_check:
0795 eorl #0xFFFFFFFF, %d1
0796 movel %d1, (128 * 1024 - 4)
0797 cmpl (%a0), %d1
0798 bne ram_test_next_size
0799
0800 ram_test_size_found: // D0 = RAM size
0801 movel %d0, %a0 // A0 = fill ptr
0802 subl #firmware_end + 4, %d0
0803 lsrl #2, %d0
0804 movel %d0, %d1 // D1 = DBf counter
0805 ram_test_fill:
0806 movel %a0, -(%a0)
0807 dbfw %d1, ram_test_fill
0808 subl #0x10000, %d1
0809 cmpl #0xFFFFFFFF, %d1
0810 bne ram_test_fill
0811
0812 ram_test_loop: // D0 = DBf counter
0813 cmpl (%a0)+, %a0
0814 dbnew %d0, ram_test_loop
0815 bne ram_test_found_bad
0816 subl #0x10000, %d0
0817 cmpl #0xFFFFFFFF, %d0
0818 bne ram_test_loop
0819 bra ram_test_all_ok
0820
0821 ram_test_found_bad:
0822 subl #4, %a0
0823 ram_test_all_ok:
0824 movel %a0, PLX_MAILBOX_5
0825 rts
0826 #endif
0827
0828
0829
0830
0831 scc_reg_addr:
0832 .long SCC1_REGS, SCC2_REGS, SCC3_REGS, SCC4_REGS
0833 scc_base_addr:
0834 .long SCC1_BASE, SCC2_BASE, SCC3_BASE, SCC4_BASE
0835
0836 tx_first_bd:
0837 .long DPRBASE
0838 .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8
0839 .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 2
0840 .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 3
0841
0842 rx_first_bd:
0843 .long DPRBASE + TX_BUFFERS * 8
0844 .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8
0845 .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 2
0846 .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 3
0847
0848 first_buffer:
0849 .long BUFFERS_ADDR
0850 .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH
0851 .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 2
0852 .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 3
0853
0854 bell_tx:
0855 .long 1 << DOORBELL_FROM_CARD_TX_0, 1 << DOORBELL_FROM_CARD_TX_1
0856 .long 1 << DOORBELL_FROM_CARD_TX_2, 1 << DOORBELL_FROM_CARD_TX_3
0857
0858 bell_cable:
0859 .long 1 << DOORBELL_FROM_CARD_CABLE_0, 1 << DOORBELL_FROM_CARD_CABLE_1
0860 .long 1 << DOORBELL_FROM_CARD_CABLE_2, 1 << DOORBELL_FROM_CARD_CABLE_3
0861
0862 packet_full:
0863 .long PACKET_FULL, PACKET_FULL + 1, PACKET_FULL + 2, PACKET_FULL + 3
0864
0865 clocking_ext:
0866 .long 0x0000002C, 0x00003E00, 0x002C0000, 0x3E000000
0867 clocking_txfromrx:
0868 .long 0x0000002D, 0x00003F00, 0x002D0000, 0x3F000000
0869 clocking_mask:
0870 .long 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
0871 dcd_mask:
0872 .word 0x020, 0, 0x080, 0, 0x200, 0, 0x800
0873
0874 .ascii "wanXL firmware\n"
0875 .asciz "Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl>\n"
0876
0877
0878
0879
0880 .align 4
0881 channel_stats: .long 0
0882
0883 tx_in: .long 0, 0, 0, 0 // transmitted
0884 tx_out: .long 0, 0, 0, 0 // received from host for transmission
0885 tx_count: .long 0, 0, 0, 0 // currently in transmit queue
0886
0887 rx_in: .long 0, 0, 0, 0 // received from port
0888 rx_out: .long 0 // transmitted to host
0889 parity_bytes: .word 0, 0, 0, 0, 0, 0, 0 // only 4 words are used
0890
0891 csr_output: .word 0
0892 old_csr_output: .word 0, 0, 0, 0, 0, 0, 0
0893 .align 4
0894 firmware_end: // must be dword-aligned