/firmware/keyspan_pda/xircom_pgs.S
Assembly | 1192 lines | 1192 code | 0 blank | 0 comment | 7 complexity | 5691a255b7e88894ac423caa9feb8aa6 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /* $Id: loop.s,v 1.23 2000/03/20 09:49:06 warner Exp $
- *
- * Firmware for the Keyspan PDA Serial Adapter, a USB serial port based on
- * the EzUSB microcontroller.
- *
- * (C) Copyright 2000 Brian Warner <warner@lothar.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * "Keyspan PDA Serial Adapter" is probably a copyright of Keyspan, the
- * company.
- *
- * This serial adapter is basically an EzUSB chip and an RS-232 line driver
- * in a little widget that has a DB-9 on one end and a USB plug on the other.
- * It uses the EzUSB's internal UART0 (using the pins from Port C) and timer2
- * as a baud-rate generator. The wiring is:
- * PC0/RxD0 <- rxd (DB9 pin 2) PC4 <- dsr pin 6
- * PC1/TxD0 -> txd pin 3 PC5 <- ri pin 9
- * PC2 -> rts pin 7 PC6 <- dcd pin 1
- * PC3 <- cts pin 8 PC7 -> dtr pin 4
- * PB1 -> line driver standby
- *
- * The EzUSB register constants below come from their excellent documentation
- * and sample code (which used to be available at www.anchorchips.com, but
- * that has now been absorbed into Cypress' site and the CD-ROM contents
- * don't appear to be available online anymore). If we get multiple
- * EzUSB-based drivers into the kernel, it might be useful to pull them out
- * into a separate .h file.
- *
- * THEORY OF OPERATION:
- *
- * There are two 256-byte ring buffers, one for tx, one for rx.
- *
- * EP2out is pure tx data. When it appears, the data is copied into the tx
- * ring and serial transmission is started if it wasn't already running. The
- * "tx buffer empty" interrupt may kick off another character if the ring
- * still has data. If the host is tx-blocked because the ring filled up,
- * it will request a "tx unthrottle" interrupt. If sending a serial character
- * empties the ring below the desired threshold, we set a bit that will send
- * up the tx unthrottle message as soon as the rx buffer becomes free.
- *
- * EP2in (interrupt) is used to send both rx chars and rx status messages
- * (only "tx unthrottle" at this time) back up to the host. The first byte
- * of the rx message indicates data (0) or status msg (1). Status messages
- * are sent before any data.
- *
- * Incoming serial characters are put into the rx ring by the serial
- * interrupt, and the EP2in buffer sent if it wasn't already in transit.
- * When the EP2in buffer returns, the interrupt prompts us to send more
- * rx chars (or status messages) if they are pending.
- *
- * Device control happens through "vendor specific" control messages on EP0.
- * All messages are destined for the "Interface" (with the index always 0,
- * so that if their two-port device might someday use similar firmware, we
- * can use index=1 to refer to the second port). The messages defined are:
- *
- * bRequest = 0 : set baud/bits/parity
- * 1 : unused
- * 2 : reserved for setting HW flow control (CTSRTS)
- * 3 : get/set "modem info" (pin states: DTR, RTS, DCD, RI, etc)
- * 4 : set break (on/off)
- * 5 : reserved for requesting interrupts on pin state change
- * 6 : query buffer room or chars in tx buffer
- * 7 : request tx unthrottle interrupt
- *
- * The host-side driver is set to recognize the device ID values stashed in
- * serial EEPROM (0x06cd, 0x0103), program this firmware into place, then
- * start it running. This firmware will use EzUSB's "renumeration" trick by
- * simulating a bus disconnect, then reconnect with a different device ID
- * (encoded in the desc_device descriptor below). The host driver then
- * recognizes the new device ID and glues it to the real serial driver code.
- *
- * USEFUL DOCS:
- * EzUSB Technical Reference Manual: <http://www.cypress.com/>
- * 8051 manuals: everywhere, but try www.dalsemi.com because the EzUSB is
- * basically the Dallas enhanced 8051 code. Remember that the EzUSB IO ports
- * use totally different registers!
- * USB 1.1 spec: www.usb.org
- *
- * HOW TO BUILD:
- * gcc -x assembler-with-cpp -P -E -o keyspan_pda.asm keyspan_pda.s
- * as31 -l keyspan_pda.asm
- * mv keyspan_pda.obj keyspan_pda.hex
- * perl ezusb_convert.pl keyspan_pda < keyspan_pda.hex > keyspan_pda_fw.h
- * Get as31 from <http://www.pjrc.com/tech/8051/index.html>, and hack on it
- * a bit to make it build.
- *
- * THANKS:
- * Greg Kroah-Hartman, for coordinating the whole usb-serial thing.
- * AnchorChips, for making such an incredibly useful little microcontroller.
- * KeySpan, for making a handy, cheap ($40) widget that was so easy to take
- * apart and trace with an ohmmeter.
- *
- * TODO:
- * lots. grep for TODO. Interrupt safety needs stress-testing. Better flow
- * control. Interrupting host upon change in DCD, etc, counting transitions.
- * Need to find a safe device id to use (the one used by the Keyspan firmware
- * under Windows would be ideal.. can anyone figure out what it is?). Parity.
- * More baud rates. Oh, and the string-descriptor-length silicon bug
- * workaround should be implemented, but I'm lazy, and the consequence is
- * that the device name strings that show up in your kernel log will have
- * lots of trailing binary garbage in them (appears as ????). Device strings
- * should be made more accurate.
- *
- * Questions, bugs, patches to Brian.
- *
- * -Brian Warner <warner@lothar.com>
- *
- */
-
- #define HIGH(x) (((x) & 0xff00) / 256)
- #define LOW(x) ((x) & 0xff)
- #define dpl1 0x84
- #define dph1 0x85
- #define dps 0x86
- ;;; our bit assignments
- #define TX_RUNNING 0
- #define DO_TX_UNTHROTTLE 1
-
- ;; stack from 0x60 to 0x7f: should really set SP to 0x60-1, not 0x60
- #define STACK #0x60-1
- #define EXIF 0x91
- #define EIE 0xe8
- .flag EUSB, EIE.0
- .flag ES0, IE.4
- #define EP0CS #0x7fb4
- #define EP0STALLbit #0x01
- #define IN0BUF #0x7f00
- #define IN0BC #0x7fb5
- #define OUT0BUF #0x7ec0
- #define OUT0BC #0x7fc5
- #define IN2BUF #0x7e00
- #define IN2BC #0x7fb9
- #define IN2CS #0x7fb8
- #define OUT2BC #0x7fc9
- #define OUT2CS #0x7fc8
- #define OUT2BUF #0x7dc0
- #define IN4BUF #0x7d00
- #define IN4BC #0x7fbd
- #define IN4CS #0x7fbc
- #define OEB #0x7f9d
- #define OUTB #0x7f97
- #define OEC #0x7f9e
- #define OUTC #0x7f98
- #define PINSC #0x7f9b
- #define PORTBCFG #0x7f94
- #define PORTCCFG #0x7f95
- #define OEA #0x7f9c
- #define IN07IRQ #0x7fa9
- #define OUT07IRQ #0x7faa
- #define IN07IEN #0x7fac
- #define OUT07IEN #0x7fad
- #define USBIRQ #0x7fab
- #define USBIEN #0x7fae
- #define USBBAV #0x7faf
- #define USBCS #0x7fd6
- #define SUDPTRH #0x7fd4
- #define SUDPTRL #0x7fd5
- #define SETUPDAT #0x7fe8
-
- ;; usb interrupt : enable is EIE.0 (0xe8), flag is EXIF.4 (0x91)
- .org 0
- ljmp start
- ;; interrupt vectors
- .org 23H
- ljmp serial_int
- .byte 0
-
- .org 43H
- ljmp USB_Jump_Table
- .byte 0 ; filled in by the USB core
- ;;; local variables. These are not initialized properly: do it by hand.
- .org 30H
- rx_ring_in: .byte 0
- rx_ring_out: .byte 0
- tx_ring_in: .byte 0
- tx_ring_out: .byte 0
- tx_unthrottle_threshold: .byte 0
-
- .org 0x100H ; wants to be on a page boundary
- USB_Jump_Table:
- ljmp ISR_Sudav ; Setup Data Available
- .byte 0
- ljmp 0 ; Start of Frame
- .byte 0
- ljmp 0 ; Setup Data Loading
- .byte 0
- ljmp 0 ; Global Suspend
- .byte 0
- ljmp 0 ; USB Reset
- .byte 0
- ljmp 0 ; Reserved
- .byte 0
- ljmp 0 ; End Point 0 In
- .byte 0
- ljmp 0 ; End Point 0 Out
- .byte 0
- ljmp 0 ; End Point 1 In
- .byte 0
- ljmp 0 ; End Point 1 Out
- .byte 0
- ljmp ISR_Ep2in
- .byte 0
- ljmp ISR_Ep2out
- .byte 0
- .org 0x200
-
- start: mov SP,STACK-1 ; set stack
- ;; clear local variables
- clr a
- mov tx_ring_in, a
- mov tx_ring_out, a
- mov rx_ring_in, a
- mov rx_ring_out, a
- mov tx_unthrottle_threshold, a
- clr TX_RUNNING
- clr DO_TX_UNTHROTTLE
-
- ;; clear fifo with "fe"
- mov r1, 0
- mov a, #0xfe
- mov dptr, #tx_ring
- clear_tx_ring_loop:
- movx @dptr, a
- inc dptr
- djnz r1, clear_tx_ring_loop
- mov a, #0xfd
- mov dptr, #rx_ring
- clear_rx_ring_loop:
- movx @dptr, a
- inc dptr
- djnz r1, clear_rx_ring_loop
- ;;; turn on the RS-232 driver chip (bring the STANDBY pin low)
- ;;; on Xircom the STANDBY is wired to PB6 and PC4
-