1*1da177e4SLinus Torvalds.psize 0 2*1da177e4SLinus Torvalds/* 3*1da177e4SLinus Torvalds wanXL serial card driver for Linux 4*1da177e4SLinus Torvalds card firmware part 5*1da177e4SLinus Torvalds 6*1da177e4SLinus Torvalds Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl> 7*1da177e4SLinus Torvalds 8*1da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify it 9*1da177e4SLinus Torvalds under the terms of version 2 of the GNU General Public License 10*1da177e4SLinus Torvalds as published by the Free Software Foundation. 11*1da177e4SLinus Torvalds 12*1da177e4SLinus Torvalds 13*1da177e4SLinus Torvalds 14*1da177e4SLinus Torvalds 15*1da177e4SLinus Torvalds DPRAM BDs: 16*1da177e4SLinus Torvalds 0x000 - 0x050 TX#0 0x050 - 0x140 RX#0 17*1da177e4SLinus Torvalds 0x140 - 0x190 TX#1 0x190 - 0x280 RX#1 18*1da177e4SLinus Torvalds 0x280 - 0x2D0 TX#2 0x2D0 - 0x3C0 RX#2 19*1da177e4SLinus Torvalds 0x3C0 - 0x410 TX#3 0x410 - 0x500 RX#3 20*1da177e4SLinus Torvalds 21*1da177e4SLinus Torvalds 22*1da177e4SLinus Torvalds 000 5FF 1536 Bytes Dual-Port RAM User Data / BDs 23*1da177e4SLinus Torvalds 600 6FF 256 Bytes Dual-Port RAM User Data / BDs 24*1da177e4SLinus Torvalds 700 7FF 256 Bytes Dual-Port RAM User Data / BDs 25*1da177e4SLinus Torvalds C00 CBF 192 Bytes Dual-Port RAM Parameter RAM Page 1 26*1da177e4SLinus Torvalds D00 DBF 192 Bytes Dual-Port RAM Parameter RAM Page 2 27*1da177e4SLinus Torvalds E00 EBF 192 Bytes Dual-Port RAM Parameter RAM Page 3 28*1da177e4SLinus Torvalds F00 FBF 192 Bytes Dual-Port RAM Parameter RAM Page 4 29*1da177e4SLinus Torvalds 30*1da177e4SLinus Torvalds local interrupts level 31*1da177e4SLinus Torvalds NMI 7 32*1da177e4SLinus Torvalds PIT timer, CPM (RX/TX complete) 4 33*1da177e4SLinus Torvalds PCI9060 DMA and PCI doorbells 3 34*1da177e4SLinus Torvalds Cable - not used 1 35*1da177e4SLinus Torvalds*/ 36*1da177e4SLinus Torvalds 37*1da177e4SLinus Torvalds#include <linux/hdlc.h> 38*1da177e4SLinus Torvalds#include "wanxl.h" 39*1da177e4SLinus Torvalds 40*1da177e4SLinus Torvalds/* memory addresses and offsets */ 41*1da177e4SLinus Torvalds 42*1da177e4SLinus TorvaldsMAX_RAM_SIZE = 16 * 1024 * 1024 // max RAM supported by hardware 43*1da177e4SLinus Torvalds 44*1da177e4SLinus TorvaldsPCI9060_VECTOR = 0x0000006C 45*1da177e4SLinus TorvaldsCPM_IRQ_BASE = 0x40 46*1da177e4SLinus TorvaldsERROR_VECTOR = CPM_IRQ_BASE * 4 47*1da177e4SLinus TorvaldsSCC1_VECTOR = (CPM_IRQ_BASE + 0x1E) * 4 48*1da177e4SLinus TorvaldsSCC2_VECTOR = (CPM_IRQ_BASE + 0x1D) * 4 49*1da177e4SLinus TorvaldsSCC3_VECTOR = (CPM_IRQ_BASE + 0x1C) * 4 50*1da177e4SLinus TorvaldsSCC4_VECTOR = (CPM_IRQ_BASE + 0x1B) * 4 51*1da177e4SLinus TorvaldsCPM_IRQ_LEVEL = 4 52*1da177e4SLinus TorvaldsTIMER_IRQ = 128 53*1da177e4SLinus TorvaldsTIMER_IRQ_LEVEL = 4 54*1da177e4SLinus TorvaldsPITR_CONST = 0x100 + 16 // 1 Hz timer 55*1da177e4SLinus Torvalds 56*1da177e4SLinus TorvaldsMBAR = 0x0003FF00 57*1da177e4SLinus Torvalds 58*1da177e4SLinus TorvaldsVALUE_WINDOW = 0x40000000 59*1da177e4SLinus TorvaldsORDER_WINDOW = 0xC0000000 60*1da177e4SLinus Torvalds 61*1da177e4SLinus TorvaldsPLX = 0xFFF90000 62*1da177e4SLinus Torvalds 63*1da177e4SLinus TorvaldsCSRA = 0xFFFB0000 64*1da177e4SLinus TorvaldsCSRB = 0xFFFB0002 65*1da177e4SLinus TorvaldsCSRC = 0xFFFB0004 66*1da177e4SLinus TorvaldsCSRD = 0xFFFB0006 67*1da177e4SLinus TorvaldsSTATUS_CABLE_LL = 0x2000 68*1da177e4SLinus TorvaldsSTATUS_CABLE_DTR = 0x1000 69*1da177e4SLinus Torvalds 70*1da177e4SLinus TorvaldsDPRBASE = 0xFFFC0000 71*1da177e4SLinus Torvalds 72*1da177e4SLinus TorvaldsSCC1_BASE = DPRBASE + 0xC00 73*1da177e4SLinus TorvaldsMISC_BASE = DPRBASE + 0xCB0 74*1da177e4SLinus TorvaldsSCC2_BASE = DPRBASE + 0xD00 75*1da177e4SLinus TorvaldsSCC3_BASE = DPRBASE + 0xE00 76*1da177e4SLinus TorvaldsSCC4_BASE = DPRBASE + 0xF00 77*1da177e4SLinus Torvalds 78*1da177e4SLinus Torvalds// offset from SCCx_BASE 79*1da177e4SLinus Torvalds// SCC_xBASE contain offsets from DPRBASE and must be divisible by 8 80*1da177e4SLinus TorvaldsSCC_RBASE = 0 // 16-bit RxBD base address 81*1da177e4SLinus TorvaldsSCC_TBASE = 2 // 16-bit TxBD base address 82*1da177e4SLinus TorvaldsSCC_RFCR = 4 // 8-bit Rx function code 83*1da177e4SLinus TorvaldsSCC_TFCR = 5 // 8-bit Tx function code 84*1da177e4SLinus TorvaldsSCC_MRBLR = 6 // 16-bit maximum Rx buffer length 85*1da177e4SLinus TorvaldsSCC_C_MASK = 0x34 // 32-bit CRC constant 86*1da177e4SLinus TorvaldsSCC_C_PRES = 0x38 // 32-bit CRC preset 87*1da177e4SLinus TorvaldsSCC_MFLR = 0x46 // 16-bit max Rx frame length (without flags) 88*1da177e4SLinus Torvalds 89*1da177e4SLinus TorvaldsREGBASE = DPRBASE + 0x1000 90*1da177e4SLinus TorvaldsPICR = REGBASE + 0x026 // 16-bit periodic irq control 91*1da177e4SLinus TorvaldsPITR = REGBASE + 0x02A // 16-bit periodic irq timing 92*1da177e4SLinus TorvaldsOR1 = REGBASE + 0x064 // 32-bit RAM bank #1 options 93*1da177e4SLinus TorvaldsCICR = REGBASE + 0x540 // 32(24)-bit CP interrupt config 94*1da177e4SLinus TorvaldsCIMR = REGBASE + 0x548 // 32-bit CP interrupt mask 95*1da177e4SLinus TorvaldsCISR = REGBASE + 0x54C // 32-bit CP interrupts in-service 96*1da177e4SLinus TorvaldsPADIR = REGBASE + 0x550 // 16-bit PortA data direction bitmap 97*1da177e4SLinus TorvaldsPAPAR = REGBASE + 0x552 // 16-bit PortA pin assignment bitmap 98*1da177e4SLinus TorvaldsPAODR = REGBASE + 0x554 // 16-bit PortA open drain bitmap 99*1da177e4SLinus TorvaldsPADAT = REGBASE + 0x556 // 16-bit PortA data register 100*1da177e4SLinus Torvalds 101*1da177e4SLinus TorvaldsPCDIR = REGBASE + 0x560 // 16-bit PortC data direction bitmap 102*1da177e4SLinus TorvaldsPCPAR = REGBASE + 0x562 // 16-bit PortC pin assignment bitmap 103*1da177e4SLinus TorvaldsPCSO = REGBASE + 0x564 // 16-bit PortC special options 104*1da177e4SLinus TorvaldsPCDAT = REGBASE + 0x566 // 16-bit PortC data register 105*1da177e4SLinus TorvaldsPCINT = REGBASE + 0x568 // 16-bit PortC interrupt control 106*1da177e4SLinus TorvaldsCR = REGBASE + 0x5C0 // 16-bit Command register 107*1da177e4SLinus Torvalds 108*1da177e4SLinus TorvaldsSCC1_REGS = REGBASE + 0x600 109*1da177e4SLinus TorvaldsSCC2_REGS = REGBASE + 0x620 110*1da177e4SLinus TorvaldsSCC3_REGS = REGBASE + 0x640 111*1da177e4SLinus TorvaldsSCC4_REGS = REGBASE + 0x660 112*1da177e4SLinus TorvaldsSICR = REGBASE + 0x6EC // 32-bit SI clock route 113*1da177e4SLinus Torvalds 114*1da177e4SLinus Torvalds// offset from SCCx_REGS 115*1da177e4SLinus TorvaldsSCC_GSMR_L = 0x00 // 32 bits 116*1da177e4SLinus TorvaldsSCC_GSMR_H = 0x04 // 32 bits 117*1da177e4SLinus TorvaldsSCC_PSMR = 0x08 // 16 bits 118*1da177e4SLinus TorvaldsSCC_TODR = 0x0C // 16 bits 119*1da177e4SLinus TorvaldsSCC_DSR = 0x0E // 16 bits 120*1da177e4SLinus TorvaldsSCC_SCCE = 0x10 // 16 bits 121*1da177e4SLinus TorvaldsSCC_SCCM = 0x14 // 16 bits 122*1da177e4SLinus TorvaldsSCC_SCCS = 0x17 // 8 bits 123*1da177e4SLinus Torvalds 124*1da177e4SLinus Torvalds#if QUICC_MEMCPY_USES_PLX 125*1da177e4SLinus Torvalds .macro memcpy_from_pci src, dest, len // len must be < 8 MB 126*1da177e4SLinus Torvalds addl #3, \len 127*1da177e4SLinus Torvalds andl #0xFFFFFFFC, \len // always copy n * 4 bytes 128*1da177e4SLinus Torvalds movel \src, PLX_DMA_0_PCI 129*1da177e4SLinus Torvalds movel \dest, PLX_DMA_0_LOCAL 130*1da177e4SLinus Torvalds movel \len, PLX_DMA_0_LENGTH 131*1da177e4SLinus Torvalds movel #0x0103, PLX_DMA_CMD_STS // start channel 0 transfer 132*1da177e4SLinus Torvalds bsr memcpy_from_pci_run 133*1da177e4SLinus Torvalds .endm 134*1da177e4SLinus Torvalds 135*1da177e4SLinus Torvalds .macro memcpy_to_pci src, dest, len 136*1da177e4SLinus Torvalds addl #3, \len 137*1da177e4SLinus Torvalds andl #0xFFFFFFFC, \len // always copy n * 4 bytes 138*1da177e4SLinus Torvalds movel \src, PLX_DMA_1_LOCAL 139*1da177e4SLinus Torvalds movel \dest, PLX_DMA_1_PCI 140*1da177e4SLinus Torvalds movel \len, PLX_DMA_1_LENGTH 141*1da177e4SLinus Torvalds movel #0x0301, PLX_DMA_CMD_STS // start channel 1 transfer 142*1da177e4SLinus Torvalds bsr memcpy_to_pci_run 143*1da177e4SLinus Torvalds .endm 144*1da177e4SLinus Torvalds 145*1da177e4SLinus Torvalds#else 146*1da177e4SLinus Torvalds 147*1da177e4SLinus Torvalds .macro memcpy src, dest, len // len must be < 65536 bytes 148*1da177e4SLinus Torvalds movel %d7, -(%sp) // src and dest must be < 256 MB 149*1da177e4SLinus Torvalds movel \len, %d7 // bits 0 and 1 150*1da177e4SLinus Torvalds lsrl #2, \len 151*1da177e4SLinus Torvalds andl \len, \len 152*1da177e4SLinus Torvalds beq 99f // only 0 - 3 bytes 153*1da177e4SLinus Torvalds subl #1, \len // for dbf 154*1da177e4SLinus Torvalds98: movel (\src)+, (\dest)+ 155*1da177e4SLinus Torvalds dbfw \len, 98b 156*1da177e4SLinus Torvalds99: movel %d7, \len 157*1da177e4SLinus Torvalds btstl #1, \len 158*1da177e4SLinus Torvalds beq 99f 159*1da177e4SLinus Torvalds movew (\src)+, (\dest)+ 160*1da177e4SLinus Torvalds99: btstl #0, \len 161*1da177e4SLinus Torvalds beq 99f 162*1da177e4SLinus Torvalds moveb (\src)+, (\dest)+ 163*1da177e4SLinus Torvalds99: 164*1da177e4SLinus Torvalds movel (%sp)+, %d7 165*1da177e4SLinus Torvalds .endm 166*1da177e4SLinus Torvalds 167*1da177e4SLinus Torvalds .macro memcpy_from_pci src, dest, len 168*1da177e4SLinus Torvalds addl #VALUE_WINDOW, \src 169*1da177e4SLinus Torvalds memcpy \src, \dest, \len 170*1da177e4SLinus Torvalds .endm 171*1da177e4SLinus Torvalds 172*1da177e4SLinus Torvalds .macro memcpy_to_pci src, dest, len 173*1da177e4SLinus Torvalds addl #VALUE_WINDOW, \dest 174*1da177e4SLinus Torvalds memcpy \src, \dest, \len 175*1da177e4SLinus Torvalds .endm 176*1da177e4SLinus Torvalds#endif 177*1da177e4SLinus Torvalds 178*1da177e4SLinus Torvalds 179*1da177e4SLinus Torvalds .macro wait_for_command 180*1da177e4SLinus Torvalds99: btstl #0, CR 181*1da177e4SLinus Torvalds bne 99b 182*1da177e4SLinus Torvalds .endm 183*1da177e4SLinus Torvalds 184*1da177e4SLinus Torvalds 185*1da177e4SLinus Torvalds 186*1da177e4SLinus Torvalds 187*1da177e4SLinus Torvalds/****************************** card initialization *******************/ 188*1da177e4SLinus Torvalds .text 189*1da177e4SLinus Torvalds .global _start 190*1da177e4SLinus Torvalds_start: bra init 191*1da177e4SLinus Torvalds 192*1da177e4SLinus Torvalds .org _start + 4 193*1da177e4SLinus Torvaldsch_status_addr: .long 0, 0, 0, 0 194*1da177e4SLinus Torvaldsrx_descs_addr: .long 0 195*1da177e4SLinus Torvalds 196*1da177e4SLinus Torvaldsinit: 197*1da177e4SLinus Torvalds#if DETECT_RAM 198*1da177e4SLinus Torvalds movel OR1, %d0 199*1da177e4SLinus Torvalds andl #0xF00007FF, %d0 // mask AMxx bits 200*1da177e4SLinus Torvalds orl #0xFFFF800 & ~(MAX_RAM_SIZE - 1), %d0 // update RAM bank size 201*1da177e4SLinus Torvalds movel %d0, OR1 202*1da177e4SLinus Torvalds#endif 203*1da177e4SLinus Torvalds 204*1da177e4SLinus Torvalds addl #VALUE_WINDOW, rx_descs_addr // PCI addresses of shared data 205*1da177e4SLinus Torvalds clrl %d0 // D0 = 4 * port 206*1da177e4SLinus Torvaldsinit_1: tstl ch_status_addr(%d0) 207*1da177e4SLinus Torvalds beq init_2 208*1da177e4SLinus Torvalds addl #VALUE_WINDOW, ch_status_addr(%d0) 209*1da177e4SLinus Torvaldsinit_2: addl #4, %d0 210*1da177e4SLinus Torvalds cmpl #4 * 4, %d0 211*1da177e4SLinus Torvalds bne init_1 212*1da177e4SLinus Torvalds 213*1da177e4SLinus Torvalds movel #pci9060_interrupt, PCI9060_VECTOR 214*1da177e4SLinus Torvalds movel #error_interrupt, ERROR_VECTOR 215*1da177e4SLinus Torvalds movel #port_interrupt_1, SCC1_VECTOR 216*1da177e4SLinus Torvalds movel #port_interrupt_2, SCC2_VECTOR 217*1da177e4SLinus Torvalds movel #port_interrupt_3, SCC3_VECTOR 218*1da177e4SLinus Torvalds movel #port_interrupt_4, SCC4_VECTOR 219*1da177e4SLinus Torvalds movel #timer_interrupt, TIMER_IRQ * 4 220*1da177e4SLinus Torvalds 221*1da177e4SLinus Torvalds movel #0x78000000, CIMR // only SCCx IRQs from CPM 222*1da177e4SLinus Torvalds movew #(TIMER_IRQ_LEVEL << 8) + TIMER_IRQ, PICR // interrupt from PIT 223*1da177e4SLinus Torvalds movew #PITR_CONST, PITR 224*1da177e4SLinus Torvalds 225*1da177e4SLinus Torvalds // SCC1=SCCa SCC2=SCCb SCC3=SCCc SCC4=SCCd prio=4 HP=-1 IRQ=64-79 226*1da177e4SLinus Torvalds movel #0xD41F40 + (CPM_IRQ_LEVEL << 13), CICR 227*1da177e4SLinus Torvalds movel #0x543, PLX_DMA_0_MODE // 32-bit, Ready, Burst, IRQ 228*1da177e4SLinus Torvalds movel #0x543, PLX_DMA_1_MODE 229*1da177e4SLinus Torvalds movel #0x0, PLX_DMA_0_DESC // from PCI to local 230*1da177e4SLinus Torvalds movel #0x8, PLX_DMA_1_DESC // from local to PCI 231*1da177e4SLinus Torvalds movel #0x101, PLX_DMA_CMD_STS // enable both DMA channels 232*1da177e4SLinus Torvalds // enable local IRQ, DMA, doorbells and PCI IRQ 233*1da177e4SLinus Torvalds orl #0x000F0300, PLX_INTERRUPT_CS 234*1da177e4SLinus Torvalds 235*1da177e4SLinus Torvalds#if DETECT_RAM 236*1da177e4SLinus Torvalds bsr ram_test 237*1da177e4SLinus Torvalds#else 238*1da177e4SLinus Torvalds movel #1, PLX_MAILBOX_5 // non-zero value = init complete 239*1da177e4SLinus Torvalds#endif 240*1da177e4SLinus Torvalds bsr check_csr 241*1da177e4SLinus Torvalds 242*1da177e4SLinus Torvalds movew #0xFFFF, PAPAR // all pins are clocks/data 243*1da177e4SLinus Torvalds clrw PADIR // first function 244*1da177e4SLinus Torvalds clrw PCSO // CD and CTS always active 245*1da177e4SLinus Torvalds 246*1da177e4SLinus Torvalds 247*1da177e4SLinus Torvalds/****************************** main loop *****************************/ 248*1da177e4SLinus Torvalds 249*1da177e4SLinus Torvaldsmain: movel channel_stats, %d7 // D7 = doorbell + irq status 250*1da177e4SLinus Torvalds clrl channel_stats 251*1da177e4SLinus Torvalds 252*1da177e4SLinus Torvalds tstl %d7 253*1da177e4SLinus Torvalds bne main_1 254*1da177e4SLinus Torvalds // nothing to do - wait for next event 255*1da177e4SLinus Torvalds stop #0x2200 // supervisor + IRQ level 2 256*1da177e4SLinus Torvalds movew #0x2700, %sr // disable IRQs again 257*1da177e4SLinus Torvalds bra main 258*1da177e4SLinus Torvalds 259*1da177e4SLinus Torvaldsmain_1: clrl %d0 // D0 = 4 * port 260*1da177e4SLinus Torvalds clrl %d6 // D6 = doorbell to host value 261*1da177e4SLinus Torvalds 262*1da177e4SLinus Torvaldsmain_l: btstl #DOORBELL_TO_CARD_CLOSE_0, %d7 263*1da177e4SLinus Torvalds beq main_op 264*1da177e4SLinus Torvalds bclrl #DOORBELL_TO_CARD_OPEN_0, %d7 // in case both bits are set 265*1da177e4SLinus Torvalds bsr close_port 266*1da177e4SLinus Torvaldsmain_op: 267*1da177e4SLinus Torvalds btstl #DOORBELL_TO_CARD_OPEN_0, %d7 268*1da177e4SLinus Torvalds beq main_cl 269*1da177e4SLinus Torvalds bsr open_port 270*1da177e4SLinus Torvaldsmain_cl: 271*1da177e4SLinus Torvalds btstl #DOORBELL_TO_CARD_TX_0, %d7 272*1da177e4SLinus Torvalds beq main_txend 273*1da177e4SLinus Torvalds bsr tx 274*1da177e4SLinus Torvaldsmain_txend: 275*1da177e4SLinus Torvalds btstl #TASK_SCC_0, %d7 276*1da177e4SLinus Torvalds beq main_next 277*1da177e4SLinus Torvalds bsr tx_end 278*1da177e4SLinus Torvalds bsr rx 279*1da177e4SLinus Torvalds 280*1da177e4SLinus Torvaldsmain_next: 281*1da177e4SLinus Torvalds lsrl #1, %d7 // port status for next port 282*1da177e4SLinus Torvalds addl #4, %d0 // D0 = 4 * next port 283*1da177e4SLinus Torvalds cmpl #4 * 4, %d0 284*1da177e4SLinus Torvalds bne main_l 285*1da177e4SLinus Torvalds movel %d6, PLX_DOORBELL_FROM_CARD // signal the host 286*1da177e4SLinus Torvalds bra main 287*1da177e4SLinus Torvalds 288*1da177e4SLinus Torvalds 289*1da177e4SLinus Torvalds/****************************** open port *****************************/ 290*1da177e4SLinus Torvalds 291*1da177e4SLinus Torvaldsopen_port: // D0 = 4 * port, D6 = doorbell to host 292*1da177e4SLinus Torvalds movel ch_status_addr(%d0), %a0 // A0 = port status address 293*1da177e4SLinus Torvalds tstl STATUS_OPEN(%a0) 294*1da177e4SLinus Torvalds bne open_port_ret // port already open 295*1da177e4SLinus Torvalds movel #1, STATUS_OPEN(%a0) // confirm the port is open 296*1da177e4SLinus Torvalds// setup BDs 297*1da177e4SLinus Torvalds clrl tx_in(%d0) 298*1da177e4SLinus Torvalds clrl tx_out(%d0) 299*1da177e4SLinus Torvalds clrl tx_count(%d0) 300*1da177e4SLinus Torvalds clrl rx_in(%d0) 301*1da177e4SLinus Torvalds 302*1da177e4SLinus Torvalds movel SICR, %d1 // D1 = clock settings in SICR 303*1da177e4SLinus Torvalds andl clocking_mask(%d0), %d1 304*1da177e4SLinus Torvalds cmpl #CLOCK_TXFROMRX, STATUS_CLOCKING(%a0) 305*1da177e4SLinus Torvalds bne open_port_clock_ext 306*1da177e4SLinus Torvalds orl clocking_txfromrx(%d0), %d1 307*1da177e4SLinus Torvalds bra open_port_set_clock 308*1da177e4SLinus Torvalds 309*1da177e4SLinus Torvaldsopen_port_clock_ext: 310*1da177e4SLinus Torvalds orl clocking_ext(%d0), %d1 311*1da177e4SLinus Torvaldsopen_port_set_clock: 312*1da177e4SLinus Torvalds movel %d1, SICR // update clock settings in SICR 313*1da177e4SLinus Torvalds 314*1da177e4SLinus Torvalds orw #STATUS_CABLE_DTR, csr_output(%d0) // DTR on 315*1da177e4SLinus Torvalds bsr check_csr // call with disabled timer interrupt 316*1da177e4SLinus Torvalds 317*1da177e4SLinus Torvalds// Setup TX descriptors 318*1da177e4SLinus Torvalds movel first_buffer(%d0), %d1 // D1 = starting buffer address 319*1da177e4SLinus Torvalds movel tx_first_bd(%d0), %a1 // A1 = starting TX BD address 320*1da177e4SLinus Torvalds movel #TX_BUFFERS - 2, %d2 // D2 = TX_BUFFERS - 1 counter 321*1da177e4SLinus Torvalds movel #0x18000000, %d3 // D3 = initial TX BD flags: Int + Last 322*1da177e4SLinus Torvalds cmpl #PARITY_NONE, STATUS_PARITY(%a0) 323*1da177e4SLinus Torvalds beq open_port_tx_loop 324*1da177e4SLinus Torvalds bsetl #26, %d3 // TX BD flag: Transmit CRC 325*1da177e4SLinus Torvaldsopen_port_tx_loop: 326*1da177e4SLinus Torvalds movel %d3, (%a1)+ // TX flags + length 327*1da177e4SLinus Torvalds movel %d1, (%a1)+ // buffer address 328*1da177e4SLinus Torvalds addl #BUFFER_LENGTH, %d1 329*1da177e4SLinus Torvalds dbfw %d2, open_port_tx_loop 330*1da177e4SLinus Torvalds 331*1da177e4SLinus Torvalds bsetl #29, %d3 // TX BD flag: Wrap (last BD) 332*1da177e4SLinus Torvalds movel %d3, (%a1)+ // Final TX flags + length 333*1da177e4SLinus Torvalds movel %d1, (%a1)+ // buffer address 334*1da177e4SLinus Torvalds 335*1da177e4SLinus Torvalds// Setup RX descriptors // A1 = starting RX BD address 336*1da177e4SLinus Torvalds movel #RX_BUFFERS - 2, %d2 // D2 = RX_BUFFERS - 1 counter 337*1da177e4SLinus Torvaldsopen_port_rx_loop: 338*1da177e4SLinus Torvalds movel #0x90000000, (%a1)+ // RX flags + length 339*1da177e4SLinus Torvalds movel %d1, (%a1)+ // buffer address 340*1da177e4SLinus Torvalds addl #BUFFER_LENGTH, %d1 341*1da177e4SLinus Torvalds dbfw %d2, open_port_rx_loop 342*1da177e4SLinus Torvalds 343*1da177e4SLinus Torvalds movel #0xB0000000, (%a1)+ // Final RX flags + length 344*1da177e4SLinus Torvalds movel %d1, (%a1)+ // buffer address 345*1da177e4SLinus Torvalds 346*1da177e4SLinus Torvalds// Setup port parameters 347*1da177e4SLinus Torvalds movel scc_base_addr(%d0), %a1 // A1 = SCC_BASE address 348*1da177e4SLinus Torvalds movel scc_reg_addr(%d0), %a2 // A2 = SCC_REGS address 349*1da177e4SLinus Torvalds 350*1da177e4SLinus Torvalds movel #0xFFFF, SCC_SCCE(%a2) // clear status bits 351*1da177e4SLinus Torvalds movel #0x0000, SCC_SCCM(%a2) // interrupt mask 352*1da177e4SLinus Torvalds 353*1da177e4SLinus Torvalds movel tx_first_bd(%d0), %d1 354*1da177e4SLinus Torvalds movew %d1, SCC_TBASE(%a1) // D1 = offset of first TxBD 355*1da177e4SLinus Torvalds addl #TX_BUFFERS * 8, %d1 356*1da177e4SLinus Torvalds movew %d1, SCC_RBASE(%a1) // D1 = offset of first RxBD 357*1da177e4SLinus Torvalds moveb #0x8, SCC_RFCR(%a1) // Intel mode, 1000 358*1da177e4SLinus Torvalds moveb #0x8, SCC_TFCR(%a1) 359*1da177e4SLinus Torvalds 360*1da177e4SLinus Torvalds// Parity settings 361*1da177e4SLinus Torvalds cmpl #PARITY_CRC16_PR1_CCITT, STATUS_PARITY(%a0) 362*1da177e4SLinus Torvalds bne open_port_parity_1 363*1da177e4SLinus Torvalds clrw SCC_PSMR(%a2) // CRC16-CCITT 364*1da177e4SLinus Torvalds movel #0xF0B8, SCC_C_MASK(%a1) 365*1da177e4SLinus Torvalds movel #0xFFFF, SCC_C_PRES(%a1) 366*1da177e4SLinus Torvalds movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC 367*1da177e4SLinus Torvalds movew #2, parity_bytes(%d0) 368*1da177e4SLinus Torvalds bra open_port_2 369*1da177e4SLinus Torvalds 370*1da177e4SLinus Torvaldsopen_port_parity_1: 371*1da177e4SLinus Torvalds cmpl #PARITY_CRC32_PR1_CCITT, STATUS_PARITY(%a0) 372*1da177e4SLinus Torvalds bne open_port_parity_2 373*1da177e4SLinus Torvalds movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT 374*1da177e4SLinus Torvalds movel #0xDEBB20E3, SCC_C_MASK(%a1) 375*1da177e4SLinus Torvalds movel #0xFFFFFFFF, SCC_C_PRES(%a1) 376*1da177e4SLinus Torvalds movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC 377*1da177e4SLinus Torvalds movew #4, parity_bytes(%d0) 378*1da177e4SLinus Torvalds bra open_port_2 379*1da177e4SLinus Torvalds 380*1da177e4SLinus Torvaldsopen_port_parity_2: 381*1da177e4SLinus Torvalds cmpl #PARITY_CRC16_PR0_CCITT, STATUS_PARITY(%a0) 382*1da177e4SLinus Torvalds bne open_port_parity_3 383*1da177e4SLinus Torvalds clrw SCC_PSMR(%a2) // CRC16-CCITT preset 0 384*1da177e4SLinus Torvalds movel #0xF0B8, SCC_C_MASK(%a1) 385*1da177e4SLinus Torvalds clrl SCC_C_PRES(%a1) 386*1da177e4SLinus Torvalds movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC 387*1da177e4SLinus Torvalds movew #2, parity_bytes(%d0) 388*1da177e4SLinus Torvalds bra open_port_2 389*1da177e4SLinus Torvalds 390*1da177e4SLinus Torvaldsopen_port_parity_3: 391*1da177e4SLinus Torvalds cmpl #PARITY_CRC32_PR0_CCITT, STATUS_PARITY(%a0) 392*1da177e4SLinus Torvalds bne open_port_parity_4 393*1da177e4SLinus Torvalds movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT preset 0 394*1da177e4SLinus Torvalds movel #0xDEBB20E3, SCC_C_MASK(%a1) 395*1da177e4SLinus Torvalds clrl SCC_C_PRES(%a1) 396*1da177e4SLinus Torvalds movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC 397*1da177e4SLinus Torvalds movew #4, parity_bytes(%d0) 398*1da177e4SLinus Torvalds bra open_port_2 399*1da177e4SLinus Torvalds 400*1da177e4SLinus Torvaldsopen_port_parity_4: 401*1da177e4SLinus Torvalds clrw SCC_PSMR(%a2) // no parity 402*1da177e4SLinus Torvalds movel #0xF0B8, SCC_C_MASK(%a1) 403*1da177e4SLinus Torvalds movel #0xFFFF, SCC_C_PRES(%a1) 404*1da177e4SLinus Torvalds movew #HDLC_MAX_MRU, SCC_MFLR(%a1) // 0 bytes for CRC 405*1da177e4SLinus Torvalds clrw parity_bytes(%d0) 406*1da177e4SLinus Torvalds 407*1da177e4SLinus Torvaldsopen_port_2: 408*1da177e4SLinus Torvalds movel #0x00000003, SCC_GSMR_H(%a2) // RTSM 409*1da177e4SLinus Torvalds cmpl #ENCODING_NRZI, STATUS_ENCODING(%a0) 410*1da177e4SLinus Torvalds bne open_port_nrz 411*1da177e4SLinus Torvalds movel #0x10040900, SCC_GSMR_L(%a2) // NRZI: TCI Tend RECN+TENC=1 412*1da177e4SLinus Torvalds bra open_port_3 413*1da177e4SLinus Torvalds 414*1da177e4SLinus Torvaldsopen_port_nrz: 415*1da177e4SLinus Torvalds movel #0x10040000, SCC_GSMR_L(%a2) // NRZ: TCI Tend RECN+TENC=0 416*1da177e4SLinus Torvaldsopen_port_3: 417*1da177e4SLinus Torvalds movew #BUFFER_LENGTH, SCC_MRBLR(%a1) 418*1da177e4SLinus Torvalds movel %d0, %d1 419*1da177e4SLinus Torvalds lsll #4, %d1 // D1 bits 7 and 6 = port 420*1da177e4SLinus Torvalds orl #1, %d1 421*1da177e4SLinus Torvalds movew %d1, CR // Init SCC RX and TX params 422*1da177e4SLinus Torvalds wait_for_command 423*1da177e4SLinus Torvalds 424*1da177e4SLinus Torvalds // TCI Tend ENR ENT 425*1da177e4SLinus Torvalds movew #0x001F, SCC_SCCM(%a2) // TXE RXF BSY TXB RXB interrupts 426*1da177e4SLinus Torvalds orl #0x00000030, SCC_GSMR_L(%a2) // enable SCC 427*1da177e4SLinus Torvaldsopen_port_ret: 428*1da177e4SLinus Torvalds rts 429*1da177e4SLinus Torvalds 430*1da177e4SLinus Torvalds 431*1da177e4SLinus Torvalds/****************************** close port ****************************/ 432*1da177e4SLinus Torvalds 433*1da177e4SLinus Torvaldsclose_port: // D0 = 4 * port, D6 = doorbell to host 434*1da177e4SLinus Torvalds movel scc_reg_addr(%d0), %a0 // A0 = SCC_REGS address 435*1da177e4SLinus Torvalds clrw SCC_SCCM(%a0) // no SCC interrupts 436*1da177e4SLinus Torvalds andl #0xFFFFFFCF, SCC_GSMR_L(%a0) // Disable ENT and ENR 437*1da177e4SLinus Torvalds 438*1da177e4SLinus Torvalds andw #~STATUS_CABLE_DTR, csr_output(%d0) // DTR off 439*1da177e4SLinus Torvalds bsr check_csr // call with disabled timer interrupt 440*1da177e4SLinus Torvalds 441*1da177e4SLinus Torvalds movel ch_status_addr(%d0), %d1 442*1da177e4SLinus Torvalds clrl STATUS_OPEN(%d1) // confirm the port is closed 443*1da177e4SLinus Torvalds rts 444*1da177e4SLinus Torvalds 445*1da177e4SLinus Torvalds 446*1da177e4SLinus Torvalds/****************************** transmit packet ***********************/ 447*1da177e4SLinus Torvalds// queue packets for transmission 448*1da177e4SLinus Torvaldstx: // D0 = 4 * port, D6 = doorbell to host 449*1da177e4SLinus Torvalds cmpl #TX_BUFFERS, tx_count(%d0) 450*1da177e4SLinus Torvalds beq tx_ret // all DB's = descs in use 451*1da177e4SLinus Torvalds 452*1da177e4SLinus Torvalds movel tx_out(%d0), %d1 453*1da177e4SLinus Torvalds movel %d1, %d2 // D1 = D2 = tx_out BD# = desc# 454*1da177e4SLinus Torvalds mulul #DESC_LENGTH, %d2 // D2 = TX desc offset 455*1da177e4SLinus Torvalds addl ch_status_addr(%d0), %d2 456*1da177e4SLinus Torvalds addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address 457*1da177e4SLinus Torvalds cmpl #PACKET_FULL, (%d2) // desc status 458*1da177e4SLinus Torvalds bne tx_ret 459*1da177e4SLinus Torvalds 460*1da177e4SLinus Torvalds// queue it 461*1da177e4SLinus Torvalds movel 4(%d2), %a0 // PCI address 462*1da177e4SLinus Torvalds lsll #3, %d1 // BD is 8-bytes long 463*1da177e4SLinus Torvalds addl tx_first_bd(%d0), %d1 // D1 = current tx_out BD addr 464*1da177e4SLinus Torvalds 465*1da177e4SLinus Torvalds movel 4(%d1), %a1 // A1 = dest address 466*1da177e4SLinus Torvalds movel 8(%d2), %d2 // D2 = length 467*1da177e4SLinus Torvalds movew %d2, 2(%d1) // length into BD 468*1da177e4SLinus Torvalds memcpy_from_pci %a0, %a1, %d2 469*1da177e4SLinus Torvalds bsetl #31, (%d1) // CP go ahead 470*1da177e4SLinus Torvalds 471*1da177e4SLinus Torvalds// update tx_out and tx_count 472*1da177e4SLinus Torvalds movel tx_out(%d0), %d1 473*1da177e4SLinus Torvalds addl #1, %d1 474*1da177e4SLinus Torvalds cmpl #TX_BUFFERS, %d1 475*1da177e4SLinus Torvalds bne tx_1 476*1da177e4SLinus Torvalds clrl %d1 477*1da177e4SLinus Torvaldstx_1: movel %d1, tx_out(%d0) 478*1da177e4SLinus Torvalds 479*1da177e4SLinus Torvalds addl #1, tx_count(%d0) 480*1da177e4SLinus Torvalds bra tx 481*1da177e4SLinus Torvalds 482*1da177e4SLinus Torvaldstx_ret: rts 483*1da177e4SLinus Torvalds 484*1da177e4SLinus Torvalds 485*1da177e4SLinus Torvalds/****************************** packet received ***********************/ 486*1da177e4SLinus Torvalds 487*1da177e4SLinus Torvalds// Service receive buffers // D0 = 4 * port, D6 = doorbell to host 488*1da177e4SLinus Torvaldsrx: movel rx_in(%d0), %d1 // D1 = rx_in BD# 489*1da177e4SLinus Torvalds lsll #3, %d1 // BD is 8-bytes long 490*1da177e4SLinus Torvalds addl rx_first_bd(%d0), %d1 // D1 = current rx_in BD address 491*1da177e4SLinus Torvalds movew (%d1), %d2 // D2 = RX BD flags 492*1da177e4SLinus Torvalds btstl #15, %d2 493*1da177e4SLinus Torvalds bne rx_ret // BD still empty 494*1da177e4SLinus Torvalds 495*1da177e4SLinus Torvalds btstl #1, %d2 496*1da177e4SLinus Torvalds bne rx_overrun 497*1da177e4SLinus Torvalds 498*1da177e4SLinus Torvalds tstw parity_bytes(%d0) 499*1da177e4SLinus Torvalds bne rx_parity 500*1da177e4SLinus Torvalds bclrl #2, %d2 // do not test for CRC errors 501*1da177e4SLinus Torvaldsrx_parity: 502*1da177e4SLinus Torvalds andw #0x0CBC, %d2 // mask status bits 503*1da177e4SLinus Torvalds cmpw #0x0C00, %d2 // correct frame 504*1da177e4SLinus Torvalds bne rx_bad_frame 505*1da177e4SLinus Torvalds clrl %d3 506*1da177e4SLinus Torvalds movew 2(%d1), %d3 507*1da177e4SLinus Torvalds subw parity_bytes(%d0), %d3 // D3 = packet length 508*1da177e4SLinus Torvalds cmpw #HDLC_MAX_MRU, %d3 509*1da177e4SLinus Torvalds bgt rx_bad_frame 510*1da177e4SLinus Torvalds 511*1da177e4SLinus Torvaldsrx_good_frame: 512*1da177e4SLinus Torvalds movel rx_out, %d2 513*1da177e4SLinus Torvalds mulul #DESC_LENGTH, %d2 514*1da177e4SLinus Torvalds addl rx_descs_addr, %d2 // D2 = RX desc address 515*1da177e4SLinus Torvalds cmpl #PACKET_EMPTY, (%d2) // desc stat 516*1da177e4SLinus Torvalds bne rx_overrun 517*1da177e4SLinus Torvalds 518*1da177e4SLinus Torvalds movel %d3, 8(%d2) 519*1da177e4SLinus Torvalds movel 4(%d1), %a0 // A0 = source address 520*1da177e4SLinus Torvalds movel 4(%d2), %a1 521*1da177e4SLinus Torvalds tstl %a1 522*1da177e4SLinus Torvalds beq rx_ignore_data 523*1da177e4SLinus Torvalds memcpy_to_pci %a0, %a1, %d3 524*1da177e4SLinus Torvaldsrx_ignore_data: 525*1da177e4SLinus Torvalds movel packet_full(%d0), (%d2) // update desc stat 526*1da177e4SLinus Torvalds 527*1da177e4SLinus Torvalds// update D6 and rx_out 528*1da177e4SLinus Torvalds bsetl #DOORBELL_FROM_CARD_RX, %d6 // signal host that RX completed 529*1da177e4SLinus Torvalds movel rx_out, %d2 530*1da177e4SLinus Torvalds addl #1, %d2 531*1da177e4SLinus Torvalds cmpl #RX_QUEUE_LENGTH, %d2 532*1da177e4SLinus Torvalds bne rx_1 533*1da177e4SLinus Torvalds clrl %d2 534*1da177e4SLinus Torvaldsrx_1: movel %d2, rx_out 535*1da177e4SLinus Torvalds 536*1da177e4SLinus Torvaldsrx_free_bd: 537*1da177e4SLinus Torvalds andw #0xF000, (%d1) // clear CM and error bits 538*1da177e4SLinus Torvalds bsetl #31, (%d1) // free BD 539*1da177e4SLinus Torvalds// update rx_in 540*1da177e4SLinus Torvalds movel rx_in(%d0), %d1 541*1da177e4SLinus Torvalds addl #1, %d1 542*1da177e4SLinus Torvalds cmpl #RX_BUFFERS, %d1 543*1da177e4SLinus Torvalds bne rx_2 544*1da177e4SLinus Torvalds clrl %d1 545*1da177e4SLinus Torvaldsrx_2: movel %d1, rx_in(%d0) 546*1da177e4SLinus Torvalds bra rx 547*1da177e4SLinus Torvalds 548*1da177e4SLinus Torvaldsrx_overrun: 549*1da177e4SLinus Torvalds movel ch_status_addr(%d0), %d2 550*1da177e4SLinus Torvalds addl #1, STATUS_RX_OVERRUNS(%d2) 551*1da177e4SLinus Torvalds bra rx_free_bd 552*1da177e4SLinus Torvalds 553*1da177e4SLinus Torvaldsrx_bad_frame: 554*1da177e4SLinus Torvalds movel ch_status_addr(%d0), %d2 555*1da177e4SLinus Torvalds addl #1, STATUS_RX_FRAME_ERRORS(%d2) 556*1da177e4SLinus Torvalds bra rx_free_bd 557*1da177e4SLinus Torvalds 558*1da177e4SLinus Torvaldsrx_ret: rts 559*1da177e4SLinus Torvalds 560*1da177e4SLinus Torvalds 561*1da177e4SLinus Torvalds/****************************** packet transmitted ********************/ 562*1da177e4SLinus Torvalds 563*1da177e4SLinus Torvalds// Service transmit buffers // D0 = 4 * port, D6 = doorbell to host 564*1da177e4SLinus Torvaldstx_end: tstl tx_count(%d0) 565*1da177e4SLinus Torvalds beq tx_end_ret // TX buffers already empty 566*1da177e4SLinus Torvalds 567*1da177e4SLinus Torvalds movel tx_in(%d0), %d1 568*1da177e4SLinus Torvalds movel %d1, %d2 // D1 = D2 = tx_in BD# = desc# 569*1da177e4SLinus Torvalds lsll #3, %d1 // BD is 8-bytes long 570*1da177e4SLinus Torvalds addl tx_first_bd(%d0), %d1 // D1 = current tx_in BD address 571*1da177e4SLinus Torvalds movew (%d1), %d3 // D3 = TX BD flags 572*1da177e4SLinus Torvalds btstl #15, %d3 573*1da177e4SLinus Torvalds bne tx_end_ret // BD still being transmitted 574*1da177e4SLinus Torvalds 575*1da177e4SLinus Torvalds// update D6, tx_in and tx_count 576*1da177e4SLinus Torvalds orl bell_tx(%d0), %d6 // signal host that TX desc freed 577*1da177e4SLinus Torvalds subl #1, tx_count(%d0) 578*1da177e4SLinus Torvalds movel tx_in(%d0), %d1 579*1da177e4SLinus Torvalds addl #1, %d1 580*1da177e4SLinus Torvalds cmpl #TX_BUFFERS, %d1 581*1da177e4SLinus Torvalds bne tx_end_1 582*1da177e4SLinus Torvalds clrl %d1 583*1da177e4SLinus Torvaldstx_end_1: 584*1da177e4SLinus Torvalds movel %d1, tx_in(%d0) 585*1da177e4SLinus Torvalds 586*1da177e4SLinus Torvalds// free host's descriptor 587*1da177e4SLinus Torvalds mulul #DESC_LENGTH, %d2 // D2 = TX desc offset 588*1da177e4SLinus Torvalds addl ch_status_addr(%d0), %d2 589*1da177e4SLinus Torvalds addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address 590*1da177e4SLinus Torvalds btstl #1, %d3 591*1da177e4SLinus Torvalds bne tx_end_underrun 592*1da177e4SLinus Torvalds movel #PACKET_SENT, (%d2) 593*1da177e4SLinus Torvalds bra tx_end 594*1da177e4SLinus Torvalds 595*1da177e4SLinus Torvaldstx_end_underrun: 596*1da177e4SLinus Torvalds movel #PACKET_UNDERRUN, (%d2) 597*1da177e4SLinus Torvalds bra tx_end 598*1da177e4SLinus Torvalds 599*1da177e4SLinus Torvaldstx_end_ret: rts 600*1da177e4SLinus Torvalds 601*1da177e4SLinus Torvalds 602*1da177e4SLinus Torvalds/****************************** PLX PCI9060 DMA memcpy ****************/ 603*1da177e4SLinus Torvalds 604*1da177e4SLinus Torvalds#if QUICC_MEMCPY_USES_PLX 605*1da177e4SLinus Torvalds// called with interrupts disabled 606*1da177e4SLinus Torvaldsmemcpy_from_pci_run: 607*1da177e4SLinus Torvalds movel %d0, -(%sp) 608*1da177e4SLinus Torvalds movew %sr, -(%sp) 609*1da177e4SLinus Torvaldsmemcpy_1: 610*1da177e4SLinus Torvalds movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly 611*1da177e4SLinus Torvalds btstl #4, %d0 // transfer done? 612*1da177e4SLinus Torvalds bne memcpy_end 613*1da177e4SLinus Torvalds stop #0x2200 // enable PCI9060 interrupts 614*1da177e4SLinus Torvalds movew #0x2700, %sr // disable interrupts again 615*1da177e4SLinus Torvalds bra memcpy_1 616*1da177e4SLinus Torvalds 617*1da177e4SLinus Torvaldsmemcpy_to_pci_run: 618*1da177e4SLinus Torvalds movel %d0, -(%sp) 619*1da177e4SLinus Torvalds movew %sr, -(%sp) 620*1da177e4SLinus Torvaldsmemcpy_2: 621*1da177e4SLinus Torvalds movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly 622*1da177e4SLinus Torvalds btstl #12, %d0 // transfer done? 623*1da177e4SLinus Torvalds bne memcpy_end 624*1da177e4SLinus Torvalds stop #0x2200 // enable PCI9060 interrupts 625*1da177e4SLinus Torvalds movew #0x2700, %sr // disable interrupts again 626*1da177e4SLinus Torvalds bra memcpy_2 627*1da177e4SLinus Torvalds 628*1da177e4SLinus Torvaldsmemcpy_end: 629*1da177e4SLinus Torvalds movew (%sp)+, %sr 630*1da177e4SLinus Torvalds movel (%sp)+, %d0 631*1da177e4SLinus Torvalds rts 632*1da177e4SLinus Torvalds#endif 633*1da177e4SLinus Torvalds 634*1da177e4SLinus Torvalds 635*1da177e4SLinus Torvalds 636*1da177e4SLinus Torvalds 637*1da177e4SLinus Torvalds 638*1da177e4SLinus Torvalds 639*1da177e4SLinus Torvalds/****************************** PLX PCI9060 interrupt *****************/ 640*1da177e4SLinus Torvalds 641*1da177e4SLinus Torvaldspci9060_interrupt: 642*1da177e4SLinus Torvalds movel %d0, -(%sp) 643*1da177e4SLinus Torvalds 644*1da177e4SLinus Torvalds movel PLX_DOORBELL_TO_CARD, %d0 645*1da177e4SLinus Torvalds movel %d0, PLX_DOORBELL_TO_CARD // confirm all requests 646*1da177e4SLinus Torvalds orl %d0, channel_stats 647*1da177e4SLinus Torvalds 648*1da177e4SLinus Torvalds movel #0x0909, PLX_DMA_CMD_STS // clear DMA ch #0 and #1 interrupts 649*1da177e4SLinus Torvalds 650*1da177e4SLinus Torvalds movel (%sp)+, %d0 651*1da177e4SLinus Torvalds rte 652*1da177e4SLinus Torvalds 653*1da177e4SLinus Torvalds/****************************** SCC interrupts ************************/ 654*1da177e4SLinus Torvalds 655*1da177e4SLinus Torvaldsport_interrupt_1: 656*1da177e4SLinus Torvalds orl #0, SCC1_REGS + SCC_SCCE; // confirm SCC events 657*1da177e4SLinus Torvalds orl #1 << TASK_SCC_0, channel_stats 658*1da177e4SLinus Torvalds movel #0x40000000, CISR 659*1da177e4SLinus Torvalds rte 660*1da177e4SLinus Torvalds 661*1da177e4SLinus Torvaldsport_interrupt_2: 662*1da177e4SLinus Torvalds orl #0, SCC2_REGS + SCC_SCCE; // confirm SCC events 663*1da177e4SLinus Torvalds orl #1 << TASK_SCC_1, channel_stats 664*1da177e4SLinus Torvalds movel #0x20000000, CISR 665*1da177e4SLinus Torvalds rte 666*1da177e4SLinus Torvalds 667*1da177e4SLinus Torvaldsport_interrupt_3: 668*1da177e4SLinus Torvalds orl #0, SCC3_REGS + SCC_SCCE; // confirm SCC events 669*1da177e4SLinus Torvalds orl #1 << TASK_SCC_2, channel_stats 670*1da177e4SLinus Torvalds movel #0x10000000, CISR 671*1da177e4SLinus Torvalds rte 672*1da177e4SLinus Torvalds 673*1da177e4SLinus Torvaldsport_interrupt_4: 674*1da177e4SLinus Torvalds orl #0, SCC4_REGS + SCC_SCCE; // confirm SCC events 675*1da177e4SLinus Torvalds orl #1 << TASK_SCC_3, channel_stats 676*1da177e4SLinus Torvalds movel #0x08000000, CISR 677*1da177e4SLinus Torvalds rte 678*1da177e4SLinus Torvalds 679*1da177e4SLinus Torvaldserror_interrupt: 680*1da177e4SLinus Torvalds rte 681*1da177e4SLinus Torvalds 682*1da177e4SLinus Torvalds 683*1da177e4SLinus Torvalds/****************************** cable and PM routine ******************/ 684*1da177e4SLinus Torvalds// modified registers: none 685*1da177e4SLinus Torvaldscheck_csr: 686*1da177e4SLinus Torvalds movel %d0, -(%sp) 687*1da177e4SLinus Torvalds movel %d1, -(%sp) 688*1da177e4SLinus Torvalds movel %d2, -(%sp) 689*1da177e4SLinus Torvalds movel %a0, -(%sp) 690*1da177e4SLinus Torvalds movel %a1, -(%sp) 691*1da177e4SLinus Torvalds 692*1da177e4SLinus Torvalds clrl %d0 // D0 = 4 * port 693*1da177e4SLinus Torvalds movel #CSRA, %a0 // A0 = CSR address 694*1da177e4SLinus Torvalds 695*1da177e4SLinus Torvaldscheck_csr_loop: 696*1da177e4SLinus Torvalds movew (%a0), %d1 // D1 = CSR input bits 697*1da177e4SLinus Torvalds andl #0xE7, %d1 // PM and cable sense bits (no DCE bit) 698*1da177e4SLinus Torvalds cmpw #STATUS_CABLE_V35 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 699*1da177e4SLinus Torvalds bne check_csr_1 700*1da177e4SLinus Torvalds movew #0x0E08, %d1 701*1da177e4SLinus Torvalds bra check_csr_valid 702*1da177e4SLinus Torvalds 703*1da177e4SLinus Torvaldscheck_csr_1: 704*1da177e4SLinus Torvalds cmpw #STATUS_CABLE_X21 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 705*1da177e4SLinus Torvalds bne check_csr_2 706*1da177e4SLinus Torvalds movew #0x0408, %d1 707*1da177e4SLinus Torvalds bra check_csr_valid 708*1da177e4SLinus Torvalds 709*1da177e4SLinus Torvaldscheck_csr_2: 710*1da177e4SLinus Torvalds cmpw #STATUS_CABLE_V24 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 711*1da177e4SLinus Torvalds bne check_csr_3 712*1da177e4SLinus Torvalds movew #0x0208, %d1 713*1da177e4SLinus Torvalds bra check_csr_valid 714*1da177e4SLinus Torvalds 715*1da177e4SLinus Torvaldscheck_csr_3: 716*1da177e4SLinus Torvalds cmpw #STATUS_CABLE_EIA530 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 717*1da177e4SLinus Torvalds bne check_csr_disable 718*1da177e4SLinus Torvalds movew #0x0D08, %d1 719*1da177e4SLinus Torvalds bra check_csr_valid 720*1da177e4SLinus Torvalds 721*1da177e4SLinus Torvaldscheck_csr_disable: 722*1da177e4SLinus Torvalds movew #0x0008, %d1 // D1 = disable everything 723*1da177e4SLinus Torvalds movew #0x80E7, %d2 // D2 = input mask: ignore DSR 724*1da177e4SLinus Torvalds bra check_csr_write 725*1da177e4SLinus Torvalds 726*1da177e4SLinus Torvaldscheck_csr_valid: // D1 = mode and IRQ bits 727*1da177e4SLinus Torvalds movew csr_output(%d0), %d2 728*1da177e4SLinus Torvalds andw #0x3000, %d2 // D2 = requested LL and DTR bits 729*1da177e4SLinus Torvalds orw %d2, %d1 // D1 = all requested output bits 730*1da177e4SLinus Torvalds movew #0x80FF, %d2 // D2 = input mask: include DSR 731*1da177e4SLinus Torvalds 732*1da177e4SLinus Torvaldscheck_csr_write: 733*1da177e4SLinus Torvalds cmpw old_csr_output(%d0), %d1 734*1da177e4SLinus Torvalds beq check_csr_input 735*1da177e4SLinus Torvalds movew %d1, old_csr_output(%d0) 736*1da177e4SLinus Torvalds movew %d1, (%a0) // Write CSR output bits 737*1da177e4SLinus Torvalds 738*1da177e4SLinus Torvaldscheck_csr_input: 739*1da177e4SLinus Torvalds movew (PCDAT), %d1 740*1da177e4SLinus Torvalds andw dcd_mask(%d0), %d1 741*1da177e4SLinus Torvalds beq check_csr_dcd_on // DCD and CTS signals are negated 742*1da177e4SLinus Torvalds movew (%a0), %d1 // D1 = CSR input bits 743*1da177e4SLinus Torvalds andw #~STATUS_CABLE_DCD, %d1 // DCD off 744*1da177e4SLinus Torvalds bra check_csr_previous 745*1da177e4SLinus Torvalds 746*1da177e4SLinus Torvaldscheck_csr_dcd_on: 747*1da177e4SLinus Torvalds movew (%a0), %d1 // D1 = CSR input bits 748*1da177e4SLinus Torvalds orw #STATUS_CABLE_DCD, %d1 // DCD on 749*1da177e4SLinus Torvaldscheck_csr_previous: 750*1da177e4SLinus Torvalds andw %d2, %d1 // input mask 751*1da177e4SLinus Torvalds movel ch_status_addr(%d0), %a1 752*1da177e4SLinus Torvalds cmpl STATUS_CABLE(%a1), %d1 // check for change 753*1da177e4SLinus Torvalds beq check_csr_next 754*1da177e4SLinus Torvalds movel %d1, STATUS_CABLE(%a1) // update status 755*1da177e4SLinus Torvalds movel bell_cable(%d0), PLX_DOORBELL_FROM_CARD // signal the host 756*1da177e4SLinus Torvalds 757*1da177e4SLinus Torvaldscheck_csr_next: 758*1da177e4SLinus Torvalds addl #2, %a0 // next CSR register 759*1da177e4SLinus Torvalds addl #4, %d0 // D0 = 4 * next port 760*1da177e4SLinus Torvalds cmpl #4 * 4, %d0 761*1da177e4SLinus Torvalds bne check_csr_loop 762*1da177e4SLinus Torvalds 763*1da177e4SLinus Torvalds movel (%sp)+, %a1 764*1da177e4SLinus Torvalds movel (%sp)+, %a0 765*1da177e4SLinus Torvalds movel (%sp)+, %d2 766*1da177e4SLinus Torvalds movel (%sp)+, %d1 767*1da177e4SLinus Torvalds movel (%sp)+, %d0 768*1da177e4SLinus Torvalds rts 769*1da177e4SLinus Torvalds 770*1da177e4SLinus Torvalds 771*1da177e4SLinus Torvalds/****************************** timer interrupt ***********************/ 772*1da177e4SLinus Torvalds 773*1da177e4SLinus Torvaldstimer_interrupt: 774*1da177e4SLinus Torvalds bsr check_csr 775*1da177e4SLinus Torvalds rte 776*1da177e4SLinus Torvalds 777*1da177e4SLinus Torvalds 778*1da177e4SLinus Torvalds/****************************** RAM sizing and test *******************/ 779*1da177e4SLinus Torvalds#if DETECT_RAM 780*1da177e4SLinus Torvaldsram_test: 781*1da177e4SLinus Torvalds movel #0x12345678, %d1 // D1 = test value 782*1da177e4SLinus Torvalds movel %d1, (128 * 1024 - 4) 783*1da177e4SLinus Torvalds movel #128 * 1024, %d0 // D0 = RAM size tested 784*1da177e4SLinus Torvaldsram_test_size: 785*1da177e4SLinus Torvalds cmpl #MAX_RAM_SIZE, %d0 786*1da177e4SLinus Torvalds beq ram_test_size_found 787*1da177e4SLinus Torvalds movel %d0, %a0 788*1da177e4SLinus Torvalds addl #128 * 1024 - 4, %a0 789*1da177e4SLinus Torvalds cmpl (%a0), %d1 790*1da177e4SLinus Torvalds beq ram_test_size_check 791*1da177e4SLinus Torvaldsram_test_next_size: 792*1da177e4SLinus Torvalds lsll #1, %d0 793*1da177e4SLinus Torvalds bra ram_test_size 794*1da177e4SLinus Torvalds 795*1da177e4SLinus Torvaldsram_test_size_check: 796*1da177e4SLinus Torvalds eorl #0xFFFFFFFF, %d1 797*1da177e4SLinus Torvalds movel %d1, (128 * 1024 - 4) 798*1da177e4SLinus Torvalds cmpl (%a0), %d1 799*1da177e4SLinus Torvalds bne ram_test_next_size 800*1da177e4SLinus Torvalds 801*1da177e4SLinus Torvaldsram_test_size_found: // D0 = RAM size 802*1da177e4SLinus Torvalds movel %d0, %a0 // A0 = fill ptr 803*1da177e4SLinus Torvalds subl #firmware_end + 4, %d0 804*1da177e4SLinus Torvalds lsrl #2, %d0 805*1da177e4SLinus Torvalds movel %d0, %d1 // D1 = DBf counter 806*1da177e4SLinus Torvaldsram_test_fill: 807*1da177e4SLinus Torvalds movel %a0, -(%a0) 808*1da177e4SLinus Torvalds dbfw %d1, ram_test_fill 809*1da177e4SLinus Torvalds subl #0x10000, %d1 810*1da177e4SLinus Torvalds cmpl #0xFFFFFFFF, %d1 811*1da177e4SLinus Torvalds bne ram_test_fill 812*1da177e4SLinus Torvalds 813*1da177e4SLinus Torvaldsram_test_loop: // D0 = DBf counter 814*1da177e4SLinus Torvalds cmpl (%a0)+, %a0 815*1da177e4SLinus Torvalds dbnew %d0, ram_test_loop 816*1da177e4SLinus Torvalds bne ram_test_found_bad 817*1da177e4SLinus Torvalds subl #0x10000, %d0 818*1da177e4SLinus Torvalds cmpl #0xFFFFFFFF, %d0 819*1da177e4SLinus Torvalds bne ram_test_loop 820*1da177e4SLinus Torvalds bra ram_test_all_ok 821*1da177e4SLinus Torvalds 822*1da177e4SLinus Torvaldsram_test_found_bad: 823*1da177e4SLinus Torvalds subl #4, %a0 824*1da177e4SLinus Torvaldsram_test_all_ok: 825*1da177e4SLinus Torvalds movel %a0, PLX_MAILBOX_5 826*1da177e4SLinus Torvalds rts 827*1da177e4SLinus Torvalds#endif 828*1da177e4SLinus Torvalds 829*1da177e4SLinus Torvalds 830*1da177e4SLinus Torvalds/****************************** constants *****************************/ 831*1da177e4SLinus Torvalds 832*1da177e4SLinus Torvaldsscc_reg_addr: 833*1da177e4SLinus Torvalds .long SCC1_REGS, SCC2_REGS, SCC3_REGS, SCC4_REGS 834*1da177e4SLinus Torvaldsscc_base_addr: 835*1da177e4SLinus Torvalds .long SCC1_BASE, SCC2_BASE, SCC3_BASE, SCC4_BASE 836*1da177e4SLinus Torvalds 837*1da177e4SLinus Torvaldstx_first_bd: 838*1da177e4SLinus Torvalds .long DPRBASE 839*1da177e4SLinus Torvalds .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 840*1da177e4SLinus Torvalds .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 2 841*1da177e4SLinus Torvalds .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 3 842*1da177e4SLinus Torvalds 843*1da177e4SLinus Torvaldsrx_first_bd: 844*1da177e4SLinus Torvalds .long DPRBASE + TX_BUFFERS * 8 845*1da177e4SLinus Torvalds .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 846*1da177e4SLinus Torvalds .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 2 847*1da177e4SLinus Torvalds .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 3 848*1da177e4SLinus Torvalds 849*1da177e4SLinus Torvaldsfirst_buffer: 850*1da177e4SLinus Torvalds .long BUFFERS_ADDR 851*1da177e4SLinus Torvalds .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH 852*1da177e4SLinus Torvalds .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 2 853*1da177e4SLinus Torvalds .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 3 854*1da177e4SLinus Torvalds 855*1da177e4SLinus Torvaldsbell_tx: 856*1da177e4SLinus Torvalds .long 1 << DOORBELL_FROM_CARD_TX_0, 1 << DOORBELL_FROM_CARD_TX_1 857*1da177e4SLinus Torvalds .long 1 << DOORBELL_FROM_CARD_TX_2, 1 << DOORBELL_FROM_CARD_TX_3 858*1da177e4SLinus Torvalds 859*1da177e4SLinus Torvaldsbell_cable: 860*1da177e4SLinus Torvalds .long 1 << DOORBELL_FROM_CARD_CABLE_0, 1 << DOORBELL_FROM_CARD_CABLE_1 861*1da177e4SLinus Torvalds .long 1 << DOORBELL_FROM_CARD_CABLE_2, 1 << DOORBELL_FROM_CARD_CABLE_3 862*1da177e4SLinus Torvalds 863*1da177e4SLinus Torvaldspacket_full: 864*1da177e4SLinus Torvalds .long PACKET_FULL, PACKET_FULL + 1, PACKET_FULL + 2, PACKET_FULL + 3 865*1da177e4SLinus Torvalds 866*1da177e4SLinus Torvaldsclocking_ext: 867*1da177e4SLinus Torvalds .long 0x0000002C, 0x00003E00, 0x002C0000, 0x3E000000 868*1da177e4SLinus Torvaldsclocking_txfromrx: 869*1da177e4SLinus Torvalds .long 0x0000002D, 0x00003F00, 0x002D0000, 0x3F000000 870*1da177e4SLinus Torvaldsclocking_mask: 871*1da177e4SLinus Torvalds .long 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 872*1da177e4SLinus Torvaldsdcd_mask: 873*1da177e4SLinus Torvalds .word 0x020, 0, 0x080, 0, 0x200, 0, 0x800 874*1da177e4SLinus Torvalds 875*1da177e4SLinus Torvalds .ascii "wanXL firmware\n" 876*1da177e4SLinus Torvalds .asciz "Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl>\n" 877*1da177e4SLinus Torvalds 878*1da177e4SLinus Torvalds 879*1da177e4SLinus Torvalds/****************************** variables *****************************/ 880*1da177e4SLinus Torvalds 881*1da177e4SLinus Torvalds .align 4 882*1da177e4SLinus Torvaldschannel_stats: .long 0 883*1da177e4SLinus Torvalds 884*1da177e4SLinus Torvaldstx_in: .long 0, 0, 0, 0 // transmitted 885*1da177e4SLinus Torvaldstx_out: .long 0, 0, 0, 0 // received from host for transmission 886*1da177e4SLinus Torvaldstx_count: .long 0, 0, 0, 0 // currently in transmit queue 887*1da177e4SLinus Torvalds 888*1da177e4SLinus Torvaldsrx_in: .long 0, 0, 0, 0 // received from port 889*1da177e4SLinus Torvaldsrx_out: .long 0 // transmitted to host 890*1da177e4SLinus Torvaldsparity_bytes: .word 0, 0, 0, 0, 0, 0, 0 // only 4 words are used 891*1da177e4SLinus Torvalds 892*1da177e4SLinus Torvaldscsr_output: .word 0 893*1da177e4SLinus Torvaldsold_csr_output: .word 0, 0, 0, 0, 0, 0, 0 894*1da177e4SLinus Torvalds .align 4 895*1da177e4SLinus Torvaldsfirmware_end: // must be dword-aligned 896