LANCOM NWAPP - neuschaefer/linux GitHub Wiki

aka. L-320agn Wireless, L-321agn Wireless, L-322agn dual Wireless_

This is the original design; for the redesigned version see NWAPP2.

Hardware

Pictures

photo, top of PCB

LANCOM NWAPP.E0, top side

photo, bottom of PCB

LANCOM NWAPP.E0, bottom side

Ports

  • LANCOM console port (RS-232 over mini-DIN 8-pin)
  • 10/100/1000 Mbit/s Ethernet port
  • 10/100 Mbit/s Ethernet port
  • 12 V DC
  • 2 mPCIe slots for WLAN

Chips

Top side:

Bottom side:

Internal connectors

  • JP1500 (D) is the debug jumper. Setting it causes the bootloader to skip the memory test and start the main menu instead of any installed firmware.
  • CN1500 is for flash access
  • CN1501 ?
  • CN1 is for JTAG, it follows the JTAG/COP pinout:

Motorola/Freescale/NXP JTAG/COP pinout diagram

Firmware

Flash layout

V<adr>/I/R/G/B/S/U/D/e/f/t/H/?>
Flashlayout:16MB_Strataflash
 FE000000      32KiB Loader1
 FE008000       8KiB Romdscr1
 FE00A000      24KiB Unused
 FE010000       8KiB Romdscr2
 FE012000      24KiB Unused
 FE018000     160KiB Loader2
 FE040000     512KiB LCFS
 FE0C0000     512KiB Config
 FE140000     512KiB Accounting
 FE1C0000   14592KiB Firmware

Main menu

V<adr>/I/R/G/B/S/U/D/e/f/t/H/?>

Monitor help page
-----------------
 V<adr>  : Dump memory addresses <adr>
 G       : Start active firmware
 I       : Version Info
 U0,U1   : Upload file to Flash-ROM by XMODEM-/CRC
 D0,D1   : Download file by XMODEM-128/1K
 R       : Reboot (Warmstart)

 Bx      : Modify outband bitrate

 E ...*  : Erase menu       * = action required
 F ...   : Firmware menu
 T ...   : Test menu

Dumping memory

Memory (both RAM and flash) can be dumping with two simple scripts:

decode.py
#!/usr/bin/python3
import re, argparse

LINE = re.compile("(........):  (.. .. .. .. .. .. .. ..  .. .. .. .. .. .. .. ..) | ................")
MiB = 1024 ** 2

def main(i, o):
    buf = bytearray()
    start = None
    for line in i:
        if 'L2Ldr: exception #' in line: break
        if m := LINE.match(line):
            addr = int(m.group(1), 16)
            if not start:
                start = addr
                print(f"Start: {start:#x}")
            offset = addr - start
            data = bytes.fromhex(m.group(2))
            if len(buf) < offset:
                buf += b'\0' * (offset - len(buf))
            if len(buf) != offset:
                print("vorwärts immer, rückwärts nimmer!")
                break
            buf += data
    l = len(buf)
    print(f"Got {l} ({l:#x}) bytes, {l / MiB:.4} MiB")
    o.write(buf)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="decode LANCOM bootloader output")
    parser.add_argument('log', help='log file to read')
    parser.add_argument('bin', help='binary file to write')
    args = parser.parse_args()
    i = open(args.log, 'r')
    o = open(args.bin, 'wb')
    main(i, o)
trigger.sh
#!/bin/sh
printf "V$1\r"
while sleep 0.1; do printf '\r'; done

which are then invoked like this:

./trigger.sh 0 | microcom -s 115200 /dev/ttyUSB0 | tee ram.log
./trigger.sh FE000000 | microcom -s 115200 /dev/ttyUSB0 | tee flash.log
./decode.py ram.log ram.bin
./decode.py flash.log flash.bin

Test menu

The test menu can be entered by pressing t in the main menu. It offers a shell-like interface, rather than the single-letter commands in the main menu.

V<adr>/I/R/G/B/S/U/D/e/f/t/H/?>

If you can read this, you have voided your warranty.
Mon>help
help> 
unknown command! type ? for help

Mon>?
?> 
fs_list                                           list filesystem contents
fs_del       <id>                                 delete file <id>
list_flash                                        detect/list flash roms
q                                                 Quit
;                                                 queue commands
run          <num>                                start firmware #num (0 or 1)
dbg          <dbg_lvl>                            Set debug level 0..n (default==1)
rep          <val>; cmd <args> [;cmd <args>] ...  repeat commands n-times
cb           <addr32>, <data8>                    read and compare byte value from address
cw           <addr32>, <data16>                   read and compare word value from address
cl           <addr32>, <data32>                   read and compare long value from address
rb           <addr32>                             read byte value from address
rw           <addr32>                             read word value from address
rl           <addr32>                             read long value from address
wb           <addr32>,<data8> [,count]            write byte value to address
ww           <addr32>,<data16> [,count]           write word value to address
wl           <addr32>,<data32> [,count]           write long value to address
test_timers                                       test timer system
test_wdog                                         test watchdog
v24_status                                        show V24 status lines
v24_dcd      1|0                                  set V24 DCD signal
v24_dsr      1|0                                  set V24 DSR signal
upload                                            upload UPX-File to flash(X-Modem)
download     start,end                            X-Modem download
led          num,val                              test LED
?                                                 Help
coldboot                                          cold-boot system (if implemented)
d            [base[,len]]                         dump memory block
mmu                                               print mmu regs
clocks                                            print clocks
map                                               print mappings
cr           hostbrg,bus,dev,fct,reg [,data32]    read and optionally compare PCI config reg
cw           hostbrg,bus,dev,fct,reg,val          write PCI config reg
lspci                                             list PCI devices

Mon>

fs_list

The file system uses numerical tags instead of names:

Mon>fs_list
fs_list>
FE040004: ID 5, len 00000039
FE040040: ID 4, len 00000072
FE0400B5: ID 1, len 0000E29F
FE04E357: ID 12, len 0000068B
FE04E9E5: ID 41, len 0000068B
FE04F073: ID 43, len 0000029C
FE04F312: ID 47, len 000000F1
FE04F406: ID 3, len 00000074
FE04F47D: ID A9, len 00001216
FE050696: ID D, len 00000004
FE068FEE: ID 6, len 0000B850
FE07595B: ID C7, len 000007A9
FE076107: <END>

GPIOs

GPIODAT = 0xe0000c08

# I/O mask device description
0 I 0x8000_0000 JP1500 debug status (active low)
1 I 0x4000_0000 SW1500 reset button (active low)
2 O 0x2000_0000 U1602? bitbanged latch
5 O 0x0400_0000 U1602? bitbanged clock
18 O 0x0000_2000 something related to SPI
20 O 0x0000_0800 U1602? bitbanged data
21 O 0x0000_0400 RS-232 DCD active
22 O 0x0000_0200 RS-232 DSR active

The MPC8314E has 32 GPIOs. Their usage on the NWAPP2 board is as follows, (#) indicates active low signals:

Bitbanged shift register

An 8-bit shift register is bitbanged through GPIO 2/5/20. Bits are transmitted MSB-first, in the following steps:

  • clock, latch, data = 0
  • for every bit:
    • data = bit
    • clock = 1
    • clock = 0
  • latch = 1
  • latch = 0
number mask default description
0 0x01 1
1 0x02 1
2 0x04 0
3 0x08 1
4 0x10 1
5 0x20 0
6 0x40 0 board reset
7 0x80 0

LEDs

The LEDs are connected to the shift registers U1500/U1501, which are driven through the SoC's SPI controller. LANCOM's bootloader configures the SPI controller to use 16-bit words, so that a single word-write to the SPI transmit register at 0xe0007030 sets the LED pattern. The shift registers do not have a latch pin, so any changes come into effect immediately.

Active-low signals are indicated by a hash sign (#).

LED purpose color bit comments
1500 Power red 0 #
(top) green 1 #
1501 Power red 2
(front) green 3
1502 WLAN 1 red 4
(front) green 5
1503 WLAN red 6 #
(top) green 7 #
1504 WLAN 2 red 8 #
(front) green 9 #
1505 red 10 unpopulated
green 11
1506 ETH 1 red -- not CPU-controlled
green --
1507 ETH 2 red --
green --

PCIe

There are two mini-PCIe slots, typically used for WLAN cards (Model DNXA-116). PCI/PCIe configuration on the MPC8314E is rather complex, but the preconfigured access windows are as follows:

type slot 1 slot 2 size
config 0x88000000 0x8c000000 4 MiB
I/O 0x8a000000 0x8e000000 4 MiB
memory 0x8a400000 0x8e400000 32 MiB

Note that 32 MiB of memory address space are not enough for typical GPUs. Previous attempts at configuring a larger access window have failed.

Ethernet

There are two Ethernet ports, externally labelled as ETH 1 and ETH 2.

port MAC PHY Conn. LED speed (Mbit/s)
ETH 2 eTSEC 1 @ 0xe0024000 U1101, 88E3018 CN1100 LED1507 10/100
ETH 1 eTSEC 2 @ 0xe0025000 U1001, 88E1116 CN1000 LED1506 10/100/1000

MDIO scans show the following:

md0.scan()
Port 0:
 0: 1140 7949 0141 0e11 01e1 0000 0004 2001
 8: 0000 0300 0000 0000 0000 0000 0000 3000
16: 6060 8040 0000 0040 0000 0000 0000 0000
24: 0000 0000 0040 0000 0000 0000 0000 0000

Port 2:
 0: 3100 78e9 0141 0e20 01e1 cde1 000f 2801
 8: 0000 0000 0000 0000 0000 0000 0000 0000
16: 0130 7c40 0000 5c40 0000 0000 4a44 4000
24: 4205 000a 0000 0000 0402 0000 0000 0000

Port 16:
 0: 1140 0149 0000 0000 0000 0000 0004 0000
 8: 0000 0000 0000 0000 0000 0000 0000 a000
16: 0000 0010 0000 0000 0000 0000 0000 0000
24: 0000 0000 0000 0000 0000 0000 0000 0000

On md0 (MDIO for eTSEC 1), the PHY is identified as 0x01410e11 (Marvell 88E1118) when reading from port address 0, but as 0x01410e20 when reading from port 2. This ID is unknown to U-Boot and Linux, but QEMU identifies it as 88E3015, which is close enough to 88E3018 to be plausible for U1101.

md1.scan()
Port 0:
 0: 1140 0149 0000 0000 0000 0000 0004 0000
 8: 0000 0000 0000 0000 0000 0000 0000 a000
16: 0000 0010 0000 0000 0000 0000 0000 0000
24: 0000 0000 0000 0000 0000 0000 0000 0000

On md1, address 0, we see a pattern that also appeared on md0, address 16. A vaguely plausible set of bits in registers 0/1, but no identification in registers 2/3. It turns out this is the eTSEC's internal "ten-bit interface" (TBI) PHY, which can be configured to respond to different addresses (cf. TBIPA in the MPC8315E Reference Manual).

⚠️ **GitHub.com Fallback** ⚠️