1*25763b3cSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 21da177e4SLinus Torvalds.psize 0 31da177e4SLinus Torvalds/* 41da177e4SLinus Torvalds wanXL serial card driver for Linux 51da177e4SLinus Torvalds card firmware part 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl> 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds DPRAM BDs: 141da177e4SLinus Torvalds 0x000 - 0x050 TX#0 0x050 - 0x140 RX#0 151da177e4SLinus Torvalds 0x140 - 0x190 TX#1 0x190 - 0x280 RX#1 161da177e4SLinus Torvalds 0x280 - 0x2D0 TX#2 0x2D0 - 0x3C0 RX#2 171da177e4SLinus Torvalds 0x3C0 - 0x410 TX#3 0x410 - 0x500 RX#3 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds 000 5FF 1536 Bytes Dual-Port RAM User Data / BDs 211da177e4SLinus Torvalds 600 6FF 256 Bytes Dual-Port RAM User Data / BDs 221da177e4SLinus Torvalds 700 7FF 256 Bytes Dual-Port RAM User Data / BDs 231da177e4SLinus Torvalds C00 CBF 192 Bytes Dual-Port RAM Parameter RAM Page 1 241da177e4SLinus Torvalds D00 DBF 192 Bytes Dual-Port RAM Parameter RAM Page 2 251da177e4SLinus Torvalds E00 EBF 192 Bytes Dual-Port RAM Parameter RAM Page 3 261da177e4SLinus Torvalds F00 FBF 192 Bytes Dual-Port RAM Parameter RAM Page 4 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds local interrupts level 291da177e4SLinus Torvalds NMI 7 301da177e4SLinus Torvalds PIT timer, CPM (RX/TX complete) 4 311da177e4SLinus Torvalds PCI9060 DMA and PCI doorbells 3 321da177e4SLinus Torvalds Cable - not used 1 331da177e4SLinus Torvalds*/ 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds#include <linux/hdlc.h> 36c48c8d51SDavid Howells#include <linux/hdlc/ioctl.h> 371da177e4SLinus Torvalds#include "wanxl.h" 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds/* memory addresses and offsets */ 401da177e4SLinus Torvalds 411da177e4SLinus TorvaldsMAX_RAM_SIZE = 16 * 1024 * 1024 // max RAM supported by hardware 421da177e4SLinus Torvalds 431da177e4SLinus TorvaldsPCI9060_VECTOR = 0x0000006C 441da177e4SLinus TorvaldsCPM_IRQ_BASE = 0x40 451da177e4SLinus TorvaldsERROR_VECTOR = CPM_IRQ_BASE * 4 461da177e4SLinus TorvaldsSCC1_VECTOR = (CPM_IRQ_BASE + 0x1E) * 4 471da177e4SLinus TorvaldsSCC2_VECTOR = (CPM_IRQ_BASE + 0x1D) * 4 481da177e4SLinus TorvaldsSCC3_VECTOR = (CPM_IRQ_BASE + 0x1C) * 4 491da177e4SLinus TorvaldsSCC4_VECTOR = (CPM_IRQ_BASE + 0x1B) * 4 501da177e4SLinus TorvaldsCPM_IRQ_LEVEL = 4 511da177e4SLinus TorvaldsTIMER_IRQ = 128 521da177e4SLinus TorvaldsTIMER_IRQ_LEVEL = 4 531da177e4SLinus TorvaldsPITR_CONST = 0x100 + 16 // 1 Hz timer 541da177e4SLinus Torvalds 551da177e4SLinus TorvaldsMBAR = 0x0003FF00 561da177e4SLinus Torvalds 571da177e4SLinus TorvaldsVALUE_WINDOW = 0x40000000 581da177e4SLinus TorvaldsORDER_WINDOW = 0xC0000000 591da177e4SLinus Torvalds 601da177e4SLinus TorvaldsPLX = 0xFFF90000 611da177e4SLinus Torvalds 621da177e4SLinus TorvaldsCSRA = 0xFFFB0000 631da177e4SLinus TorvaldsCSRB = 0xFFFB0002 641da177e4SLinus TorvaldsCSRC = 0xFFFB0004 651da177e4SLinus TorvaldsCSRD = 0xFFFB0006 661da177e4SLinus TorvaldsSTATUS_CABLE_LL = 0x2000 671da177e4SLinus TorvaldsSTATUS_CABLE_DTR = 0x1000 681da177e4SLinus Torvalds 691da177e4SLinus TorvaldsDPRBASE = 0xFFFC0000 701da177e4SLinus Torvalds 711da177e4SLinus TorvaldsSCC1_BASE = DPRBASE + 0xC00 721da177e4SLinus TorvaldsMISC_BASE = DPRBASE + 0xCB0 731da177e4SLinus TorvaldsSCC2_BASE = DPRBASE + 0xD00 741da177e4SLinus TorvaldsSCC3_BASE = DPRBASE + 0xE00 751da177e4SLinus TorvaldsSCC4_BASE = DPRBASE + 0xF00 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds// offset from SCCx_BASE 781da177e4SLinus Torvalds// SCC_xBASE contain offsets from DPRBASE and must be divisible by 8 791da177e4SLinus TorvaldsSCC_RBASE = 0 // 16-bit RxBD base address 801da177e4SLinus TorvaldsSCC_TBASE = 2 // 16-bit TxBD base address 811da177e4SLinus TorvaldsSCC_RFCR = 4 // 8-bit Rx function code 821da177e4SLinus TorvaldsSCC_TFCR = 5 // 8-bit Tx function code 831da177e4SLinus TorvaldsSCC_MRBLR = 6 // 16-bit maximum Rx buffer length 841da177e4SLinus TorvaldsSCC_C_MASK = 0x34 // 32-bit CRC constant 851da177e4SLinus TorvaldsSCC_C_PRES = 0x38 // 32-bit CRC preset 861da177e4SLinus TorvaldsSCC_MFLR = 0x46 // 16-bit max Rx frame length (without flags) 871da177e4SLinus Torvalds 881da177e4SLinus TorvaldsREGBASE = DPRBASE + 0x1000 891da177e4SLinus TorvaldsPICR = REGBASE + 0x026 // 16-bit periodic irq control 901da177e4SLinus TorvaldsPITR = REGBASE + 0x02A // 16-bit periodic irq timing 911da177e4SLinus TorvaldsOR1 = REGBASE + 0x064 // 32-bit RAM bank #1 options 921da177e4SLinus TorvaldsCICR = REGBASE + 0x540 // 32(24)-bit CP interrupt config 931da177e4SLinus TorvaldsCIMR = REGBASE + 0x548 // 32-bit CP interrupt mask 941da177e4SLinus TorvaldsCISR = REGBASE + 0x54C // 32-bit CP interrupts in-service 951da177e4SLinus TorvaldsPADIR = REGBASE + 0x550 // 16-bit PortA data direction bitmap 961da177e4SLinus TorvaldsPAPAR = REGBASE + 0x552 // 16-bit PortA pin assignment bitmap 971da177e4SLinus TorvaldsPAODR = REGBASE + 0x554 // 16-bit PortA open drain bitmap 981da177e4SLinus TorvaldsPADAT = REGBASE + 0x556 // 16-bit PortA data register 991da177e4SLinus Torvalds 1001da177e4SLinus TorvaldsPCDIR = REGBASE + 0x560 // 16-bit PortC data direction bitmap 1011da177e4SLinus TorvaldsPCPAR = REGBASE + 0x562 // 16-bit PortC pin assignment bitmap 1021da177e4SLinus TorvaldsPCSO = REGBASE + 0x564 // 16-bit PortC special options 1031da177e4SLinus TorvaldsPCDAT = REGBASE + 0x566 // 16-bit PortC data register 1041da177e4SLinus TorvaldsPCINT = REGBASE + 0x568 // 16-bit PortC interrupt control 1051da177e4SLinus TorvaldsCR = REGBASE + 0x5C0 // 16-bit Command register 1061da177e4SLinus Torvalds 1071da177e4SLinus TorvaldsSCC1_REGS = REGBASE + 0x600 1081da177e4SLinus TorvaldsSCC2_REGS = REGBASE + 0x620 1091da177e4SLinus TorvaldsSCC3_REGS = REGBASE + 0x640 1101da177e4SLinus TorvaldsSCC4_REGS = REGBASE + 0x660 1111da177e4SLinus TorvaldsSICR = REGBASE + 0x6EC // 32-bit SI clock route 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds// offset from SCCx_REGS 1141da177e4SLinus TorvaldsSCC_GSMR_L = 0x00 // 32 bits 1151da177e4SLinus TorvaldsSCC_GSMR_H = 0x04 // 32 bits 1161da177e4SLinus TorvaldsSCC_PSMR = 0x08 // 16 bits 1171da177e4SLinus TorvaldsSCC_TODR = 0x0C // 16 bits 1181da177e4SLinus TorvaldsSCC_DSR = 0x0E // 16 bits 1191da177e4SLinus TorvaldsSCC_SCCE = 0x10 // 16 bits 1201da177e4SLinus TorvaldsSCC_SCCM = 0x14 // 16 bits 1211da177e4SLinus TorvaldsSCC_SCCS = 0x17 // 8 bits 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds#if QUICC_MEMCPY_USES_PLX 1241da177e4SLinus Torvalds .macro memcpy_from_pci src, dest, len // len must be < 8 MB 1251da177e4SLinus Torvalds addl #3, \len 1261da177e4SLinus Torvalds andl #0xFFFFFFFC, \len // always copy n * 4 bytes 1271da177e4SLinus Torvalds movel \src, PLX_DMA_0_PCI 1281da177e4SLinus Torvalds movel \dest, PLX_DMA_0_LOCAL 1291da177e4SLinus Torvalds movel \len, PLX_DMA_0_LENGTH 1301da177e4SLinus Torvalds movel #0x0103, PLX_DMA_CMD_STS // start channel 0 transfer 1311da177e4SLinus Torvalds bsr memcpy_from_pci_run 1321da177e4SLinus Torvalds .endm 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds .macro memcpy_to_pci src, dest, len 1351da177e4SLinus Torvalds addl #3, \len 1361da177e4SLinus Torvalds andl #0xFFFFFFFC, \len // always copy n * 4 bytes 1371da177e4SLinus Torvalds movel \src, PLX_DMA_1_LOCAL 1381da177e4SLinus Torvalds movel \dest, PLX_DMA_1_PCI 1391da177e4SLinus Torvalds movel \len, PLX_DMA_1_LENGTH 1401da177e4SLinus Torvalds movel #0x0301, PLX_DMA_CMD_STS // start channel 1 transfer 1411da177e4SLinus Torvalds bsr memcpy_to_pci_run 1421da177e4SLinus Torvalds .endm 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds#else 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds .macro memcpy src, dest, len // len must be < 65536 bytes 1471da177e4SLinus Torvalds movel %d7, -(%sp) // src and dest must be < 256 MB 1481da177e4SLinus Torvalds movel \len, %d7 // bits 0 and 1 1491da177e4SLinus Torvalds lsrl #2, \len 1501da177e4SLinus Torvalds andl \len, \len 1511da177e4SLinus Torvalds beq 99f // only 0 - 3 bytes 1521da177e4SLinus Torvalds subl #1, \len // for dbf 1531da177e4SLinus Torvalds98: movel (\src)+, (\dest)+ 1541da177e4SLinus Torvalds dbfw \len, 98b 1551da177e4SLinus Torvalds99: movel %d7, \len 1561da177e4SLinus Torvalds btstl #1, \len 1571da177e4SLinus Torvalds beq 99f 1581da177e4SLinus Torvalds movew (\src)+, (\dest)+ 1591da177e4SLinus Torvalds99: btstl #0, \len 1601da177e4SLinus Torvalds beq 99f 1611da177e4SLinus Torvalds moveb (\src)+, (\dest)+ 1621da177e4SLinus Torvalds99: 1631da177e4SLinus Torvalds movel (%sp)+, %d7 1641da177e4SLinus Torvalds .endm 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds .macro memcpy_from_pci src, dest, len 1671da177e4SLinus Torvalds addl #VALUE_WINDOW, \src 1681da177e4SLinus Torvalds memcpy \src, \dest, \len 1691da177e4SLinus Torvalds .endm 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds .macro memcpy_to_pci src, dest, len 1721da177e4SLinus Torvalds addl #VALUE_WINDOW, \dest 1731da177e4SLinus Torvalds memcpy \src, \dest, \len 1741da177e4SLinus Torvalds .endm 1751da177e4SLinus Torvalds#endif 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds .macro wait_for_command 1791da177e4SLinus Torvalds99: btstl #0, CR 1801da177e4SLinus Torvalds bne 99b 1811da177e4SLinus Torvalds .endm 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds/****************************** card initialization *******************/ 1871da177e4SLinus Torvalds .text 1881da177e4SLinus Torvalds .global _start 1891da177e4SLinus Torvalds_start: bra init 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds .org _start + 4 1921da177e4SLinus Torvaldsch_status_addr: .long 0, 0, 0, 0 1931da177e4SLinus Torvaldsrx_descs_addr: .long 0 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvaldsinit: 1961da177e4SLinus Torvalds#if DETECT_RAM 1971da177e4SLinus Torvalds movel OR1, %d0 1981da177e4SLinus Torvalds andl #0xF00007FF, %d0 // mask AMxx bits 1991da177e4SLinus Torvalds orl #0xFFFF800 & ~(MAX_RAM_SIZE - 1), %d0 // update RAM bank size 2001da177e4SLinus Torvalds movel %d0, OR1 2011da177e4SLinus Torvalds#endif 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds addl #VALUE_WINDOW, rx_descs_addr // PCI addresses of shared data 2041da177e4SLinus Torvalds clrl %d0 // D0 = 4 * port 2051da177e4SLinus Torvaldsinit_1: tstl ch_status_addr(%d0) 2061da177e4SLinus Torvalds beq init_2 2071da177e4SLinus Torvalds addl #VALUE_WINDOW, ch_status_addr(%d0) 2081da177e4SLinus Torvaldsinit_2: addl #4, %d0 2091da177e4SLinus Torvalds cmpl #4 * 4, %d0 2101da177e4SLinus Torvalds bne init_1 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds movel #pci9060_interrupt, PCI9060_VECTOR 2131da177e4SLinus Torvalds movel #error_interrupt, ERROR_VECTOR 2141da177e4SLinus Torvalds movel #port_interrupt_1, SCC1_VECTOR 2151da177e4SLinus Torvalds movel #port_interrupt_2, SCC2_VECTOR 2161da177e4SLinus Torvalds movel #port_interrupt_3, SCC3_VECTOR 2171da177e4SLinus Torvalds movel #port_interrupt_4, SCC4_VECTOR 2181da177e4SLinus Torvalds movel #timer_interrupt, TIMER_IRQ * 4 2191da177e4SLinus Torvalds 2201da177e4SLinus Torvalds movel #0x78000000, CIMR // only SCCx IRQs from CPM 2211da177e4SLinus Torvalds movew #(TIMER_IRQ_LEVEL << 8) + TIMER_IRQ, PICR // interrupt from PIT 2221da177e4SLinus Torvalds movew #PITR_CONST, PITR 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds // SCC1=SCCa SCC2=SCCb SCC3=SCCc SCC4=SCCd prio=4 HP=-1 IRQ=64-79 2251da177e4SLinus Torvalds movel #0xD41F40 + (CPM_IRQ_LEVEL << 13), CICR 2261da177e4SLinus Torvalds movel #0x543, PLX_DMA_0_MODE // 32-bit, Ready, Burst, IRQ 2271da177e4SLinus Torvalds movel #0x543, PLX_DMA_1_MODE 2281da177e4SLinus Torvalds movel #0x0, PLX_DMA_0_DESC // from PCI to local 2291da177e4SLinus Torvalds movel #0x8, PLX_DMA_1_DESC // from local to PCI 2301da177e4SLinus Torvalds movel #0x101, PLX_DMA_CMD_STS // enable both DMA channels 2311da177e4SLinus Torvalds // enable local IRQ, DMA, doorbells and PCI IRQ 2321da177e4SLinus Torvalds orl #0x000F0300, PLX_INTERRUPT_CS 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds#if DETECT_RAM 2351da177e4SLinus Torvalds bsr ram_test 2361da177e4SLinus Torvalds#else 2371da177e4SLinus Torvalds movel #1, PLX_MAILBOX_5 // non-zero value = init complete 2381da177e4SLinus Torvalds#endif 2391da177e4SLinus Torvalds bsr check_csr 2401da177e4SLinus Torvalds 2411da177e4SLinus Torvalds movew #0xFFFF, PAPAR // all pins are clocks/data 2421da177e4SLinus Torvalds clrw PADIR // first function 2431da177e4SLinus Torvalds clrw PCSO // CD and CTS always active 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds/****************************** main loop *****************************/ 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvaldsmain: movel channel_stats, %d7 // D7 = doorbell + irq status 2491da177e4SLinus Torvalds clrl channel_stats 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds tstl %d7 2521da177e4SLinus Torvalds bne main_1 2531da177e4SLinus Torvalds // nothing to do - wait for next event 2541da177e4SLinus Torvalds stop #0x2200 // supervisor + IRQ level 2 2551da177e4SLinus Torvalds movew #0x2700, %sr // disable IRQs again 2561da177e4SLinus Torvalds bra main 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvaldsmain_1: clrl %d0 // D0 = 4 * port 2591da177e4SLinus Torvalds clrl %d6 // D6 = doorbell to host value 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvaldsmain_l: btstl #DOORBELL_TO_CARD_CLOSE_0, %d7 2621da177e4SLinus Torvalds beq main_op 2631da177e4SLinus Torvalds bclrl #DOORBELL_TO_CARD_OPEN_0, %d7 // in case both bits are set 2641da177e4SLinus Torvalds bsr close_port 2651da177e4SLinus Torvaldsmain_op: 2661da177e4SLinus Torvalds btstl #DOORBELL_TO_CARD_OPEN_0, %d7 2671da177e4SLinus Torvalds beq main_cl 2681da177e4SLinus Torvalds bsr open_port 2691da177e4SLinus Torvaldsmain_cl: 2701da177e4SLinus Torvalds btstl #DOORBELL_TO_CARD_TX_0, %d7 2711da177e4SLinus Torvalds beq main_txend 2721da177e4SLinus Torvalds bsr tx 2731da177e4SLinus Torvaldsmain_txend: 2741da177e4SLinus Torvalds btstl #TASK_SCC_0, %d7 2751da177e4SLinus Torvalds beq main_next 2761da177e4SLinus Torvalds bsr tx_end 2771da177e4SLinus Torvalds bsr rx 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvaldsmain_next: 2801da177e4SLinus Torvalds lsrl #1, %d7 // port status for next port 2811da177e4SLinus Torvalds addl #4, %d0 // D0 = 4 * next port 2821da177e4SLinus Torvalds cmpl #4 * 4, %d0 2831da177e4SLinus Torvalds bne main_l 2841da177e4SLinus Torvalds movel %d6, PLX_DOORBELL_FROM_CARD // signal the host 2851da177e4SLinus Torvalds bra main 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds/****************************** open port *****************************/ 2891da177e4SLinus Torvalds 2901da177e4SLinus Torvaldsopen_port: // D0 = 4 * port, D6 = doorbell to host 2911da177e4SLinus Torvalds movel ch_status_addr(%d0), %a0 // A0 = port status address 2921da177e4SLinus Torvalds tstl STATUS_OPEN(%a0) 2931da177e4SLinus Torvalds bne open_port_ret // port already open 2941da177e4SLinus Torvalds movel #1, STATUS_OPEN(%a0) // confirm the port is open 2951da177e4SLinus Torvalds// setup BDs 2961da177e4SLinus Torvalds clrl tx_in(%d0) 2971da177e4SLinus Torvalds clrl tx_out(%d0) 2981da177e4SLinus Torvalds clrl tx_count(%d0) 2991da177e4SLinus Torvalds clrl rx_in(%d0) 3001da177e4SLinus Torvalds 3011da177e4SLinus Torvalds movel SICR, %d1 // D1 = clock settings in SICR 3021da177e4SLinus Torvalds andl clocking_mask(%d0), %d1 3031da177e4SLinus Torvalds cmpl #CLOCK_TXFROMRX, STATUS_CLOCKING(%a0) 3041da177e4SLinus Torvalds bne open_port_clock_ext 3051da177e4SLinus Torvalds orl clocking_txfromrx(%d0), %d1 3061da177e4SLinus Torvalds bra open_port_set_clock 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvaldsopen_port_clock_ext: 3091da177e4SLinus Torvalds orl clocking_ext(%d0), %d1 3101da177e4SLinus Torvaldsopen_port_set_clock: 3111da177e4SLinus Torvalds movel %d1, SICR // update clock settings in SICR 3121da177e4SLinus Torvalds 3131da177e4SLinus Torvalds orw #STATUS_CABLE_DTR, csr_output(%d0) // DTR on 3141da177e4SLinus Torvalds bsr check_csr // call with disabled timer interrupt 3151da177e4SLinus Torvalds 3161da177e4SLinus Torvalds// Setup TX descriptors 3171da177e4SLinus Torvalds movel first_buffer(%d0), %d1 // D1 = starting buffer address 3181da177e4SLinus Torvalds movel tx_first_bd(%d0), %a1 // A1 = starting TX BD address 3191da177e4SLinus Torvalds movel #TX_BUFFERS - 2, %d2 // D2 = TX_BUFFERS - 1 counter 3201da177e4SLinus Torvalds movel #0x18000000, %d3 // D3 = initial TX BD flags: Int + Last 3211da177e4SLinus Torvalds cmpl #PARITY_NONE, STATUS_PARITY(%a0) 3221da177e4SLinus Torvalds beq open_port_tx_loop 3231da177e4SLinus Torvalds bsetl #26, %d3 // TX BD flag: Transmit CRC 3241da177e4SLinus Torvaldsopen_port_tx_loop: 3251da177e4SLinus Torvalds movel %d3, (%a1)+ // TX flags + length 3261da177e4SLinus Torvalds movel %d1, (%a1)+ // buffer address 3271da177e4SLinus Torvalds addl #BUFFER_LENGTH, %d1 3281da177e4SLinus Torvalds dbfw %d2, open_port_tx_loop 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds bsetl #29, %d3 // TX BD flag: Wrap (last BD) 3311da177e4SLinus Torvalds movel %d3, (%a1)+ // Final TX flags + length 3321da177e4SLinus Torvalds movel %d1, (%a1)+ // buffer address 3331da177e4SLinus Torvalds 3341da177e4SLinus Torvalds// Setup RX descriptors // A1 = starting RX BD address 3351da177e4SLinus Torvalds movel #RX_BUFFERS - 2, %d2 // D2 = RX_BUFFERS - 1 counter 3361da177e4SLinus Torvaldsopen_port_rx_loop: 3371da177e4SLinus Torvalds movel #0x90000000, (%a1)+ // RX flags + length 3381da177e4SLinus Torvalds movel %d1, (%a1)+ // buffer address 3391da177e4SLinus Torvalds addl #BUFFER_LENGTH, %d1 3401da177e4SLinus Torvalds dbfw %d2, open_port_rx_loop 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds movel #0xB0000000, (%a1)+ // Final RX flags + length 3431da177e4SLinus Torvalds movel %d1, (%a1)+ // buffer address 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds// Setup port parameters 3461da177e4SLinus Torvalds movel scc_base_addr(%d0), %a1 // A1 = SCC_BASE address 3471da177e4SLinus Torvalds movel scc_reg_addr(%d0), %a2 // A2 = SCC_REGS address 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds movel #0xFFFF, SCC_SCCE(%a2) // clear status bits 3501da177e4SLinus Torvalds movel #0x0000, SCC_SCCM(%a2) // interrupt mask 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds movel tx_first_bd(%d0), %d1 3531da177e4SLinus Torvalds movew %d1, SCC_TBASE(%a1) // D1 = offset of first TxBD 3541da177e4SLinus Torvalds addl #TX_BUFFERS * 8, %d1 3551da177e4SLinus Torvalds movew %d1, SCC_RBASE(%a1) // D1 = offset of first RxBD 3561da177e4SLinus Torvalds moveb #0x8, SCC_RFCR(%a1) // Intel mode, 1000 3571da177e4SLinus Torvalds moveb #0x8, SCC_TFCR(%a1) 3581da177e4SLinus Torvalds 3591da177e4SLinus Torvalds// Parity settings 3601da177e4SLinus Torvalds cmpl #PARITY_CRC16_PR1_CCITT, STATUS_PARITY(%a0) 3611da177e4SLinus Torvalds bne open_port_parity_1 3621da177e4SLinus Torvalds clrw SCC_PSMR(%a2) // CRC16-CCITT 3631da177e4SLinus Torvalds movel #0xF0B8, SCC_C_MASK(%a1) 3641da177e4SLinus Torvalds movel #0xFFFF, SCC_C_PRES(%a1) 3651da177e4SLinus Torvalds movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC 3661da177e4SLinus Torvalds movew #2, parity_bytes(%d0) 3671da177e4SLinus Torvalds bra open_port_2 3681da177e4SLinus Torvalds 3691da177e4SLinus Torvaldsopen_port_parity_1: 3701da177e4SLinus Torvalds cmpl #PARITY_CRC32_PR1_CCITT, STATUS_PARITY(%a0) 3711da177e4SLinus Torvalds bne open_port_parity_2 3721da177e4SLinus Torvalds movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT 3731da177e4SLinus Torvalds movel #0xDEBB20E3, SCC_C_MASK(%a1) 3741da177e4SLinus Torvalds movel #0xFFFFFFFF, SCC_C_PRES(%a1) 3751da177e4SLinus Torvalds movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC 3761da177e4SLinus Torvalds movew #4, parity_bytes(%d0) 3771da177e4SLinus Torvalds bra open_port_2 3781da177e4SLinus Torvalds 3791da177e4SLinus Torvaldsopen_port_parity_2: 3801da177e4SLinus Torvalds cmpl #PARITY_CRC16_PR0_CCITT, STATUS_PARITY(%a0) 3811da177e4SLinus Torvalds bne open_port_parity_3 3821da177e4SLinus Torvalds clrw SCC_PSMR(%a2) // CRC16-CCITT preset 0 3831da177e4SLinus Torvalds movel #0xF0B8, SCC_C_MASK(%a1) 3841da177e4SLinus Torvalds clrl SCC_C_PRES(%a1) 3851da177e4SLinus Torvalds movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC 3861da177e4SLinus Torvalds movew #2, parity_bytes(%d0) 3871da177e4SLinus Torvalds bra open_port_2 3881da177e4SLinus Torvalds 3891da177e4SLinus Torvaldsopen_port_parity_3: 3901da177e4SLinus Torvalds cmpl #PARITY_CRC32_PR0_CCITT, STATUS_PARITY(%a0) 3911da177e4SLinus Torvalds bne open_port_parity_4 3921da177e4SLinus Torvalds movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT preset 0 3931da177e4SLinus Torvalds movel #0xDEBB20E3, SCC_C_MASK(%a1) 3941da177e4SLinus Torvalds clrl SCC_C_PRES(%a1) 3951da177e4SLinus Torvalds movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC 3961da177e4SLinus Torvalds movew #4, parity_bytes(%d0) 3971da177e4SLinus Torvalds bra open_port_2 3981da177e4SLinus Torvalds 3991da177e4SLinus Torvaldsopen_port_parity_4: 4001da177e4SLinus Torvalds clrw SCC_PSMR(%a2) // no parity 4011da177e4SLinus Torvalds movel #0xF0B8, SCC_C_MASK(%a1) 4021da177e4SLinus Torvalds movel #0xFFFF, SCC_C_PRES(%a1) 4031da177e4SLinus Torvalds movew #HDLC_MAX_MRU, SCC_MFLR(%a1) // 0 bytes for CRC 4041da177e4SLinus Torvalds clrw parity_bytes(%d0) 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvaldsopen_port_2: 4071da177e4SLinus Torvalds movel #0x00000003, SCC_GSMR_H(%a2) // RTSM 4081da177e4SLinus Torvalds cmpl #ENCODING_NRZI, STATUS_ENCODING(%a0) 4091da177e4SLinus Torvalds bne open_port_nrz 4101da177e4SLinus Torvalds movel #0x10040900, SCC_GSMR_L(%a2) // NRZI: TCI Tend RECN+TENC=1 4111da177e4SLinus Torvalds bra open_port_3 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvaldsopen_port_nrz: 4141da177e4SLinus Torvalds movel #0x10040000, SCC_GSMR_L(%a2) // NRZ: TCI Tend RECN+TENC=0 4151da177e4SLinus Torvaldsopen_port_3: 4161da177e4SLinus Torvalds movew #BUFFER_LENGTH, SCC_MRBLR(%a1) 4171da177e4SLinus Torvalds movel %d0, %d1 4181da177e4SLinus Torvalds lsll #4, %d1 // D1 bits 7 and 6 = port 4191da177e4SLinus Torvalds orl #1, %d1 4201da177e4SLinus Torvalds movew %d1, CR // Init SCC RX and TX params 4211da177e4SLinus Torvalds wait_for_command 4221da177e4SLinus Torvalds 4231da177e4SLinus Torvalds // TCI Tend ENR ENT 4241da177e4SLinus Torvalds movew #0x001F, SCC_SCCM(%a2) // TXE RXF BSY TXB RXB interrupts 4251da177e4SLinus Torvalds orl #0x00000030, SCC_GSMR_L(%a2) // enable SCC 4261da177e4SLinus Torvaldsopen_port_ret: 4271da177e4SLinus Torvalds rts 4281da177e4SLinus Torvalds 4291da177e4SLinus Torvalds 4301da177e4SLinus Torvalds/****************************** close port ****************************/ 4311da177e4SLinus Torvalds 4321da177e4SLinus Torvaldsclose_port: // D0 = 4 * port, D6 = doorbell to host 4331da177e4SLinus Torvalds movel scc_reg_addr(%d0), %a0 // A0 = SCC_REGS address 4341da177e4SLinus Torvalds clrw SCC_SCCM(%a0) // no SCC interrupts 4351da177e4SLinus Torvalds andl #0xFFFFFFCF, SCC_GSMR_L(%a0) // Disable ENT and ENR 4361da177e4SLinus Torvalds 4371da177e4SLinus Torvalds andw #~STATUS_CABLE_DTR, csr_output(%d0) // DTR off 4381da177e4SLinus Torvalds bsr check_csr // call with disabled timer interrupt 4391da177e4SLinus Torvalds 4401da177e4SLinus Torvalds movel ch_status_addr(%d0), %d1 4411da177e4SLinus Torvalds clrl STATUS_OPEN(%d1) // confirm the port is closed 4421da177e4SLinus Torvalds rts 4431da177e4SLinus Torvalds 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds/****************************** transmit packet ***********************/ 4461da177e4SLinus Torvalds// queue packets for transmission 4471da177e4SLinus Torvaldstx: // D0 = 4 * port, D6 = doorbell to host 4481da177e4SLinus Torvalds cmpl #TX_BUFFERS, tx_count(%d0) 4491da177e4SLinus Torvalds beq tx_ret // all DB's = descs in use 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds movel tx_out(%d0), %d1 4521da177e4SLinus Torvalds movel %d1, %d2 // D1 = D2 = tx_out BD# = desc# 4531da177e4SLinus Torvalds mulul #DESC_LENGTH, %d2 // D2 = TX desc offset 4541da177e4SLinus Torvalds addl ch_status_addr(%d0), %d2 4551da177e4SLinus Torvalds addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address 4561da177e4SLinus Torvalds cmpl #PACKET_FULL, (%d2) // desc status 4571da177e4SLinus Torvalds bne tx_ret 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds// queue it 4601da177e4SLinus Torvalds movel 4(%d2), %a0 // PCI address 4611da177e4SLinus Torvalds lsll #3, %d1 // BD is 8-bytes long 4621da177e4SLinus Torvalds addl tx_first_bd(%d0), %d1 // D1 = current tx_out BD addr 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds movel 4(%d1), %a1 // A1 = dest address 4651da177e4SLinus Torvalds movel 8(%d2), %d2 // D2 = length 4661da177e4SLinus Torvalds movew %d2, 2(%d1) // length into BD 4671da177e4SLinus Torvalds memcpy_from_pci %a0, %a1, %d2 4681da177e4SLinus Torvalds bsetl #31, (%d1) // CP go ahead 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds// update tx_out and tx_count 4711da177e4SLinus Torvalds movel tx_out(%d0), %d1 4721da177e4SLinus Torvalds addl #1, %d1 4731da177e4SLinus Torvalds cmpl #TX_BUFFERS, %d1 4741da177e4SLinus Torvalds bne tx_1 4751da177e4SLinus Torvalds clrl %d1 4761da177e4SLinus Torvaldstx_1: movel %d1, tx_out(%d0) 4771da177e4SLinus Torvalds 4781da177e4SLinus Torvalds addl #1, tx_count(%d0) 4791da177e4SLinus Torvalds bra tx 4801da177e4SLinus Torvalds 4811da177e4SLinus Torvaldstx_ret: rts 4821da177e4SLinus Torvalds 4831da177e4SLinus Torvalds 4841da177e4SLinus Torvalds/****************************** packet received ***********************/ 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds// Service receive buffers // D0 = 4 * port, D6 = doorbell to host 4871da177e4SLinus Torvaldsrx: movel rx_in(%d0), %d1 // D1 = rx_in BD# 4881da177e4SLinus Torvalds lsll #3, %d1 // BD is 8-bytes long 4891da177e4SLinus Torvalds addl rx_first_bd(%d0), %d1 // D1 = current rx_in BD address 4901da177e4SLinus Torvalds movew (%d1), %d2 // D2 = RX BD flags 4911da177e4SLinus Torvalds btstl #15, %d2 4921da177e4SLinus Torvalds bne rx_ret // BD still empty 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds btstl #1, %d2 4951da177e4SLinus Torvalds bne rx_overrun 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds tstw parity_bytes(%d0) 4981da177e4SLinus Torvalds bne rx_parity 4991da177e4SLinus Torvalds bclrl #2, %d2 // do not test for CRC errors 5001da177e4SLinus Torvaldsrx_parity: 5011da177e4SLinus Torvalds andw #0x0CBC, %d2 // mask status bits 5021da177e4SLinus Torvalds cmpw #0x0C00, %d2 // correct frame 5031da177e4SLinus Torvalds bne rx_bad_frame 5041da177e4SLinus Torvalds clrl %d3 5051da177e4SLinus Torvalds movew 2(%d1), %d3 5061da177e4SLinus Torvalds subw parity_bytes(%d0), %d3 // D3 = packet length 5071da177e4SLinus Torvalds cmpw #HDLC_MAX_MRU, %d3 5081da177e4SLinus Torvalds bgt rx_bad_frame 5091da177e4SLinus Torvalds 5101da177e4SLinus Torvaldsrx_good_frame: 5111da177e4SLinus Torvalds movel rx_out, %d2 5121da177e4SLinus Torvalds mulul #DESC_LENGTH, %d2 5131da177e4SLinus Torvalds addl rx_descs_addr, %d2 // D2 = RX desc address 5141da177e4SLinus Torvalds cmpl #PACKET_EMPTY, (%d2) // desc stat 5151da177e4SLinus Torvalds bne rx_overrun 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds movel %d3, 8(%d2) 5181da177e4SLinus Torvalds movel 4(%d1), %a0 // A0 = source address 5191da177e4SLinus Torvalds movel 4(%d2), %a1 5201da177e4SLinus Torvalds tstl %a1 5211da177e4SLinus Torvalds beq rx_ignore_data 5221da177e4SLinus Torvalds memcpy_to_pci %a0, %a1, %d3 5231da177e4SLinus Torvaldsrx_ignore_data: 5241da177e4SLinus Torvalds movel packet_full(%d0), (%d2) // update desc stat 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds// update D6 and rx_out 5271da177e4SLinus Torvalds bsetl #DOORBELL_FROM_CARD_RX, %d6 // signal host that RX completed 5281da177e4SLinus Torvalds movel rx_out, %d2 5291da177e4SLinus Torvalds addl #1, %d2 5301da177e4SLinus Torvalds cmpl #RX_QUEUE_LENGTH, %d2 5311da177e4SLinus Torvalds bne rx_1 5321da177e4SLinus Torvalds clrl %d2 5331da177e4SLinus Torvaldsrx_1: movel %d2, rx_out 5341da177e4SLinus Torvalds 5351da177e4SLinus Torvaldsrx_free_bd: 5361da177e4SLinus Torvalds andw #0xF000, (%d1) // clear CM and error bits 5371da177e4SLinus Torvalds bsetl #31, (%d1) // free BD 5381da177e4SLinus Torvalds// update rx_in 5391da177e4SLinus Torvalds movel rx_in(%d0), %d1 5401da177e4SLinus Torvalds addl #1, %d1 5411da177e4SLinus Torvalds cmpl #RX_BUFFERS, %d1 5421da177e4SLinus Torvalds bne rx_2 5431da177e4SLinus Torvalds clrl %d1 5441da177e4SLinus Torvaldsrx_2: movel %d1, rx_in(%d0) 5451da177e4SLinus Torvalds bra rx 5461da177e4SLinus Torvalds 5471da177e4SLinus Torvaldsrx_overrun: 5481da177e4SLinus Torvalds movel ch_status_addr(%d0), %d2 5491da177e4SLinus Torvalds addl #1, STATUS_RX_OVERRUNS(%d2) 5501da177e4SLinus Torvalds bra rx_free_bd 5511da177e4SLinus Torvalds 5521da177e4SLinus Torvaldsrx_bad_frame: 5531da177e4SLinus Torvalds movel ch_status_addr(%d0), %d2 5541da177e4SLinus Torvalds addl #1, STATUS_RX_FRAME_ERRORS(%d2) 5551da177e4SLinus Torvalds bra rx_free_bd 5561da177e4SLinus Torvalds 5571da177e4SLinus Torvaldsrx_ret: rts 5581da177e4SLinus Torvalds 5591da177e4SLinus Torvalds 5601da177e4SLinus Torvalds/****************************** packet transmitted ********************/ 5611da177e4SLinus Torvalds 5621da177e4SLinus Torvalds// Service transmit buffers // D0 = 4 * port, D6 = doorbell to host 5631da177e4SLinus Torvaldstx_end: tstl tx_count(%d0) 5641da177e4SLinus Torvalds beq tx_end_ret // TX buffers already empty 5651da177e4SLinus Torvalds 5661da177e4SLinus Torvalds movel tx_in(%d0), %d1 5671da177e4SLinus Torvalds movel %d1, %d2 // D1 = D2 = tx_in BD# = desc# 5681da177e4SLinus Torvalds lsll #3, %d1 // BD is 8-bytes long 5691da177e4SLinus Torvalds addl tx_first_bd(%d0), %d1 // D1 = current tx_in BD address 5701da177e4SLinus Torvalds movew (%d1), %d3 // D3 = TX BD flags 5711da177e4SLinus Torvalds btstl #15, %d3 5721da177e4SLinus Torvalds bne tx_end_ret // BD still being transmitted 5731da177e4SLinus Torvalds 5741da177e4SLinus Torvalds// update D6, tx_in and tx_count 5751da177e4SLinus Torvalds orl bell_tx(%d0), %d6 // signal host that TX desc freed 5761da177e4SLinus Torvalds subl #1, tx_count(%d0) 5771da177e4SLinus Torvalds movel tx_in(%d0), %d1 5781da177e4SLinus Torvalds addl #1, %d1 5791da177e4SLinus Torvalds cmpl #TX_BUFFERS, %d1 5801da177e4SLinus Torvalds bne tx_end_1 5811da177e4SLinus Torvalds clrl %d1 5821da177e4SLinus Torvaldstx_end_1: 5831da177e4SLinus Torvalds movel %d1, tx_in(%d0) 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds// free host's descriptor 5861da177e4SLinus Torvalds mulul #DESC_LENGTH, %d2 // D2 = TX desc offset 5871da177e4SLinus Torvalds addl ch_status_addr(%d0), %d2 5881da177e4SLinus Torvalds addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address 5891da177e4SLinus Torvalds btstl #1, %d3 5901da177e4SLinus Torvalds bne tx_end_underrun 5911da177e4SLinus Torvalds movel #PACKET_SENT, (%d2) 5921da177e4SLinus Torvalds bra tx_end 5931da177e4SLinus Torvalds 5941da177e4SLinus Torvaldstx_end_underrun: 5951da177e4SLinus Torvalds movel #PACKET_UNDERRUN, (%d2) 5961da177e4SLinus Torvalds bra tx_end 5971da177e4SLinus Torvalds 5981da177e4SLinus Torvaldstx_end_ret: rts 5991da177e4SLinus Torvalds 6001da177e4SLinus Torvalds 6011da177e4SLinus Torvalds/****************************** PLX PCI9060 DMA memcpy ****************/ 6021da177e4SLinus Torvalds 6031da177e4SLinus Torvalds#if QUICC_MEMCPY_USES_PLX 6041da177e4SLinus Torvalds// called with interrupts disabled 6051da177e4SLinus Torvaldsmemcpy_from_pci_run: 6061da177e4SLinus Torvalds movel %d0, -(%sp) 6071da177e4SLinus Torvalds movew %sr, -(%sp) 6081da177e4SLinus Torvaldsmemcpy_1: 6091da177e4SLinus Torvalds movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly 6101da177e4SLinus Torvalds btstl #4, %d0 // transfer done? 6111da177e4SLinus Torvalds bne memcpy_end 6121da177e4SLinus Torvalds stop #0x2200 // enable PCI9060 interrupts 6131da177e4SLinus Torvalds movew #0x2700, %sr // disable interrupts again 6141da177e4SLinus Torvalds bra memcpy_1 6151da177e4SLinus Torvalds 6161da177e4SLinus Torvaldsmemcpy_to_pci_run: 6171da177e4SLinus Torvalds movel %d0, -(%sp) 6181da177e4SLinus Torvalds movew %sr, -(%sp) 6191da177e4SLinus Torvaldsmemcpy_2: 6201da177e4SLinus Torvalds movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly 6211da177e4SLinus Torvalds btstl #12, %d0 // transfer done? 6221da177e4SLinus Torvalds bne memcpy_end 6231da177e4SLinus Torvalds stop #0x2200 // enable PCI9060 interrupts 6241da177e4SLinus Torvalds movew #0x2700, %sr // disable interrupts again 6251da177e4SLinus Torvalds bra memcpy_2 6261da177e4SLinus Torvalds 6271da177e4SLinus Torvaldsmemcpy_end: 6281da177e4SLinus Torvalds movew (%sp)+, %sr 6291da177e4SLinus Torvalds movel (%sp)+, %d0 6301da177e4SLinus Torvalds rts 6311da177e4SLinus Torvalds#endif 6321da177e4SLinus Torvalds 6331da177e4SLinus Torvalds 6341da177e4SLinus Torvalds 6351da177e4SLinus Torvalds 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds 6381da177e4SLinus Torvalds/****************************** PLX PCI9060 interrupt *****************/ 6391da177e4SLinus Torvalds 6401da177e4SLinus Torvaldspci9060_interrupt: 6411da177e4SLinus Torvalds movel %d0, -(%sp) 6421da177e4SLinus Torvalds 6431da177e4SLinus Torvalds movel PLX_DOORBELL_TO_CARD, %d0 6441da177e4SLinus Torvalds movel %d0, PLX_DOORBELL_TO_CARD // confirm all requests 6451da177e4SLinus Torvalds orl %d0, channel_stats 6461da177e4SLinus Torvalds 6471da177e4SLinus Torvalds movel #0x0909, PLX_DMA_CMD_STS // clear DMA ch #0 and #1 interrupts 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds movel (%sp)+, %d0 6501da177e4SLinus Torvalds rte 6511da177e4SLinus Torvalds 6521da177e4SLinus Torvalds/****************************** SCC interrupts ************************/ 6531da177e4SLinus Torvalds 6541da177e4SLinus Torvaldsport_interrupt_1: 6551da177e4SLinus Torvalds orl #0, SCC1_REGS + SCC_SCCE; // confirm SCC events 6561da177e4SLinus Torvalds orl #1 << TASK_SCC_0, channel_stats 6571da177e4SLinus Torvalds movel #0x40000000, CISR 6581da177e4SLinus Torvalds rte 6591da177e4SLinus Torvalds 6601da177e4SLinus Torvaldsport_interrupt_2: 6611da177e4SLinus Torvalds orl #0, SCC2_REGS + SCC_SCCE; // confirm SCC events 6621da177e4SLinus Torvalds orl #1 << TASK_SCC_1, channel_stats 6631da177e4SLinus Torvalds movel #0x20000000, CISR 6641da177e4SLinus Torvalds rte 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvaldsport_interrupt_3: 6671da177e4SLinus Torvalds orl #0, SCC3_REGS + SCC_SCCE; // confirm SCC events 6681da177e4SLinus Torvalds orl #1 << TASK_SCC_2, channel_stats 6691da177e4SLinus Torvalds movel #0x10000000, CISR 6701da177e4SLinus Torvalds rte 6711da177e4SLinus Torvalds 6721da177e4SLinus Torvaldsport_interrupt_4: 6731da177e4SLinus Torvalds orl #0, SCC4_REGS + SCC_SCCE; // confirm SCC events 6741da177e4SLinus Torvalds orl #1 << TASK_SCC_3, channel_stats 6751da177e4SLinus Torvalds movel #0x08000000, CISR 6761da177e4SLinus Torvalds rte 6771da177e4SLinus Torvalds 6781da177e4SLinus Torvaldserror_interrupt: 6791da177e4SLinus Torvalds rte 6801da177e4SLinus Torvalds 6811da177e4SLinus Torvalds 6821da177e4SLinus Torvalds/****************************** cable and PM routine ******************/ 6831da177e4SLinus Torvalds// modified registers: none 6841da177e4SLinus Torvaldscheck_csr: 6851da177e4SLinus Torvalds movel %d0, -(%sp) 6861da177e4SLinus Torvalds movel %d1, -(%sp) 6871da177e4SLinus Torvalds movel %d2, -(%sp) 6881da177e4SLinus Torvalds movel %a0, -(%sp) 6891da177e4SLinus Torvalds movel %a1, -(%sp) 6901da177e4SLinus Torvalds 6911da177e4SLinus Torvalds clrl %d0 // D0 = 4 * port 6921da177e4SLinus Torvalds movel #CSRA, %a0 // A0 = CSR address 6931da177e4SLinus Torvalds 6941da177e4SLinus Torvaldscheck_csr_loop: 6951da177e4SLinus Torvalds movew (%a0), %d1 // D1 = CSR input bits 6961da177e4SLinus Torvalds andl #0xE7, %d1 // PM and cable sense bits (no DCE bit) 6971da177e4SLinus Torvalds cmpw #STATUS_CABLE_V35 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 6981da177e4SLinus Torvalds bne check_csr_1 6991da177e4SLinus Torvalds movew #0x0E08, %d1 7001da177e4SLinus Torvalds bra check_csr_valid 7011da177e4SLinus Torvalds 7021da177e4SLinus Torvaldscheck_csr_1: 7031da177e4SLinus Torvalds cmpw #STATUS_CABLE_X21 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 7041da177e4SLinus Torvalds bne check_csr_2 7051da177e4SLinus Torvalds movew #0x0408, %d1 7061da177e4SLinus Torvalds bra check_csr_valid 7071da177e4SLinus Torvalds 7081da177e4SLinus Torvaldscheck_csr_2: 7091da177e4SLinus Torvalds cmpw #STATUS_CABLE_V24 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 7101da177e4SLinus Torvalds bne check_csr_3 7111da177e4SLinus Torvalds movew #0x0208, %d1 7121da177e4SLinus Torvalds bra check_csr_valid 7131da177e4SLinus Torvalds 7141da177e4SLinus Torvaldscheck_csr_3: 7151da177e4SLinus Torvalds cmpw #STATUS_CABLE_EIA530 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 7161da177e4SLinus Torvalds bne check_csr_disable 7171da177e4SLinus Torvalds movew #0x0D08, %d1 7181da177e4SLinus Torvalds bra check_csr_valid 7191da177e4SLinus Torvalds 7201da177e4SLinus Torvaldscheck_csr_disable: 7211da177e4SLinus Torvalds movew #0x0008, %d1 // D1 = disable everything 7221da177e4SLinus Torvalds movew #0x80E7, %d2 // D2 = input mask: ignore DSR 7231da177e4SLinus Torvalds bra check_csr_write 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvaldscheck_csr_valid: // D1 = mode and IRQ bits 7261da177e4SLinus Torvalds movew csr_output(%d0), %d2 7271da177e4SLinus Torvalds andw #0x3000, %d2 // D2 = requested LL and DTR bits 7281da177e4SLinus Torvalds orw %d2, %d1 // D1 = all requested output bits 7291da177e4SLinus Torvalds movew #0x80FF, %d2 // D2 = input mask: include DSR 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvaldscheck_csr_write: 7321da177e4SLinus Torvalds cmpw old_csr_output(%d0), %d1 7331da177e4SLinus Torvalds beq check_csr_input 7341da177e4SLinus Torvalds movew %d1, old_csr_output(%d0) 7351da177e4SLinus Torvalds movew %d1, (%a0) // Write CSR output bits 7361da177e4SLinus Torvalds 7371da177e4SLinus Torvaldscheck_csr_input: 7381da177e4SLinus Torvalds movew (PCDAT), %d1 7391da177e4SLinus Torvalds andw dcd_mask(%d0), %d1 7401da177e4SLinus Torvalds beq check_csr_dcd_on // DCD and CTS signals are negated 7411da177e4SLinus Torvalds movew (%a0), %d1 // D1 = CSR input bits 7421da177e4SLinus Torvalds andw #~STATUS_CABLE_DCD, %d1 // DCD off 7431da177e4SLinus Torvalds bra check_csr_previous 7441da177e4SLinus Torvalds 7451da177e4SLinus Torvaldscheck_csr_dcd_on: 7461da177e4SLinus Torvalds movew (%a0), %d1 // D1 = CSR input bits 7471da177e4SLinus Torvalds orw #STATUS_CABLE_DCD, %d1 // DCD on 7481da177e4SLinus Torvaldscheck_csr_previous: 7491da177e4SLinus Torvalds andw %d2, %d1 // input mask 7501da177e4SLinus Torvalds movel ch_status_addr(%d0), %a1 7511da177e4SLinus Torvalds cmpl STATUS_CABLE(%a1), %d1 // check for change 7521da177e4SLinus Torvalds beq check_csr_next 7531da177e4SLinus Torvalds movel %d1, STATUS_CABLE(%a1) // update status 7541da177e4SLinus Torvalds movel bell_cable(%d0), PLX_DOORBELL_FROM_CARD // signal the host 7551da177e4SLinus Torvalds 7561da177e4SLinus Torvaldscheck_csr_next: 7571da177e4SLinus Torvalds addl #2, %a0 // next CSR register 7581da177e4SLinus Torvalds addl #4, %d0 // D0 = 4 * next port 7591da177e4SLinus Torvalds cmpl #4 * 4, %d0 7601da177e4SLinus Torvalds bne check_csr_loop 7611da177e4SLinus Torvalds 7621da177e4SLinus Torvalds movel (%sp)+, %a1 7631da177e4SLinus Torvalds movel (%sp)+, %a0 7641da177e4SLinus Torvalds movel (%sp)+, %d2 7651da177e4SLinus Torvalds movel (%sp)+, %d1 7661da177e4SLinus Torvalds movel (%sp)+, %d0 7671da177e4SLinus Torvalds rts 7681da177e4SLinus Torvalds 7691da177e4SLinus Torvalds 7701da177e4SLinus Torvalds/****************************** timer interrupt ***********************/ 7711da177e4SLinus Torvalds 7721da177e4SLinus Torvaldstimer_interrupt: 7731da177e4SLinus Torvalds bsr check_csr 7741da177e4SLinus Torvalds rte 7751da177e4SLinus Torvalds 7761da177e4SLinus Torvalds 7771da177e4SLinus Torvalds/****************************** RAM sizing and test *******************/ 7781da177e4SLinus Torvalds#if DETECT_RAM 7791da177e4SLinus Torvaldsram_test: 7801da177e4SLinus Torvalds movel #0x12345678, %d1 // D1 = test value 7811da177e4SLinus Torvalds movel %d1, (128 * 1024 - 4) 7821da177e4SLinus Torvalds movel #128 * 1024, %d0 // D0 = RAM size tested 7831da177e4SLinus Torvaldsram_test_size: 7841da177e4SLinus Torvalds cmpl #MAX_RAM_SIZE, %d0 7851da177e4SLinus Torvalds beq ram_test_size_found 7861da177e4SLinus Torvalds movel %d0, %a0 7871da177e4SLinus Torvalds addl #128 * 1024 - 4, %a0 7881da177e4SLinus Torvalds cmpl (%a0), %d1 7891da177e4SLinus Torvalds beq ram_test_size_check 7901da177e4SLinus Torvaldsram_test_next_size: 7911da177e4SLinus Torvalds lsll #1, %d0 7921da177e4SLinus Torvalds bra ram_test_size 7931da177e4SLinus Torvalds 7941da177e4SLinus Torvaldsram_test_size_check: 7951da177e4SLinus Torvalds eorl #0xFFFFFFFF, %d1 7961da177e4SLinus Torvalds movel %d1, (128 * 1024 - 4) 7971da177e4SLinus Torvalds cmpl (%a0), %d1 7981da177e4SLinus Torvalds bne ram_test_next_size 7991da177e4SLinus Torvalds 8001da177e4SLinus Torvaldsram_test_size_found: // D0 = RAM size 8011da177e4SLinus Torvalds movel %d0, %a0 // A0 = fill ptr 8021da177e4SLinus Torvalds subl #firmware_end + 4, %d0 8031da177e4SLinus Torvalds lsrl #2, %d0 8041da177e4SLinus Torvalds movel %d0, %d1 // D1 = DBf counter 8051da177e4SLinus Torvaldsram_test_fill: 8061da177e4SLinus Torvalds movel %a0, -(%a0) 8071da177e4SLinus Torvalds dbfw %d1, ram_test_fill 8081da177e4SLinus Torvalds subl #0x10000, %d1 8091da177e4SLinus Torvalds cmpl #0xFFFFFFFF, %d1 8101da177e4SLinus Torvalds bne ram_test_fill 8111da177e4SLinus Torvalds 8121da177e4SLinus Torvaldsram_test_loop: // D0 = DBf counter 8131da177e4SLinus Torvalds cmpl (%a0)+, %a0 8141da177e4SLinus Torvalds dbnew %d0, ram_test_loop 8151da177e4SLinus Torvalds bne ram_test_found_bad 8161da177e4SLinus Torvalds subl #0x10000, %d0 8171da177e4SLinus Torvalds cmpl #0xFFFFFFFF, %d0 8181da177e4SLinus Torvalds bne ram_test_loop 8191da177e4SLinus Torvalds bra ram_test_all_ok 8201da177e4SLinus Torvalds 8211da177e4SLinus Torvaldsram_test_found_bad: 8221da177e4SLinus Torvalds subl #4, %a0 8231da177e4SLinus Torvaldsram_test_all_ok: 8241da177e4SLinus Torvalds movel %a0, PLX_MAILBOX_5 8251da177e4SLinus Torvalds rts 8261da177e4SLinus Torvalds#endif 8271da177e4SLinus Torvalds 8281da177e4SLinus Torvalds 8291da177e4SLinus Torvalds/****************************** constants *****************************/ 8301da177e4SLinus Torvalds 8311da177e4SLinus Torvaldsscc_reg_addr: 8321da177e4SLinus Torvalds .long SCC1_REGS, SCC2_REGS, SCC3_REGS, SCC4_REGS 8331da177e4SLinus Torvaldsscc_base_addr: 8341da177e4SLinus Torvalds .long SCC1_BASE, SCC2_BASE, SCC3_BASE, SCC4_BASE 8351da177e4SLinus Torvalds 8361da177e4SLinus Torvaldstx_first_bd: 8371da177e4SLinus Torvalds .long DPRBASE 8381da177e4SLinus Torvalds .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 8391da177e4SLinus Torvalds .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 2 8401da177e4SLinus Torvalds .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 3 8411da177e4SLinus Torvalds 8421da177e4SLinus Torvaldsrx_first_bd: 8431da177e4SLinus Torvalds .long DPRBASE + TX_BUFFERS * 8 8441da177e4SLinus Torvalds .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 8451da177e4SLinus Torvalds .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 2 8461da177e4SLinus Torvalds .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 3 8471da177e4SLinus Torvalds 8481da177e4SLinus Torvaldsfirst_buffer: 8491da177e4SLinus Torvalds .long BUFFERS_ADDR 8501da177e4SLinus Torvalds .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH 8511da177e4SLinus Torvalds .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 2 8521da177e4SLinus Torvalds .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 3 8531da177e4SLinus Torvalds 8541da177e4SLinus Torvaldsbell_tx: 8551da177e4SLinus Torvalds .long 1 << DOORBELL_FROM_CARD_TX_0, 1 << DOORBELL_FROM_CARD_TX_1 8561da177e4SLinus Torvalds .long 1 << DOORBELL_FROM_CARD_TX_2, 1 << DOORBELL_FROM_CARD_TX_3 8571da177e4SLinus Torvalds 8581da177e4SLinus Torvaldsbell_cable: 8591da177e4SLinus Torvalds .long 1 << DOORBELL_FROM_CARD_CABLE_0, 1 << DOORBELL_FROM_CARD_CABLE_1 8601da177e4SLinus Torvalds .long 1 << DOORBELL_FROM_CARD_CABLE_2, 1 << DOORBELL_FROM_CARD_CABLE_3 8611da177e4SLinus Torvalds 8621da177e4SLinus Torvaldspacket_full: 8631da177e4SLinus Torvalds .long PACKET_FULL, PACKET_FULL + 1, PACKET_FULL + 2, PACKET_FULL + 3 8641da177e4SLinus Torvalds 8651da177e4SLinus Torvaldsclocking_ext: 8661da177e4SLinus Torvalds .long 0x0000002C, 0x00003E00, 0x002C0000, 0x3E000000 8671da177e4SLinus Torvaldsclocking_txfromrx: 8681da177e4SLinus Torvalds .long 0x0000002D, 0x00003F00, 0x002D0000, 0x3F000000 8691da177e4SLinus Torvaldsclocking_mask: 8701da177e4SLinus Torvalds .long 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 8711da177e4SLinus Torvaldsdcd_mask: 8721da177e4SLinus Torvalds .word 0x020, 0, 0x080, 0, 0x200, 0, 0x800 8731da177e4SLinus Torvalds 8741da177e4SLinus Torvalds .ascii "wanXL firmware\n" 8751da177e4SLinus Torvalds .asciz "Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl>\n" 8761da177e4SLinus Torvalds 8771da177e4SLinus Torvalds 8781da177e4SLinus Torvalds/****************************** variables *****************************/ 8791da177e4SLinus Torvalds 8801da177e4SLinus Torvalds .align 4 8811da177e4SLinus Torvaldschannel_stats: .long 0 8821da177e4SLinus Torvalds 8831da177e4SLinus Torvaldstx_in: .long 0, 0, 0, 0 // transmitted 8841da177e4SLinus Torvaldstx_out: .long 0, 0, 0, 0 // received from host for transmission 8851da177e4SLinus Torvaldstx_count: .long 0, 0, 0, 0 // currently in transmit queue 8861da177e4SLinus Torvalds 8871da177e4SLinus Torvaldsrx_in: .long 0, 0, 0, 0 // received from port 8881da177e4SLinus Torvaldsrx_out: .long 0 // transmitted to host 8891da177e4SLinus Torvaldsparity_bytes: .word 0, 0, 0, 0, 0, 0, 0 // only 4 words are used 8901da177e4SLinus Torvalds 8911da177e4SLinus Torvaldscsr_output: .word 0 8921da177e4SLinus Torvaldsold_csr_output: .word 0, 0, 0, 0, 0, 0, 0 8931da177e4SLinus Torvalds .align 4 8941da177e4SLinus Torvaldsfirmware_end: // must be dword-aligned 895