linux/drivers/net/ethernet/realtek/atp.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/* Linux header file for the ATP pocket ethernet adapter. */
   3/* v1.09 8/9/2000 becker@scyld.com. */
   4
   5#include <linux/if_ether.h>
   6#include <linux/types.h>
   7
   8/* The header prepended to received packets. */
   9struct rx_header {
  10        ushort pad;             /* Pad. */
  11        ushort rx_count;
  12        ushort rx_status;       /* Unknown bit assignments :-<.  */
  13        ushort cur_addr;        /* Apparently the current buffer address(?) */
  14};
  15
  16#define PAR_DATA        0
  17#define PAR_STATUS      1
  18#define PAR_CONTROL 2
  19
  20#define Ctrl_LNibRead   0x08    /* LP_PSELECP */
  21#define Ctrl_HNibRead   0
  22#define Ctrl_LNibWrite  0x08    /* LP_PSELECP */
  23#define Ctrl_HNibWrite  0
  24#define Ctrl_SelData    0x04    /* LP_PINITP */
  25#define Ctrl_IRQEN      0x10    /* LP_PINTEN */
  26
  27#define EOW     0xE0
  28#define EOC     0xE0
  29#define WrAddr  0x40    /* Set address of EPLC read, write register. */
  30#define RdAddr  0xC0
  31#define HNib    0x10
  32
  33enum page0_regs {
  34        /* The first six registers hold
  35         * the ethernet physical station address.
  36         */
  37        PAR0 = 0, PAR1 = 1, PAR2 = 2, PAR3 = 3, PAR4 = 4, PAR5 = 5,
  38        TxCNT0 = 6, TxCNT1 = 7,         /* The transmit byte count. */
  39        TxSTAT = 8, RxSTAT = 9,         /* Tx and Rx status. */
  40        ISR = 10, IMR = 11,             /* Interrupt status and mask. */
  41        CMR1 = 12,                      /* Command register 1. */
  42        CMR2 = 13,                      /* Command register 2. */
  43        MODSEL = 14,            /* Mode select register. */
  44        MAR = 14,                       /* Memory address register (?). */
  45        CMR2_h = 0x1d,
  46};
  47
  48enum eepage_regs {
  49        PROM_CMD = 6,
  50        PROM_DATA = 7   /* Note that PROM_CMD is in the "high" bits. */
  51};
  52
  53#define ISR_TxOK        0x01
  54#define ISR_RxOK        0x04
  55#define ISR_TxErr       0x02
  56#define ISRh_RxErr      0x11    /* ISR, high nibble */
  57
  58#define CMR1h_MUX       0x08    /* Select printer multiplexor on 8012. */
  59#define CMR1h_RESET     0x04    /* Reset. */
  60#define CMR1h_RxENABLE  0x02    /* Rx unit enable.  */
  61#define CMR1h_TxENABLE  0x01    /* Tx unit enable.  */
  62#define CMR1h_TxRxOFF   0x00
  63#define CMR1_ReXmit     0x08    /* Trigger a retransmit. */
  64#define CMR1_Xmit       0x04    /* Trigger a transmit. */
  65#define CMR1_IRQ        0x02    /* Interrupt active. */
  66#define CMR1_BufEnb     0x01    /* Enable the buffer(?). */
  67#define CMR1_NextPkt    0x01    /* Enable the buffer(?). */
  68
  69#define CMR2_NULL       8
  70#define CMR2_IRQOUT     9
  71#define CMR2_RAMTEST    10
  72#define CMR2_EEPROM     12      /* Set to page 1, for reading the EEPROM. */
  73
  74#define CMR2h_OFF       0       /* No accept mode. */
  75#define CMR2h_Physical  1       /* Accept a physical address match only. */
  76#define CMR2h_Normal    2       /* Accept physical and broadcast address. */
  77#define CMR2h_PROMISC   3       /* Promiscuous mode. */
  78
  79/* An inline function used below: it differs from inb() by explicitly
  80 * return an unsigned char, saving a truncation.
  81 */
  82static inline unsigned char inbyte(unsigned short port)
  83{
  84        unsigned char _v;
  85
  86        __asm__ __volatile__ ("inb %w1,%b0" : "=a" (_v) : "d" (port));
  87        return _v;
  88}
  89
  90/* Read register OFFSET.
  91 * This command should always be terminated with read_end().
  92 */
  93static inline unsigned char read_nibble(short port, unsigned char offset)
  94{
  95        unsigned char retval;
  96
  97        outb(EOC+offset, port + PAR_DATA);
  98        outb(RdAddr+offset, port + PAR_DATA);
  99        inbyte(port + PAR_STATUS);      /* Settling time delay */
 100        retval = inbyte(port + PAR_STATUS);
 101        outb(EOC+offset, port + PAR_DATA);
 102
 103        return retval;
 104}
 105
 106/* Functions for bulk data read.  The interrupt line is always disabled. */
 107/* Get a byte using read mode 0, reading data from the control lines. */
 108static inline unsigned char read_byte_mode0(short ioaddr)
 109{
 110        unsigned char low_nib;
 111
 112        outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL);
 113        inbyte(ioaddr + PAR_STATUS);
 114        low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
 115        outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL);
 116        inbyte(ioaddr + PAR_STATUS);    /* Settling time delay -- needed!  */
 117        inbyte(ioaddr + PAR_STATUS);    /* Settling time delay -- needed!  */
 118        return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
 119}
 120
 121/* The same as read_byte_mode0(), but does multiple inb()s for stability. */
 122static inline unsigned char read_byte_mode2(short ioaddr)
 123{
 124        unsigned char low_nib;
 125
 126        outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL);
 127        inbyte(ioaddr + PAR_STATUS);
 128        low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
 129        outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL);
 130        inbyte(ioaddr + PAR_STATUS);    /* Settling time delay -- needed!  */
 131        return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
 132}
 133
 134/* Read a byte through the data register. */
 135static inline unsigned char read_byte_mode4(short ioaddr)
 136{
 137        unsigned char low_nib;
 138
 139        outb(RdAddr | MAR, ioaddr + PAR_DATA);
 140        low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
 141        outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA);
 142        return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
 143}
 144
 145/* Read a byte through the data register, double reading to allow settling. */
 146static inline unsigned char read_byte_mode6(short ioaddr)
 147{
 148        unsigned char low_nib;
 149
 150        outb(RdAddr | MAR, ioaddr + PAR_DATA);
 151        inbyte(ioaddr + PAR_STATUS);
 152        low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f;
 153        outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA);
 154        inbyte(ioaddr + PAR_STATUS);
 155        return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0);
 156}
 157
 158static inline void
 159write_reg(short port, unsigned char reg, unsigned char value)
 160{
 161        unsigned char outval;
 162
 163        outb(EOC | reg, port + PAR_DATA);
 164        outval = WrAddr | reg;
 165        outb(outval, port + PAR_DATA);
 166        outb(outval, port + PAR_DATA);  /* Double write for PS/2. */
 167
 168        outval &= 0xf0;
 169        outval |= value;
 170        outb(outval, port + PAR_DATA);
 171        outval &= 0x1f;
 172        outb(outval, port + PAR_DATA);
 173        outb(outval, port + PAR_DATA);
 174
 175        outb(EOC | outval, port + PAR_DATA);
 176}
 177
 178static inline void
 179write_reg_high(short port, unsigned char reg, unsigned char value)
 180{
 181        unsigned char outval = EOC | HNib | reg;
 182
 183        outb(outval, port + PAR_DATA);
 184        outval &= WrAddr | HNib | 0x0f;
 185        outb(outval, port + PAR_DATA);
 186        outb(outval, port + PAR_DATA);  /* Double write for PS/2. */
 187
 188        outval = WrAddr | HNib | value;
 189        outb(outval, port + PAR_DATA);
 190        outval &= HNib | 0x0f;          /* HNib | value */
 191        outb(outval, port + PAR_DATA);
 192        outb(outval, port + PAR_DATA);
 193
 194        outb(EOC | HNib | outval, port + PAR_DATA);
 195}
 196
 197/* Write a byte out using nibble mode.  The low nibble is written first. */
 198static inline void
 199write_reg_byte(short port, unsigned char reg, unsigned char value)
 200{
 201        unsigned char outval;
 202
 203        outb(EOC | reg, port + PAR_DATA); /* Reset the address register. */
 204        outval = WrAddr | reg;
 205        outb(outval, port + PAR_DATA);
 206        outb(outval, port + PAR_DATA);  /* Double write for PS/2. */
 207
 208        outb((outval & 0xf0) | (value & 0x0f), port + PAR_DATA);
 209        outb(value & 0x0f, port + PAR_DATA);
 210        value >>= 4;
 211        outb(value, port + PAR_DATA);
 212        outb(0x10 | value, port + PAR_DATA);
 213        outb(0x10 | value, port + PAR_DATA);
 214
 215        outb(EOC  | value, port + PAR_DATA); /* Reset the address register. */
 216}
 217
 218/* Bulk data writes to the packet buffer.  The interrupt line remains enabled.
 219 * The first, faster method uses only the dataport (data modes 0, 2 & 4).
 220 * The second (backup) method uses data and control regs (modes 1, 3 & 5).
 221 * It should only be needed when there is skew between the individual data
 222 * lines.
 223 */
 224static inline void write_byte_mode0(short ioaddr, unsigned char value)
 225{
 226        outb(value & 0x0f, ioaddr + PAR_DATA);
 227        outb((value>>4) | 0x10, ioaddr + PAR_DATA);
 228}
 229
 230static inline void write_byte_mode1(short ioaddr, unsigned char value)
 231{
 232        outb(value & 0x0f, ioaddr + PAR_DATA);
 233        outb(Ctrl_IRQEN | Ctrl_LNibWrite, ioaddr + PAR_CONTROL);
 234        outb((value>>4) | 0x10, ioaddr + PAR_DATA);
 235        outb(Ctrl_IRQEN | Ctrl_HNibWrite, ioaddr + PAR_CONTROL);
 236}
 237
 238/* Write 16bit VALUE to the packet buffer: the same as above just doubled. */
 239static inline void write_word_mode0(short ioaddr, unsigned short value)
 240{
 241        outb(value & 0x0f, ioaddr + PAR_DATA);
 242        value >>= 4;
 243        outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA);
 244        value >>= 4;
 245        outb(value & 0x0f, ioaddr + PAR_DATA);
 246        value >>= 4;
 247        outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA);
 248}
 249
 250/*  EEPROM_Ctrl bits. */
 251#define EE_SHIFT_CLK    0x04    /* EEPROM shift clock. */
 252#define EE_CS           0x02    /* EEPROM chip select. */
 253#define EE_CLK_HIGH     0x12
 254#define EE_CLK_LOW      0x16
 255#define EE_DATA_WRITE   0x01    /* EEPROM chip data in. */
 256#define EE_DATA_READ    0x08    /* EEPROM chip data out. */
 257
 258/* Delay between EEPROM clock transitions. */
 259#define eeprom_delay(ticks) \
 260do { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; } } while (0)
 261
 262/* The EEPROM commands include the alway-set leading bit. */
 263#define EE_WRITE_CMD(offset)    (((5 << 6) + (offset)) << 17)
 264#define EE_READ(offset)         (((6 << 6) + (offset)) << 17)
 265#define EE_ERASE(offset)        (((7 << 6) + (offset)) << 17)
 266#define EE_CMD_SIZE     27      /* The command+address+data size. */
 267