summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/drivers/net/myson.h
blob: 8d7cc5855d07270b63c5d0ded676fc2b99cfdb6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#ifndef _MYSON_H
#define _MYSON_H

/** @file
 *
 * Myson Technology network card driver
 *
 */

FILE_LICENCE ( GPL2_OR_LATER );

#include <stdint.h>
#include <ipxe/if_ether.h>

/** BAR size */
#define MYSON_BAR_SIZE 256

/** A packet descriptor */
struct myson_descriptor {
	/** Status */
	uint32_t status;
	/** Control */
	uint32_t control;
	/** Buffer start address */
	uint32_t address;
	/** Next descriptor address */
	uint32_t next;
} __attribute__ (( packed ));

/* Transmit status */
#define MYSON_TX_STAT_OWN	0x80000000UL	/**< Owner */
#define MYSON_TX_STAT_ABORT	0x00002000UL	/**< Abort */
#define MYSON_TX_STAT_CSL	0x00001000UL	/**< Carrier sense lost */

/* Transmit control */
#define MYSON_TX_CTRL_IC	0x80000000UL	/**< Interrupt control */
#define MYSON_TX_CTRL_LD	0x20000000UL	/**< Last descriptor */
#define MYSON_TX_CTRL_FD	0x10000000UL	/**< First descriptor */
#define MYSON_TX_CTRL_CRC	0x08000000UL	/**< CRC append */
#define MYSON_TX_CTRL_PAD	0x04000000UL	/**< Pad control */
#define MYSON_TX_CTRL_RTLC	0x02000000UL	/**< Retry late collision */
#define MYSON_TX_CTRL_PKTS(x)	( (x) << 11 )	/**< Packet size */
#define MYSON_TX_CTRL_TBS(x)	( (x) << 0 )	/**< Transmit buffer size */

/* Receive status */
#define MYSON_RX_STAT_OWN	0x80000000UL	/**< Owner */
#define MYSON_RX_STAT_FLNG(status) ( ( (status) >> 16 ) & 0xfff )
#define MYSON_RX_STAT_ES	0x00000080UL	/**< Error summary */

/* Receive control */
#define MYSON_RX_CTRL_RBS(x)	( (x) << 0 )	/**< Receive buffer size */

/** Descriptor ring alignment */
#define MYSON_RING_ALIGN 4

/** Physical Address Register 0 */
#define MYSON_PAR0 0x00

/** Physical Address Register 4 */
#define MYSON_PAR4 0x04

/** Physical address */
union myson_physical_address {
	struct {
		uint32_t low;
		uint32_t high;
	} __attribute__ (( packed )) reg;
	uint8_t raw[ETH_ALEN];
};

/** Transmit and Receive Configuration Register */
#define MYSON_TCR_RCR 0x18
#define MYSON_TCR_TXS		0x80000000UL	/**< Transmit status */
#define MYSON_TCR_TE		0x00040000UL	/**< Transmit enable */
#define MYSON_RCR_RXS		0x00008000UL	/**< Receive status */
#define MYSON_RCR_PROM		0x00000080UL	/**< Promiscuous mode */
#define MYSON_RCR_AB		0x00000040UL	/**< Accept broadcast */
#define MYSON_RCR_AM		0x00000020UL	/**< Accept multicast */
#define MYSON_RCR_ARP		0x00000008UL	/**< Accept runt packet */
#define MYSON_RCR_ALP		0x00000004UL	/**< Accept long packet */
#define MYSON_RCR_RE		0x00000001UL	/**< Receive enable */

/** Maximum time to wait for transmit and receive to be idle, in milliseconds */
#define MYSON_IDLE_MAX_WAIT_MS 100

/** Bus Command Register */
#define MYSON_BCR 0x1c
#define MYSON_BCR_RLE		0x00000100UL	/**< Read line enable */
#define MYSON_BCR_RME		0x00000080UL	/**< Read multiple enable */
#define MYSON_BCR_WIE		0x00000040UL	/**< Write and invalidate */
#define MYSON_BCR_PBL(x)	( (x) << 3 )	/**< Burst length */
#define MYSON_BCR_PBL_MASK	MYSON_BCR_PBL ( 0x7 )
#define MYSON_BCR_PBL_DEFAULT	MYSON_BCR_PBL ( 0x6 )
#define MYSON_BCR_SWR		0x00000001UL	/**< Software reset */

/** Maximum time to wait for a reset, in milliseconds */
#define MYSON_RESET_MAX_WAIT_MS 100

/** Transmit Poll Demand Register */
#define MYSON_TXPDR 0x20

/** Receive Poll Demand Register */
#define MYSON_RXPDR 0x24

/** Transmit List Base Address */
#define MYSON_TXLBA 0x2c

/** Number of transmit descriptors */
#define MYSON_NUM_TX_DESC 4

/** Receive List Base Address */
#define MYSON_RXLBA 0x30

/** Number of receive descriptors */
#define MYSON_NUM_RX_DESC 4

/** Receive buffer length */
#define MYSON_RX_MAX_LEN ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ )

/** Interrupt Status Register */
#define MYSON_ISR 0x34
#define MYSON_IRQ_TI		0x00000008UL	/**< Transmit interrupt */
#define MYSON_IRQ_RI		0x00000004UL	/**< Receive interrupt */

/** Number of I/O delays between ISR reads */
#define MYSON_ISR_IODELAY_COUNT 4

/** Interrupt Mask Register */
#define MYSON_IMR 0x38

/** Boot ROM / EEPROM / MII Management Register */
#define MYSON_ROM_MII 0x40
#define MYSON_ROM_AUTOLD	0x00100000UL	/**< Auto load */

/** Maximum time to wait for a configuration reload, in milliseconds */
#define MYSON_AUTOLD_MAX_WAIT_MS 100

/** A Myson descriptor ring */
struct myson_ring {
	/** Descriptors */
	struct myson_descriptor *desc;
	/** Producer index */
	unsigned int prod;
	/** Consumer index */
	unsigned int cons;

	/** Number of descriptors */
	unsigned int count;
	/** Descriptor start address register */
	unsigned int reg;
};

/**
 * Initialise descriptor ring
 *
 * @v ring		Descriptor ring
 * @v count		Number of descriptors
 * @v reg		Descriptor base address register
 */
static inline __attribute__ (( always_inline)) void
myson_init_ring ( struct myson_ring *ring, unsigned int count,
		  unsigned int reg ) {
	ring->count = count;
	ring->reg = reg;
}

/** A myson network card */
struct myson_nic {
	/** Registers */
	void *regs;

	/** Transmit descriptor ring */
	struct myson_ring tx;
	/** Receive descriptor ring */
	struct myson_ring rx;
	/** Receive I/O buffers */
	struct io_buffer *rx_iobuf[MYSON_NUM_RX_DESC];
};

/**
 * Check if card can access physical address
 *
 * @v address		Physical address
 * @v address_ok	Card can access physical address
 */
static inline __attribute__ (( always_inline )) int
myson_address_ok ( physaddr_t address ) {

	/* In a 32-bit build, all addresses can be accessed */
	if ( sizeof ( physaddr_t ) <= sizeof ( uint32_t ) )
		return 1;

	/* Card can access all addresses below 4GB */
	if ( ( address & ~0xffffffffULL ) == 0 )
		return 1;

	return 0;
}

#endif /* _MYSON_H */