Modules/RTL8169 - Replace some magic with enum
[tpg/acess2.git] / KernelLand / Modules / Network / RTL8169 / rtl8169.c
1 /*
2  * Acess2 RealTek 8169 Gigabit Network Controller Driver
3  * - By John Hodge (thePowersGang)
4  *
5  * rtl8169.c
6  * - Driver source
7  */
8 #define DEBUG   0
9 #define VERSION 0x001
10 #include <acess.h>
11 #include <fs_devfs.h>
12 #include <drv_pci.h>
13 #include <api_drv_network.h>
14 #include "rtl8169.h"
15
16 #define N_RX_DESCS      128
17 #define N_TX_DESCS      (256-N_RX_DESCS)        // 256 * 16 = 4096 (1 page)
18 #define RX_BUF_SIZE     1024    // Most packets will fit in one buffer
19
20 #define INT_SYSERR      (1 << 15)       // System Error
21 #define INT_TIMEOUT     (1 << 14)       // Timer fire (TCTR reg)
22 #define INT_LINKCHANGE  (1 << 5)
23 #define INT_TXERR       (1 << 3)
24 #define INT_TXOK        (1 << 2)
25 #define INT_RXERR       (1 << 1)
26 #define INT_RXOK        (1 << 0)
27
28 enum eRegisters
29 {
30         REG_INTMASK  = 0x3C,
31         REG_INSSTATE = 0x3E,
32         REG_TXC = 0x40,
33         REG_RXC = 0x44,
34 }
35
36 // === PROTOTYPES ===
37  int    RTL8169_Initialise(char **Arguments);
38 void    RTL8169_Cleanup(void);
39 void    RTL8169_InterruptHandler(int IRQ, void *CardPtr);
40
41 // === GLOBALS ===
42 MODULE_DEFINE(0, RTL8169, RTL8169_Initialise, RTL8169_Cleanup, NULL);
43  int    giRTL8169_CardCount;
44 tCard   *gaRTL8169_Cards;
45
46 // === CODE ===
47 int RTL8169_Initialise(char **Arguments)
48 {
49         const Uint16    vendor_id = 0x10EC;
50         const Uint16    device_id = 0x8129;     // 8169 = 0x8129 PCI?
51         giRTL8169_CardCount = PCI_CountDevices(vendor_id, device_id);
52         if( !giRTL8169_CardCount )      return MODULE_ERR_NOTNEEDED;
53         
54         // Allocate card structures
55         gaRTL8169_Cards = malloc( sizeof(tCard) * giRTL8169_CardCount );
56         
57         // Initialise devices
58         for( int id = -1, int i = 0 ; (id = PCI_GetDevice(vendor_id, device_id, id)) != -1; i ++ )
59         {
60                 tCard   *card = &gaRTL8169_Cards[i];
61                 card->PCIId = id;
62                 
63                 card->IOAddr = PCI_GetBAR(id, 0);
64                 if( !(card->IOAddr & 1) ) {
65                         // Invalid IO address
66                         Log_Warning("RTL8169", "Card %i doesn't have BAR0 as an IO space", i);
67                         continue;
68                 }
69                 
70                 if(card->IOAddr == 1 )
71                 {
72                         // Try MMIO
73                         card->PMemAddr = PCI_GetBAR(id, 1);
74                         if( card->PMemAddr == 0 ) {
75                                 Log_Warning("RTL8169", "TODO: Allocate MMIO space");
76                                 continue ;
77                         }
78                         card->MemAddr = MM_MapHWPages(card->PMemAddr, 1);
79                 }
80         
81                 card->IRQNum = PCI_GetIRQ(card);
82                 IRQ_AddHandler( card->IRQNum, RTL8169_InterruptHandler, card );
83         
84                 RTL8169_int_SetupCard(card);
85         }
86 }
87
88 void RTL8169_int_SetupCard(tCard *Card)
89 {
90         // Initialise RX/TX Descs
91         // TODO: Handle non-64-bit PCI
92         Card->RXDescs = MM_AllocDMA(1, -1, &Card->RXDescsPhys);
93         Card->TXDescs = Card->RXDescs + N_RX_DESCS;
94
95         // - RX Descs - Max of 4096 bytes per packet (1 page)
96         tPAddr  paddr;
97         for( int i = 0; i < N_RX_DESCS; i += 2 )
98         {
99                 t8169_Desc      *desc;
100
101                 desc = &Card->RXDescs[i];
102                 if( i % (PAGE_SIZE/RX_BUF_SIZE) == 0 )
103                         Card->RXBufs[i] = MM_AllocDMA(1, 64, &paddr);
104                 else
105                         Card->RXBufs[i] = Card->RXBufs[i-1] + RX_BUF_SIZE;
106                 desc->FrameLength = RX_BUF_SIZE;
107                 desc->Flags = TXD_FLAG_OWN;
108                 desc->VLANTag = 0;
109                 desc->VLANFlags = 0;
110                 desc->AddressLow = paddr & 0xFFFFFFFF;
111                 desc->AddressHigh = paddr >> 32;
112                 paddr += RX_BUF_SIZE;
113         }
114         Card->RXDescs[N_RX_DESCS-1].Flags |= TXD_FLAG_EOR;
115         // - TX Descs - Just clear
116         memset(Card->TXDescs, 0, sizeof(t8169_Desc)*N_TX_DESCS);
117         Card->TXDescs[N_TX_DESCS-1].Flags |= TXD_FLAG_EOR;
118         
119         // Reset
120         _WriteB(Card, 0x37, 0x10);
121         while( _ReadB(Card, 0x37) & 0x10 )
122                 ;       // TODO: Timeout
123         
124         // Read MAC address
125         for( int i = 0; i < 6; i ++ )
126                 Card->MacAddr[i] = _ReadB(Card, i);
127         
128         // Initialise
129 //      _WriteB(Card, 0x50, 0xC0);
130         _WriteD(Card, REG_TXC, 0x03000700);     // TX Config
131         _WriteD(Card, REG_RXC, 0x0000E70F);     // RX Config
132         _WriteW(Card, 0xDA, RX_BUF_SIZE-1);     // Max RX Size
133         _WriteW(Card, 0xEC, 2048/32);   // Max TX size (in units of 32/128 bytes)
134         
135         _WriteQ(Card, 0x20, MM_GetPhysAddr( (tVAddr)Card->TXDescs ));
136 //      _WriteQ(Card, 0x28, MM_GetPhysAddr( (tVAddr)Card->TXHighDescs ));
137         _WriteQ(Card, 0xE4, MM_GetPhysAddr( (tVAddr)Card->RXDescs ));
138
139         _WriteW(Card, REG_INTMASK, INT_LINKCHANGE|INT_TXOK|INT_RXOK);   // Set interrupt mask
140
141         _WriteB(card, 0x37, 0x0C);      // Enable
142 }
143
144 void RTL8169_InterruptHandler(int IRQ, void *CardPtr)
145 {
146         
147 }
148
149 // --- IO ---
150 void _WriteW(tCard *Card, int Offset, Uint16 Value)
151 {
152         if( Card->MemAddr )
153                 ((Uint16*)Card->MemAddr)[Offset/2] = Value;
154         else
155                 outw(Card->IOAddr & ~1, Offset, Value);
156 }
157
158 void _WriteD(tCard *Card, int Offset, Uint32 Value)
159 {
160         if( Card->MemAddr )
161                 ((Uint32*)Card->MemAddr)[Offset/4] = Value;
162         else
163                 outl(Card->IOAddr & ~1, Offset, Value);
164 }
165
166 void _WriteQ(tCard *Card, int Offset, Uint64 Value)
167 {
168         if( Card->MemAddr ) {
169                 ((Uint32*)Card->MemAddr)[Offset/4+0] = Value;
170                 ((Uint32*)Card->MemAddr)[Offset/4+1] = Value>>32;
171         }
172         else {
173                 outd(Card->IOAddr & ~1, Offset, Value);
174                 outd(Card->IOAddr & ~1, Offset+4, Value>>32);
175         }
176 }

UCC git Repository :: git.ucc.asn.au