-
Notifications
You must be signed in to change notification settings - Fork 7
/
RealtekR1000SL.h
599 lines (479 loc) · 16.4 KB
/
RealtekR1000SL.h
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
/*
* RealtekR1000SL.h - Class definition for Realtek Ethernet driver
* RealtekR1000SL
*
* Copyright 2009 Chuck Fry. All rights reserved.
*
* This software incorporates code from Realtek's open source Linux drivers
* and the open source Mac OS X project RealtekR1000 by Dmitri Arekhta,
* as modified by PSYSTAR Corporation.
*
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
* copyright PSYSTAR Corporation, 2008
* 2006 (c) Dmitri Arekhta ([email protected])
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _REALTEKR1000_H_
#define _REALTEKR1000_H_
#include <IOKit/IOLib.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include <IOKit/network/IOEthernetController.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IOBasicOutputQueue.h>
#include <IOKit/network/IOMbufMemoryCursor.h>
#include <IOKit/pci/IOPCIDevice.h>
#include <IOKit/IOFilterInterruptEventSource.h>
extern "C"
{
#include <sys/kpi_mbuf.h>
#include <architecture/i386/pio.h>
}
#include "R1000Regs.h"
#include "mii.h"
#define RealtekR1000 com_chucko_RealtekR1000
//
// Memory allocation method
//
// Choose ONE of these
//
//#define R1000_ORIGINAL_BUFFER_ALLOCATION
#define R1000_NEW_BUFFER_ALLOCATION_1
//
// Debug logging
//
#ifdef DEBUG
#define DLog(format, ...) IOLog("%s: "format, bsdName, ##__VA_ARGS__)
#else
#define DLog(...)
#endif
//
// Configuration macros
//
//#define R1000_CHECKSUM_OFFLOAD
#define BSD_NAME_LEN 16
enum
{
MEDIUM_INDEX_10HD = 0,
MEDIUM_INDEX_10FD = 1,
MEDIUM_INDEX_100HD = 2,
MEDIUM_INDEX_100FD = 3,
MEDIUM_INDEX_1000HD = 4,
MEDIUM_INDEX_1000FD = 5,
MEDIUM_INDEX_AUTO = 6,
MEDIUM_INDEX_COUNT = 7
};
// Power states
enum
{
kR1000PowerStateOff = 0,
kR1000PowerStateOn,
kR1000PowerStateCount
};
class RealtekR1000 : public IOEthernetController
{
OSDeclareDefaultStructors(RealtekR1000)
public:
//
// IONetworkController API
//
virtual bool init(OSDictionary *properties);
virtual void free();
virtual bool start(IOService *provider);
virtual void stop(IOService *provider);
virtual IOReturn enable(IONetworkInterface *netif);
virtual IOReturn disable(IONetworkInterface *netif);
virtual bool setLinkStatus( UInt32 status,
const IONetworkMedium *activeMedium = 0,
UInt64 speed = 0,
OSData *data = 0 );
virtual UInt32 outputPacket(mbuf_t m, void *param);
virtual void getPacketBufferConstraints(IOPacketBufferConstraints *constraints) const;
virtual IOOutputQueue *createOutputQueue();
virtual const OSString *newVendorString() const;
virtual const OSString *newModelString() const;
virtual IOReturn selectMedium(const IONetworkMedium *medium);
virtual bool configureInterface(IONetworkInterface *netif);
virtual bool createWorkLoop();
virtual IOWorkLoop *getWorkLoop() const;
virtual IOReturn getHardwareAddress(IOEthernetAddress *addr);
// Broadcast, multicast, promiscuous modes
virtual IOReturn setPromiscuousMode(bool enabled);
virtual IOReturn setMulticastMode(bool enabled);
virtual IOReturn setMulticastList(IOEthernetAddress *addrs, UInt32 count);
// Kernel debug methods
virtual void sendPacket(void *pkt, UInt32 pkt_len);
virtual void receivePacket(void * pkt, UInt32 *pkt_len, UInt32 timeout);
// Power management
virtual IOReturn registerWithPolicyMaker(IOService *policyMaker);
virtual IOReturn setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker);
//
// H/W checksum support
virtual IOReturn getChecksumSupport(UInt32 *checksumMask,
UInt32 checksumFamily,
bool isOutput);
private:
//
// Private methods used in IONetworkInterface API
//
void R1000Interrupt(OSObject * client, IOInterruptEventSource * src, int count);
void R1000TxTimeout(OSObject *owner, IOTimerEventSource * timer);
//
// IOKit interface objects
//
IOPCIDevice *pciDev;
IOWorkLoop *workLoop;
IOInterruptEventSource *intSource;
IOTimerEventSource *timerSource;
IONetworkStats *netStats;
IOEthernetStats *etherStats;
IOOutputQueue *transmitQueue;
IOEthernetInterface *etherif;
OSDictionary *mediumDict;
const IONetworkMedium *mediumTable[MEDIUM_INDEX_COUNT]; // *** only used in increaseActivationLevel() ??
//
// BSD name for this device
//
char bsdName[BSD_NAME_LEN];
//
// OS flag data for configureInterface() method
//
UInt32 canOffload; // chip h/w capabilities
bool board_inited;
bool buffers_inited;
bool enabled;
bool linked;
UInt32 activationLevel;
bool enabledForBSD;
bool enabledForKDP;
unsigned long powerState;
bool rx_fifo_overflow;
// HW Configuration info
int mcfg; // Which chip
u32 rx_config_base; // Base value of RxConfig register for this chip
u32 rx_config_mask; // Mask for RxConfig register
u16 max_jumbo_frame_sz; // Max jumbo frame size for this chip ; 0 == not supported
u16 efuse; // EFUSE capability (some 8168 variants only)
ulong expire_time;
ulong n_rx_desc; /* Number of receive buffers for this chip. */
ulong cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. Max value is n_rx_desc - 1. */
// cur_tx and dirty_tx are indices into the Tx descriptor ring buffer.
// (cur_tx % n_tx_desc) is the index of the next free Tx descriptor.
// (dirty_tx % n_tx_desc) is the index of the Tx descriptor currently being transmitted (if any).
// dirty_tx lags cur_tx when transmission is in progress.
// Both increase monotonically - no consequences if they wrap around,
// as long as n_tx_desc is a power of 2.
ulong n_tx_desc; /* Number of transmit buffers for this chip. */
ulong cur_tx; /* Index into the Tx descriptor buffer of next Tx pkt. */
ulong dirty_tx;
//
// Transmit buffers
//
// packets as passed in by caller
struct __mbuf *Tx_skbuff[NUM_TX_DESC];
#ifdef R1000_ORIGINAL_BUFFER_ALLOCATION
// virtual memory addresses of buffer pool
uchar *Tx_dbuff[NUM_TX_DESC];
// OS descriptors
IOBufferMemoryDescriptor *Tx_skbuff_Md[NUM_TX_DESC];
// Physical addresses for hardware to use
IOPhysicalAddress Tx_skbuff_Dma[NUM_TX_DESC];
#endif // R1000_ORIGINAL_BUFFER_ALLOCATION
#ifdef R1000_NEW_BUFFER_ALLOCATION_1
// OS descriptor
IOBufferMemoryDescriptor *Tx_skbuff_pool_Md;
// Virtual memory map
IOMemoryMap *Tx_skbuff_pool_Map;
// Physical base address
IOPhysicalAddress Tx_skbuff_pool_phys_addr;
// Virtual base address
IOVirtualAddress Tx_skbuff_pool_virt_addr;
#endif // R1000_NEW_BUFFER_ALLOCATION_1
//
// Receive buffers
//
#ifdef R1000_ORIGINAL_BUFFER_ALLOCATION
// virtual memory addresses of buffer pool
uchar *Rx_dbuff[NUM_RX_DESC];
// OS descriptors
IOBufferMemoryDescriptor *Rx_skbuff_Md[NUM_RX_DESC];
// Physical addresses for hardware to use
IOPhysicalAddress Rx_skbuff_Dma[NUM_RX_DESC];
#endif // R1000_ORIGINAL_BUFFER_ALLOCATION
#ifdef R1000_NEW_BUFFER_ALLOCATION_1
// OS descriptor
IOBufferMemoryDescriptor *Rx_skbuff_pool_Md;
// Virtual memory map
IOMemoryMap *Rx_skbuff_pool_Map;
// Physical base address
IOPhysicalAddress Rx_skbuff_pool_phys_addr;
// Virtual base address
IOVirtualAddress Rx_skbuff_pool_virt_addr;
#endif // R1000_NEW_BUFFER_ALLOCATION_1
void *txdesc_space;
struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */
IOBufferMemoryDescriptor *tx_descMd;
IOPhysicalAddress txdesc_phy_dma_addr;
int sizeof_txdesc_space;
void *rxdesc_space;
struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */
IOBufferMemoryDescriptor *rx_descMd;
IOPhysicalAddress rxdesc_phy_dma_addr;
int sizeof_rxdesc_space;
// Maximum packet sizes
// These will always be smaller than 2^16.
ulong curr_mtu_size;
ulong tx_pkt_len;
ulong rx_pkt_len;
ulong hw_rx_pkt_len;
// Medium settings
u16 speed;
u8 duplex;
u8 autoneg;
//
// Cached copies of registers
//
u16 cp_cmd;
u16 intr_mask;
u32 msg_enable;
u32 tx_tcp_csum_cmd;
u32 tx_udp_csum_cmd;
u32 tx_ip_csum_cmd;
u16 wol_enabled; /* Wake On Lan */
ulong mc_filter0, mc_filter1; // cached multicast filter bits
static int max_interrupt_work;
static UInt32 multicast_filter_limit;
static const u32 ethernet_polynomial;
static const u16 r1000_intr_mask;
static const u16 rtl8101_intr_mask;
static const u16 rtl8101_napi_event;
static const uint32_t rtl8101_rx_config;
static const u16 rtl8168_intr_mask;
static const u16 rtl8168_napi_event;
static const struct RtlChipInfo rtl_chip_info[];
static struct IOPMPowerState powerStateArray[kR1000PowerStateCount];
//
// Primitive IO operations
//
UInt16 pioBase; // Port IO base address
IOMemoryMap *mmioBase; // Memory map for IO
bool forcedPio; // True = no memory mapped IO
//
// Writes - equivalent to RTL_W{8,16,32}
//
inline void WriteMMIO8(ushort offset, uchar value)
{ (forcedPio) ? outb(pioBase + offset, value) : pciDev->ioWrite8(offset, value, mmioBase); }
inline void WriteMMIO16(ushort offset, ushort value)
{ (forcedPio) ? outw(pioBase + offset, value) : pciDev->ioWrite16(offset, value, mmioBase); }
inline void WriteMMIO32(ushort offset, UInt32 value)
{ (forcedPio) ? outl(pioBase + offset, value) : pciDev->ioWrite32(offset, value, mmioBase); }
//
// Reads - equivalent to RTL_R{8,16,32}
//
inline uchar ReadMMIO8(ushort offset)
{ return ((forcedPio) ? inb(pioBase + offset) : pciDev->ioRead8(offset, mmioBase)); }
inline ushort ReadMMIO16(ushort offset)
{ return ((forcedPio) ? inw(pioBase + offset) : pciDev->ioRead16(offset, mmioBase)); }
inline ulong ReadMMIO32(ushort offset)
{ return ((forcedPio) ? inl(pioBase + offset) : pciDev->ioRead32(offset, mmioBase)); }
//
// Less primitive IO
//
//
// GMII access
// Equivalent to mdio_{write,read}
//
void WriteGMII16(int RegAddr, u16 value);
u16 ReadGMII16(int RegAddr);
//
// EPHY access
// Equivalent to RTL8xxx_ephy_{write,read}
//
void WriteEPHY16(int RegAddr, u16 value);
u16 ReadEPHY16(int RegAddr);
//
// CSI access
// Equivalent to RTL8xxx_csi_{write,read}
//
void WriteCSI32(int addr, int value);
int ReadCSI32(int addr);
//
// ERI Register access
// Equivalent to rtl8xxx_eri_{write,read}
int WriteERI(int addr, int len, int value, int type);
int ReadERI(int addr, int len, int type);
//
// EEPROM access
//
int rtl_eeprom_type();
void rtl_eeprom_cleanup();
u16 rtl_eeprom_read_sc(u16 reg);
void rtl_eeprom_write_sc(u16 reg, u16 data);
void rtl_shift_out_bits(int data, int count);
u16 rtl_shift_in_bits();
void rtl_raise_clock(u8 *x);
void rtl_lower_clock(u8 *);
void rtl_stand_by();
int rtl_eeprom_cmd_done();
void R1000GetMacVersion();
bool R1000InitBoard();
bool R1000ProbeAndStartBoard();
bool R1000StopBoard();
// Meant to be called as an IOWorkLoop Action.
IOReturn R1000ResetTask();
void R1000SetMedium(ushort speed, uchar duplex, uchar autoneg);
bool increaseActivationLevel(UInt32 level);
bool decreaseActivationLevel(UInt32 level);
bool setActivationLevel(UInt32 level);
void R1000HwPhyReset();
void R1000HwPhyConfig();
void R1000NicReset();
void R1000HwStart();
void R1000TxClear();
void R1000Suspend();
void R1000Resume();
bool R1000CheckLinkStatus();
void R1000DSM(int dev_state);
void R1000PowerDownPLL();
void R1000PowerUpPLL();
void R1000PowerDownPHY();
void R1000PowerUpPHY();
void R1000ASICDown();
void R1000IRQMaskAndAck();
inline void R1000InitRingIndices()
{
cur_rx = cur_tx = dirty_tx = 0;
}
inline u16 map_phy_ocp_addr(u16 page, u16 reg)
{
if (page != OCP_STD_PHY_BASE_PAGE) {
reg -= 16;
}
page <<= 4;
reg <<= 1;
return (page + reg);
}
//
// Specialized methods by chip family
//
// RTL8100
//
void RTL8100HwStart();
// Chip specific subroutines
void RTL8100HwStart1Gen();
void RTL8105EHwStart1();
void RTL8105EHwStart();
void RTL8402HwStart();
void RTL8100HwPhyConfig();
// Chip specific configuration
void RTL8102EHwPhyConfig();
void RTL8401PhyHwConfig();
void RTL8105E1HwPhyConfig();
void RTL8105EHwPhyConfig();
void RTL8402HwPhyConfig();
void RTL8100NicReset();
void RTL8100SetMedium(ushort speedIn, uchar duplexIn, uchar autonegIn);
void RTL8100DSM(int dev_state);
static const int eee_enable = 0;
void RTL8100EnableEEE();
void RTL8100DisableEEE();
void RTL8100PowerDownPLL();
void RTL8100PowerUpPLL();
void RTL8100PowerDownPHY();
void RTL8100PowerUpPHY();
void RTL8100WritePhyIO(int RegAddr, int value);
int RTL8100ReadPhyIO(int RegAddr);
//
// RTL8168
//
void RTL8168HwStart();
// subroutines of above
void RTL8168BHwStart2();
void RTL8168CHwStart2();
void RTL8168CPHwStart2();
void RTL8168DHwStart2();
void RTL8168DPHwStart2();
void RTL8168EHwStart2();
void RTL8168EVLHwStart2();
void RTL8168FHwStart2();
void RTL8168HwPhyConfig();
// subroutines of above
void RTL8168BHwPhyConfig();
void RTL8168CHwPhyConfig();
void RTL8168CPHwPhyConfig();
void RTL8168DHwPhyConfig();
void RTL8168DPHwPhyConfig();
void RTL8168EHwPhyConfig();
void RTL8168FHwPhyConfig();
void RTL8168NicReset();
void RTL8168SleepRxEnable();
void RTL8168SetMedium(ushort speedIn, uchar duplexIn, uchar autonegIn);
void RTL8168DSM(int dev_state);
void RTL8168PowerDownPLL();
void RTL8168PowerUpPLL();
void RTL8168PowerDownPHY();
void RTL8168PowerUpPHY();
void RTL8168WriteOCP_GPHY(int RegAddr, u16 value);
u16 RTL8168ReadOCP_GPHY(int RegAddr);
u8 RTL8168ReadEfuse(u16 reg);
//
// RTL8169
//
void RTL8169HwStart();
void RTL8169HwPhyConfig();
void RTL8169NicReset();
void RTL8169SetMedium(ushort speedIn, uchar duplexIn, uchar autonegIn);
void RTL8169PowerDownPHY();
void RTL8169PowerUpPHY();
ulong ether_crc(int length, unsigned char *data);
//
// Buffer pool allocation/deallocation
//
// Descriptor buffers
bool AllocateDescriptorsMemory();
void FreeDescriptorsMemory();
// Packet buffers
void InitializeBufferMemoryPointers();
bool AllocateBufferMemory();
void FreeBufferMemory();
#ifdef R1000_ORIGINAL_BUFFER_ALLOCATION
inline IOPhysicalAddress RxBufferPhysicalAddress(int n) { return Rx_skbuff_Dma[n]; }
inline IOPhysicalAddress TxBufferPhysicalAddress(int n) { return Tx_skbuff_Dma[n]; }
inline uchar* RxBufferVirtualAddress(int n) { return Rx_dbuff[n]; }
inline uchar* TxBufferVirtualAddress(int n) { return Tx_dbuff[n]; }
#endif
#ifdef R1000_NEW_BUFFER_ALLOCATION_1
// FIXME - buffer sizes should be a variable, not a macro!
inline IOPhysicalAddress RxBufferPhysicalAddress(int n)
{ return Rx_skbuff_pool_phys_addr + (n * MAX_RX_SKBDATA_SIZE); }
inline IOPhysicalAddress TxBufferPhysicalAddress(int n)
{ return Tx_skbuff_pool_phys_addr + (n * MAX_TX_SKBDATA_SIZE); }
inline uchar* RxBufferVirtualAddress(int n)
{ return reinterpret_cast<uchar*>(Rx_skbuff_pool_virt_addr + (n * MAX_RX_SKBDATA_SIZE)); }
inline uchar* TxBufferVirtualAddress(int n)
{ return reinterpret_cast<uchar*>(Tx_skbuff_pool_virt_addr + (n * MAX_TX_SKBDATA_SIZE)); }
#endif
void InitializeRingBufferDescriptors();
void R1000InitRxDescCmds(bool nicOwn);
bool R1000InitEventSources(IOService *provide);
bool R1000OpenAdapter();
void R1000CloseAdapter();
void R1000RxInterrupt(u16 intStatus);
void R1000TxInterrupt(u16 intStatus);
void R1000PCIErrorInterrupt();
bool OSAddNetworkMedium(ulong type, UInt32 bps, ulong index);
};
#endif