URL
https://opencores.org/ocsvn/test_project/test_project/trunk
Subversion Repositories test_project
[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [wan/] [wanxlfw.S] - Rev 79
Go to most recent revision | Compare with Previous | Blame | View Log
.psize 0/*wanXL serial card driver for Linuxcard firmware partCopyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl>This program is free software; you can redistribute it and/or modify itunder the terms of version 2 of the GNU General Public Licenseas published by the Free Software Foundation.DPRAM BDs:0x000 - 0x050 TX#0 0x050 - 0x140 RX#00x140 - 0x190 TX#1 0x190 - 0x280 RX#10x280 - 0x2D0 TX#2 0x2D0 - 0x3C0 RX#20x3C0 - 0x410 TX#3 0x410 - 0x500 RX#3000 5FF 1536 Bytes Dual-Port RAM User Data / BDs600 6FF 256 Bytes Dual-Port RAM User Data / BDs700 7FF 256 Bytes Dual-Port RAM User Data / BDsC00 CBF 192 Bytes Dual-Port RAM Parameter RAM Page 1D00 DBF 192 Bytes Dual-Port RAM Parameter RAM Page 2E00 EBF 192 Bytes Dual-Port RAM Parameter RAM Page 3F00 FBF 192 Bytes Dual-Port RAM Parameter RAM Page 4local interrupts levelNMI 7PIT timer, CPM (RX/TX complete) 4PCI9060 DMA and PCI doorbells 3Cable - not used 1*/#include <linux/hdlc.h>#include "wanxl.h"/* memory addresses and offsets */MAX_RAM_SIZE = 16 * 1024 * 1024 // max RAM supported by hardwarePCI9060_VECTOR = 0x0000006CCPM_IRQ_BASE = 0x40ERROR_VECTOR = CPM_IRQ_BASE * 4SCC1_VECTOR = (CPM_IRQ_BASE + 0x1E) * 4SCC2_VECTOR = (CPM_IRQ_BASE + 0x1D) * 4SCC3_VECTOR = (CPM_IRQ_BASE + 0x1C) * 4SCC4_VECTOR = (CPM_IRQ_BASE + 0x1B) * 4CPM_IRQ_LEVEL = 4TIMER_IRQ = 128TIMER_IRQ_LEVEL = 4PITR_CONST = 0x100 + 16 // 1 Hz timerMBAR = 0x0003FF00VALUE_WINDOW = 0x40000000ORDER_WINDOW = 0xC0000000PLX = 0xFFF90000CSRA = 0xFFFB0000CSRB = 0xFFFB0002CSRC = 0xFFFB0004CSRD = 0xFFFB0006STATUS_CABLE_LL = 0x2000STATUS_CABLE_DTR = 0x1000DPRBASE = 0xFFFC0000SCC1_BASE = DPRBASE + 0xC00MISC_BASE = DPRBASE + 0xCB0SCC2_BASE = DPRBASE + 0xD00SCC3_BASE = DPRBASE + 0xE00SCC4_BASE = DPRBASE + 0xF00// offset from SCCx_BASE// SCC_xBASE contain offsets from DPRBASE and must be divisible by 8SCC_RBASE = 0 // 16-bit RxBD base addressSCC_TBASE = 2 // 16-bit TxBD base addressSCC_RFCR = 4 // 8-bit Rx function codeSCC_TFCR = 5 // 8-bit Tx function codeSCC_MRBLR = 6 // 16-bit maximum Rx buffer lengthSCC_C_MASK = 0x34 // 32-bit CRC constantSCC_C_PRES = 0x38 // 32-bit CRC presetSCC_MFLR = 0x46 // 16-bit max Rx frame length (without flags)REGBASE = DPRBASE + 0x1000PICR = REGBASE + 0x026 // 16-bit periodic irq controlPITR = REGBASE + 0x02A // 16-bit periodic irq timingOR1 = REGBASE + 0x064 // 32-bit RAM bank #1 optionsCICR = REGBASE + 0x540 // 32(24)-bit CP interrupt configCIMR = REGBASE + 0x548 // 32-bit CP interrupt maskCISR = REGBASE + 0x54C // 32-bit CP interrupts in-servicePADIR = REGBASE + 0x550 // 16-bit PortA data direction bitmapPAPAR = REGBASE + 0x552 // 16-bit PortA pin assignment bitmapPAODR = REGBASE + 0x554 // 16-bit PortA open drain bitmapPADAT = REGBASE + 0x556 // 16-bit PortA data registerPCDIR = REGBASE + 0x560 // 16-bit PortC data direction bitmapPCPAR = REGBASE + 0x562 // 16-bit PortC pin assignment bitmapPCSO = REGBASE + 0x564 // 16-bit PortC special optionsPCDAT = REGBASE + 0x566 // 16-bit PortC data registerPCINT = REGBASE + 0x568 // 16-bit PortC interrupt controlCR = REGBASE + 0x5C0 // 16-bit Command registerSCC1_REGS = REGBASE + 0x600SCC2_REGS = REGBASE + 0x620SCC3_REGS = REGBASE + 0x640SCC4_REGS = REGBASE + 0x660SICR = REGBASE + 0x6EC // 32-bit SI clock route// offset from SCCx_REGSSCC_GSMR_L = 0x00 // 32 bitsSCC_GSMR_H = 0x04 // 32 bitsSCC_PSMR = 0x08 // 16 bitsSCC_TODR = 0x0C // 16 bitsSCC_DSR = 0x0E // 16 bitsSCC_SCCE = 0x10 // 16 bitsSCC_SCCM = 0x14 // 16 bitsSCC_SCCS = 0x17 // 8 bits#if QUICC_MEMCPY_USES_PLX.macro memcpy_from_pci src, dest, len // len must be < 8 MBaddl #3, \lenandl #0xFFFFFFFC, \len // always copy n * 4 bytesmovel \src, PLX_DMA_0_PCImovel \dest, PLX_DMA_0_LOCALmovel \len, PLX_DMA_0_LENGTHmovel #0x0103, PLX_DMA_CMD_STS // start channel 0 transferbsr memcpy_from_pci_run.endm.macro memcpy_to_pci src, dest, lenaddl #3, \lenandl #0xFFFFFFFC, \len // always copy n * 4 bytesmovel \src, PLX_DMA_1_LOCALmovel \dest, PLX_DMA_1_PCImovel \len, PLX_DMA_1_LENGTHmovel #0x0301, PLX_DMA_CMD_STS // start channel 1 transferbsr memcpy_to_pci_run.endm#else.macro memcpy src, dest, len // len must be < 65536 bytesmovel %d7, -(%sp) // src and dest must be < 256 MBmovel \len, %d7 // bits 0 and 1lsrl #2, \lenandl \len, \lenbeq 99f // only 0 - 3 bytessubl #1, \len // for dbf98: movel (\src)+, (\dest)+dbfw \len, 98b99: movel %d7, \lenbtstl #1, \lenbeq 99fmovew (\src)+, (\dest)+99: btstl #0, \lenbeq 99fmoveb (\src)+, (\dest)+99:movel (%sp)+, %d7.endm.macro memcpy_from_pci src, dest, lenaddl #VALUE_WINDOW, \srcmemcpy \src, \dest, \len.endm.macro memcpy_to_pci src, dest, lenaddl #VALUE_WINDOW, \destmemcpy \src, \dest, \len.endm#endif.macro wait_for_command99: btstl #0, CRbne 99b.endm/****************************** card initialization *******************/.text.global _start_start: bra init.org _start + 4ch_status_addr: .long 0, 0, 0, 0rx_descs_addr: .long 0init:#if DETECT_RAMmovel OR1, %d0andl #0xF00007FF, %d0 // mask AMxx bitsorl #0xFFFF800 & ~(MAX_RAM_SIZE - 1), %d0 // update RAM bank sizemovel %d0, OR1#endifaddl #VALUE_WINDOW, rx_descs_addr // PCI addresses of shared dataclrl %d0 // D0 = 4 * portinit_1: tstl ch_status_addr(%d0)beq init_2addl #VALUE_WINDOW, ch_status_addr(%d0)init_2: addl #4, %d0cmpl #4 * 4, %d0bne init_1movel #pci9060_interrupt, PCI9060_VECTORmovel #error_interrupt, ERROR_VECTORmovel #port_interrupt_1, SCC1_VECTORmovel #port_interrupt_2, SCC2_VECTORmovel #port_interrupt_3, SCC3_VECTORmovel #port_interrupt_4, SCC4_VECTORmovel #timer_interrupt, TIMER_IRQ * 4movel #0x78000000, CIMR // only SCCx IRQs from CPMmovew #(TIMER_IRQ_LEVEL << 8) + TIMER_IRQ, PICR // interrupt from PITmovew #PITR_CONST, PITR// SCC1=SCCa SCC2=SCCb SCC3=SCCc SCC4=SCCd prio=4 HP=-1 IRQ=64-79movel #0xD41F40 + (CPM_IRQ_LEVEL << 13), CICRmovel #0x543, PLX_DMA_0_MODE // 32-bit, Ready, Burst, IRQmovel #0x543, PLX_DMA_1_MODEmovel #0x0, PLX_DMA_0_DESC // from PCI to localmovel #0x8, PLX_DMA_1_DESC // from local to PCImovel #0x101, PLX_DMA_CMD_STS // enable both DMA channels// enable local IRQ, DMA, doorbells and PCI IRQorl #0x000F0300, PLX_INTERRUPT_CS#if DETECT_RAMbsr ram_test#elsemovel #1, PLX_MAILBOX_5 // non-zero value = init complete#endifbsr check_csrmovew #0xFFFF, PAPAR // all pins are clocks/dataclrw PADIR // first functionclrw PCSO // CD and CTS always active/****************************** main loop *****************************/main: movel channel_stats, %d7 // D7 = doorbell + irq statusclrl channel_statststl %d7bne main_1// nothing to do - wait for next eventstop #0x2200 // supervisor + IRQ level 2movew #0x2700, %sr // disable IRQs againbra mainmain_1: clrl %d0 // D0 = 4 * portclrl %d6 // D6 = doorbell to host valuemain_l: btstl #DOORBELL_TO_CARD_CLOSE_0, %d7beq main_opbclrl #DOORBELL_TO_CARD_OPEN_0, %d7 // in case both bits are setbsr close_portmain_op:btstl #DOORBELL_TO_CARD_OPEN_0, %d7beq main_clbsr open_portmain_cl:btstl #DOORBELL_TO_CARD_TX_0, %d7beq main_txendbsr txmain_txend:btstl #TASK_SCC_0, %d7beq main_nextbsr tx_endbsr rxmain_next:lsrl #1, %d7 // port status for next portaddl #4, %d0 // D0 = 4 * next portcmpl #4 * 4, %d0bne main_lmovel %d6, PLX_DOORBELL_FROM_CARD // signal the hostbra main/****************************** open port *****************************/open_port: // D0 = 4 * port, D6 = doorbell to hostmovel ch_status_addr(%d0), %a0 // A0 = port status addresststl STATUS_OPEN(%a0)bne open_port_ret // port already openmovel #1, STATUS_OPEN(%a0) // confirm the port is open// setup BDsclrl tx_in(%d0)clrl tx_out(%d0)clrl tx_count(%d0)clrl rx_in(%d0)movel SICR, %d1 // D1 = clock settings in SICRandl clocking_mask(%d0), %d1cmpl #CLOCK_TXFROMRX, STATUS_CLOCKING(%a0)bne open_port_clock_extorl clocking_txfromrx(%d0), %d1bra open_port_set_clockopen_port_clock_ext:orl clocking_ext(%d0), %d1open_port_set_clock:movel %d1, SICR // update clock settings in SICRorw #STATUS_CABLE_DTR, csr_output(%d0) // DTR onbsr check_csr // call with disabled timer interrupt// Setup TX descriptorsmovel first_buffer(%d0), %d1 // D1 = starting buffer addressmovel tx_first_bd(%d0), %a1 // A1 = starting TX BD addressmovel #TX_BUFFERS - 2, %d2 // D2 = TX_BUFFERS - 1 countermovel #0x18000000, %d3 // D3 = initial TX BD flags: Int + Lastcmpl #PARITY_NONE, STATUS_PARITY(%a0)beq open_port_tx_loopbsetl #26, %d3 // TX BD flag: Transmit CRCopen_port_tx_loop:movel %d3, (%a1)+ // TX flags + lengthmovel %d1, (%a1)+ // buffer addressaddl #BUFFER_LENGTH, %d1dbfw %d2, open_port_tx_loopbsetl #29, %d3 // TX BD flag: Wrap (last BD)movel %d3, (%a1)+ // Final TX flags + lengthmovel %d1, (%a1)+ // buffer address// Setup RX descriptors // A1 = starting RX BD addressmovel #RX_BUFFERS - 2, %d2 // D2 = RX_BUFFERS - 1 counteropen_port_rx_loop:movel #0x90000000, (%a1)+ // RX flags + lengthmovel %d1, (%a1)+ // buffer addressaddl #BUFFER_LENGTH, %d1dbfw %d2, open_port_rx_loopmovel #0xB0000000, (%a1)+ // Final RX flags + lengthmovel %d1, (%a1)+ // buffer address// Setup port parametersmovel scc_base_addr(%d0), %a1 // A1 = SCC_BASE addressmovel scc_reg_addr(%d0), %a2 // A2 = SCC_REGS addressmovel #0xFFFF, SCC_SCCE(%a2) // clear status bitsmovel #0x0000, SCC_SCCM(%a2) // interrupt maskmovel tx_first_bd(%d0), %d1movew %d1, SCC_TBASE(%a1) // D1 = offset of first TxBDaddl #TX_BUFFERS * 8, %d1movew %d1, SCC_RBASE(%a1) // D1 = offset of first RxBDmoveb #0x8, SCC_RFCR(%a1) // Intel mode, 1000moveb #0x8, SCC_TFCR(%a1)// Parity settingscmpl #PARITY_CRC16_PR1_CCITT, STATUS_PARITY(%a0)bne open_port_parity_1clrw SCC_PSMR(%a2) // CRC16-CCITTmovel #0xF0B8, SCC_C_MASK(%a1)movel #0xFFFF, SCC_C_PRES(%a1)movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRCmovew #2, parity_bytes(%d0)bra open_port_2open_port_parity_1:cmpl #PARITY_CRC32_PR1_CCITT, STATUS_PARITY(%a0)bne open_port_parity_2movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITTmovel #0xDEBB20E3, SCC_C_MASK(%a1)movel #0xFFFFFFFF, SCC_C_PRES(%a1)movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRCmovew #4, parity_bytes(%d0)bra open_port_2open_port_parity_2:cmpl #PARITY_CRC16_PR0_CCITT, STATUS_PARITY(%a0)bne open_port_parity_3clrw SCC_PSMR(%a2) // CRC16-CCITT preset 0movel #0xF0B8, SCC_C_MASK(%a1)clrl SCC_C_PRES(%a1)movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRCmovew #2, parity_bytes(%d0)bra open_port_2open_port_parity_3:cmpl #PARITY_CRC32_PR0_CCITT, STATUS_PARITY(%a0)bne open_port_parity_4movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT preset 0movel #0xDEBB20E3, SCC_C_MASK(%a1)clrl SCC_C_PRES(%a1)movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRCmovew #4, parity_bytes(%d0)bra open_port_2open_port_parity_4:clrw SCC_PSMR(%a2) // no paritymovel #0xF0B8, SCC_C_MASK(%a1)movel #0xFFFF, SCC_C_PRES(%a1)movew #HDLC_MAX_MRU, SCC_MFLR(%a1) // 0 bytes for CRCclrw parity_bytes(%d0)open_port_2:movel #0x00000003, SCC_GSMR_H(%a2) // RTSMcmpl #ENCODING_NRZI, STATUS_ENCODING(%a0)bne open_port_nrzmovel #0x10040900, SCC_GSMR_L(%a2) // NRZI: TCI Tend RECN+TENC=1bra open_port_3open_port_nrz:movel #0x10040000, SCC_GSMR_L(%a2) // NRZ: TCI Tend RECN+TENC=0open_port_3:movew #BUFFER_LENGTH, SCC_MRBLR(%a1)movel %d0, %d1lsll #4, %d1 // D1 bits 7 and 6 = portorl #1, %d1movew %d1, CR // Init SCC RX and TX paramswait_for_command// TCI Tend ENR ENTmovew #0x001F, SCC_SCCM(%a2) // TXE RXF BSY TXB RXB interruptsorl #0x00000030, SCC_GSMR_L(%a2) // enable SCCopen_port_ret:rts/****************************** close port ****************************/close_port: // D0 = 4 * port, D6 = doorbell to hostmovel scc_reg_addr(%d0), %a0 // A0 = SCC_REGS addressclrw SCC_SCCM(%a0) // no SCC interruptsandl #0xFFFFFFCF, SCC_GSMR_L(%a0) // Disable ENT and ENRandw #~STATUS_CABLE_DTR, csr_output(%d0) // DTR offbsr check_csr // call with disabled timer interruptmovel ch_status_addr(%d0), %d1clrl STATUS_OPEN(%d1) // confirm the port is closedrts/****************************** transmit packet ***********************/// queue packets for transmissiontx: // D0 = 4 * port, D6 = doorbell to hostcmpl #TX_BUFFERS, tx_count(%d0)beq tx_ret // all DB's = descs in usemovel tx_out(%d0), %d1movel %d1, %d2 // D1 = D2 = tx_out BD# = desc#mulul #DESC_LENGTH, %d2 // D2 = TX desc offsetaddl ch_status_addr(%d0), %d2addl #STATUS_TX_DESCS, %d2 // D2 = TX desc addresscmpl #PACKET_FULL, (%d2) // desc statusbne tx_ret// queue itmovel 4(%d2), %a0 // PCI addresslsll #3, %d1 // BD is 8-bytes longaddl tx_first_bd(%d0), %d1 // D1 = current tx_out BD addrmovel 4(%d1), %a1 // A1 = dest addressmovel 8(%d2), %d2 // D2 = lengthmovew %d2, 2(%d1) // length into BDmemcpy_from_pci %a0, %a1, %d2bsetl #31, (%d1) // CP go ahead// update tx_out and tx_countmovel tx_out(%d0), %d1addl #1, %d1cmpl #TX_BUFFERS, %d1bne tx_1clrl %d1tx_1: movel %d1, tx_out(%d0)addl #1, tx_count(%d0)bra txtx_ret: rts/****************************** packet received ***********************/// Service receive buffers // D0 = 4 * port, D6 = doorbell to hostrx: movel rx_in(%d0), %d1 // D1 = rx_in BD#lsll #3, %d1 // BD is 8-bytes longaddl rx_first_bd(%d0), %d1 // D1 = current rx_in BD addressmovew (%d1), %d2 // D2 = RX BD flagsbtstl #15, %d2bne rx_ret // BD still emptybtstl #1, %d2bne rx_overruntstw parity_bytes(%d0)bne rx_paritybclrl #2, %d2 // do not test for CRC errorsrx_parity:andw #0x0CBC, %d2 // mask status bitscmpw #0x0C00, %d2 // correct framebne rx_bad_frameclrl %d3movew 2(%d1), %d3subw parity_bytes(%d0), %d3 // D3 = packet lengthcmpw #HDLC_MAX_MRU, %d3bgt rx_bad_framerx_good_frame:movel rx_out, %d2mulul #DESC_LENGTH, %d2addl rx_descs_addr, %d2 // D2 = RX desc addresscmpl #PACKET_EMPTY, (%d2) // desc statbne rx_overrunmovel %d3, 8(%d2)movel 4(%d1), %a0 // A0 = source addressmovel 4(%d2), %a1tstl %a1beq rx_ignore_datamemcpy_to_pci %a0, %a1, %d3rx_ignore_data:movel packet_full(%d0), (%d2) // update desc stat// update D6 and rx_outbsetl #DOORBELL_FROM_CARD_RX, %d6 // signal host that RX completedmovel rx_out, %d2addl #1, %d2cmpl #RX_QUEUE_LENGTH, %d2bne rx_1clrl %d2rx_1: movel %d2, rx_outrx_free_bd:andw #0xF000, (%d1) // clear CM and error bitsbsetl #31, (%d1) // free BD// update rx_inmovel rx_in(%d0), %d1addl #1, %d1cmpl #RX_BUFFERS, %d1bne rx_2clrl %d1rx_2: movel %d1, rx_in(%d0)bra rxrx_overrun:movel ch_status_addr(%d0), %d2addl #1, STATUS_RX_OVERRUNS(%d2)bra rx_free_bdrx_bad_frame:movel ch_status_addr(%d0), %d2addl #1, STATUS_RX_FRAME_ERRORS(%d2)bra rx_free_bdrx_ret: rts/****************************** packet transmitted ********************/// Service transmit buffers // D0 = 4 * port, D6 = doorbell to hosttx_end: tstl tx_count(%d0)beq tx_end_ret // TX buffers already emptymovel tx_in(%d0), %d1movel %d1, %d2 // D1 = D2 = tx_in BD# = desc#lsll #3, %d1 // BD is 8-bytes longaddl tx_first_bd(%d0), %d1 // D1 = current tx_in BD addressmovew (%d1), %d3 // D3 = TX BD flagsbtstl #15, %d3bne tx_end_ret // BD still being transmitted// update D6, tx_in and tx_countorl bell_tx(%d0), %d6 // signal host that TX desc freedsubl #1, tx_count(%d0)movel tx_in(%d0), %d1addl #1, %d1cmpl #TX_BUFFERS, %d1bne tx_end_1clrl %d1tx_end_1:movel %d1, tx_in(%d0)// free host's descriptormulul #DESC_LENGTH, %d2 // D2 = TX desc offsetaddl ch_status_addr(%d0), %d2addl #STATUS_TX_DESCS, %d2 // D2 = TX desc addressbtstl #1, %d3bne tx_end_underrunmovel #PACKET_SENT, (%d2)bra tx_endtx_end_underrun:movel #PACKET_UNDERRUN, (%d2)bra tx_endtx_end_ret: rts/****************************** PLX PCI9060 DMA memcpy ****************/#if QUICC_MEMCPY_USES_PLX// called with interrupts disabledmemcpy_from_pci_run:movel %d0, -(%sp)movew %sr, -(%sp)memcpy_1:movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directlybtstl #4, %d0 // transfer done?bne memcpy_endstop #0x2200 // enable PCI9060 interruptsmovew #0x2700, %sr // disable interrupts againbra memcpy_1memcpy_to_pci_run:movel %d0, -(%sp)movew %sr, -(%sp)memcpy_2:movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directlybtstl #12, %d0 // transfer done?bne memcpy_endstop #0x2200 // enable PCI9060 interruptsmovew #0x2700, %sr // disable interrupts againbra memcpy_2memcpy_end:movew (%sp)+, %srmovel (%sp)+, %d0rts#endif/****************************** PLX PCI9060 interrupt *****************/pci9060_interrupt:movel %d0, -(%sp)movel PLX_DOORBELL_TO_CARD, %d0movel %d0, PLX_DOORBELL_TO_CARD // confirm all requestsorl %d0, channel_statsmovel #0x0909, PLX_DMA_CMD_STS // clear DMA ch #0 and #1 interruptsmovel (%sp)+, %d0rte/****************************** SCC interrupts ************************/port_interrupt_1:orl #0, SCC1_REGS + SCC_SCCE; // confirm SCC eventsorl #1 << TASK_SCC_0, channel_statsmovel #0x40000000, CISRrteport_interrupt_2:orl #0, SCC2_REGS + SCC_SCCE; // confirm SCC eventsorl #1 << TASK_SCC_1, channel_statsmovel #0x20000000, CISRrteport_interrupt_3:orl #0, SCC3_REGS + SCC_SCCE; // confirm SCC eventsorl #1 << TASK_SCC_2, channel_statsmovel #0x10000000, CISRrteport_interrupt_4:orl #0, SCC4_REGS + SCC_SCCE; // confirm SCC eventsorl #1 << TASK_SCC_3, channel_statsmovel #0x08000000, CISRrteerror_interrupt:rte/****************************** cable and PM routine ******************/// modified registers: nonecheck_csr:movel %d0, -(%sp)movel %d1, -(%sp)movel %d2, -(%sp)movel %a0, -(%sp)movel %a1, -(%sp)clrl %d0 // D0 = 4 * portmovel #CSRA, %a0 // A0 = CSR addresscheck_csr_loop:movew (%a0), %d1 // D1 = CSR input bitsandl #0xE7, %d1 // PM and cable sense bits (no DCE bit)cmpw #STATUS_CABLE_V35 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1bne check_csr_1movew #0x0E08, %d1bra check_csr_validcheck_csr_1:cmpw #STATUS_CABLE_X21 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1bne check_csr_2movew #0x0408, %d1bra check_csr_validcheck_csr_2:cmpw #STATUS_CABLE_V24 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1bne check_csr_3movew #0x0208, %d1bra check_csr_validcheck_csr_3:cmpw #STATUS_CABLE_EIA530 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1bne check_csr_disablemovew #0x0D08, %d1bra check_csr_validcheck_csr_disable:movew #0x0008, %d1 // D1 = disable everythingmovew #0x80E7, %d2 // D2 = input mask: ignore DSRbra check_csr_writecheck_csr_valid: // D1 = mode and IRQ bitsmovew csr_output(%d0), %d2andw #0x3000, %d2 // D2 = requested LL and DTR bitsorw %d2, %d1 // D1 = all requested output bitsmovew #0x80FF, %d2 // D2 = input mask: include DSRcheck_csr_write:cmpw old_csr_output(%d0), %d1beq check_csr_inputmovew %d1, old_csr_output(%d0)movew %d1, (%a0) // Write CSR output bitscheck_csr_input:movew (PCDAT), %d1andw dcd_mask(%d0), %d1beq check_csr_dcd_on // DCD and CTS signals are negatedmovew (%a0), %d1 // D1 = CSR input bitsandw #~STATUS_CABLE_DCD, %d1 // DCD offbra check_csr_previouscheck_csr_dcd_on:movew (%a0), %d1 // D1 = CSR input bitsorw #STATUS_CABLE_DCD, %d1 // DCD oncheck_csr_previous:andw %d2, %d1 // input maskmovel ch_status_addr(%d0), %a1cmpl STATUS_CABLE(%a1), %d1 // check for changebeq check_csr_nextmovel %d1, STATUS_CABLE(%a1) // update statusmovel bell_cable(%d0), PLX_DOORBELL_FROM_CARD // signal the hostcheck_csr_next:addl #2, %a0 // next CSR registeraddl #4, %d0 // D0 = 4 * next portcmpl #4 * 4, %d0bne check_csr_loopmovel (%sp)+, %a1movel (%sp)+, %a0movel (%sp)+, %d2movel (%sp)+, %d1movel (%sp)+, %d0rts/****************************** timer interrupt ***********************/timer_interrupt:bsr check_csrrte/****************************** RAM sizing and test *******************/#if DETECT_RAMram_test:movel #0x12345678, %d1 // D1 = test valuemovel %d1, (128 * 1024 - 4)movel #128 * 1024, %d0 // D0 = RAM size testedram_test_size:cmpl #MAX_RAM_SIZE, %d0beq ram_test_size_foundmovel %d0, %a0addl #128 * 1024 - 4, %a0cmpl (%a0), %d1beq ram_test_size_checkram_test_next_size:lsll #1, %d0bra ram_test_sizeram_test_size_check:eorl #0xFFFFFFFF, %d1movel %d1, (128 * 1024 - 4)cmpl (%a0), %d1bne ram_test_next_sizeram_test_size_found: // D0 = RAM sizemovel %d0, %a0 // A0 = fill ptrsubl #firmware_end + 4, %d0lsrl #2, %d0movel %d0, %d1 // D1 = DBf counterram_test_fill:movel %a0, -(%a0)dbfw %d1, ram_test_fillsubl #0x10000, %d1cmpl #0xFFFFFFFF, %d1bne ram_test_fillram_test_loop: // D0 = DBf countercmpl (%a0)+, %a0dbnew %d0, ram_test_loopbne ram_test_found_badsubl #0x10000, %d0cmpl #0xFFFFFFFF, %d0bne ram_test_loopbra ram_test_all_okram_test_found_bad:subl #4, %a0ram_test_all_ok:movel %a0, PLX_MAILBOX_5rts#endif/****************************** constants *****************************/scc_reg_addr:.long SCC1_REGS, SCC2_REGS, SCC3_REGS, SCC4_REGSscc_base_addr:.long SCC1_BASE, SCC2_BASE, SCC3_BASE, SCC4_BASEtx_first_bd:.long DPRBASE.long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8.long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 2.long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 3rx_first_bd:.long DPRBASE + TX_BUFFERS * 8.long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8.long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 2.long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 3first_buffer:.long BUFFERS_ADDR.long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH.long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 2.long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 3bell_tx:.long 1 << DOORBELL_FROM_CARD_TX_0, 1 << DOORBELL_FROM_CARD_TX_1.long 1 << DOORBELL_FROM_CARD_TX_2, 1 << DOORBELL_FROM_CARD_TX_3bell_cable:.long 1 << DOORBELL_FROM_CARD_CABLE_0, 1 << DOORBELL_FROM_CARD_CABLE_1.long 1 << DOORBELL_FROM_CARD_CABLE_2, 1 << DOORBELL_FROM_CARD_CABLE_3packet_full:.long PACKET_FULL, PACKET_FULL + 1, PACKET_FULL + 2, PACKET_FULL + 3clocking_ext:.long 0x0000002C, 0x00003E00, 0x002C0000, 0x3E000000clocking_txfromrx:.long 0x0000002D, 0x00003F00, 0x002D0000, 0x3F000000clocking_mask:.long 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000dcd_mask:.word 0x020, 0, 0x080, 0, 0x200, 0, 0x800.ascii "wanXL firmware\n".asciz "Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl>\n"/****************************** variables *****************************/.align 4channel_stats: .long 0tx_in: .long 0, 0, 0, 0 // transmittedtx_out: .long 0, 0, 0, 0 // received from host for transmissiontx_count: .long 0, 0, 0, 0 // currently in transmit queuerx_in: .long 0, 0, 0, 0 // received from portrx_out: .long 0 // transmitted to hostparity_bytes: .word 0, 0, 0, 0, 0, 0, 0 // only 4 words are usedcsr_output: .word 0old_csr_output: .word 0, 0, 0, 0, 0, 0, 0.align 4firmware_end: // must be dword-aligned
Go to most recent revision | Compare with Previous | Blame | View Log
