The Pedigree Project  0.1
Rtl8139.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "Rtl8139.h"
21 #include "Rtl8139Constants.h"
22 #include "modules/system/network-stack/NetworkStack.h"
23 #include "pedigree/kernel/Log.h"
24 #include "pedigree/kernel/machine/IrqManager.h"
25 #include "pedigree/kernel/machine/Machine.h"
26 #include "pedigree/kernel/machine/Network.h"
27 #include "pedigree/kernel/processor/Processor.h"
28 
29 Rtl8139::Rtl8139(Network *pDev)
30  : Network(pDev), m_pBase(0), m_StationInfo(), m_RxCurr(0), m_TxCurr(0),
31  m_RxLock(false), m_TxLock(), m_pRxBuffVirt(0), m_pTxBuffVirt(0),
32  m_pRxBuffPhys(0), m_pTxBuffPhys(0), m_RxBuffMR("rtl8139-rxbuffer"),
33  m_TxBuffMR("rtl8139-txbuffer")
34 {
35  setSpecificType(String("rtl8139-card"));
36 
37  // allocate the rx and tx buffers
38  if (!PhysicalMemoryManager::instance().allocateRegion(
39  m_RxBuffMR,
40  RTL_BUFF_SIZE / PAGE_SIZE + (RTL_BUFF_SIZE % PAGE_SIZE ? 1 : 0),
42  {
43  ERROR("RTL8139: Couldn't allocate Rx Buffer!");
44  return;
45  }
46  if (!PhysicalMemoryManager::instance().allocateRegion(
47  m_TxBuffMR,
48  RTL_BUFF_SIZE / PAGE_SIZE + (RTL_BUFF_SIZE % PAGE_SIZE ? 1 : 0),
50  {
51  ERROR("RTL8139: Couldn't allocate Tx Buffer!");
52  delete &m_RxBuffMR;
53  return;
54  }
55  m_pRxBuffVirt = static_cast<uint8_t *>(m_RxBuffMR.virtualAddress());
56  m_pTxBuffVirt = static_cast<uint8_t *>(m_TxBuffMR.virtualAddress());
57  m_pRxBuffPhys = m_RxBuffMR.physicalAddress();
58  m_pTxBuffPhys = m_TxBuffMR.physicalAddress();
59 
60  // grab the ports
61  m_pBase = m_Addresses[0]->m_Io;
62 
63  // reset the card
64  reset();
65 
66  // get the mac
67  for (int i = 0; i < 6; i++)
68  m_StationInfo.mac.setMac(m_pBase->read16(RTL_MAC + i), i);
69 
70  WARNING(
71  "RTL8139: MAC is " << m_StationInfo.mac[0] << ":"
72  << m_StationInfo.mac[1] << ":"
73  << m_StationInfo.mac[2] << ":"
74  << m_StationInfo.mac[3] << ":"
75  << m_StationInfo.mac[4] << ":"
76  << m_StationInfo.mac[5] << ".");
77 
78  // install the IRQ and register the NIC in the stack
79  Machine::instance().getIrqManager()->registerIsaIrqHandler(
80  getInterruptNumber(), static_cast<IrqHandler *>(this));
82 }
83 
84 Rtl8139::~Rtl8139()
85 {
86 }
87 
88 void Rtl8139::reset()
89 {
90  // reset current offsets
91  m_RxCurr = 0;
92  m_TxCurr = 0;
93 
94  // clear buffers
95  ByteSet(m_pRxBuffVirt, 0, RTL_BUFF_SIZE);
96  ByteSet(m_pTxBuffVirt, 0, RTL_BUFF_SIZE);
97 
98  // reset command and wait for complete
99  m_pBase->write8(RTL_CMD_RES, RTL_CMD);
100  while (m_pBase->read8(RTL_CMD) & RTL_CMD_RES)
101  ;
102 
103  // unlock BMCR registers
104  m_pBase->write8(RTL_CFG9346_UNLOCK, RTL_CFG9346);
105 
106  // enable Rx and Tx
107  m_pBase->write8(RTL_CMD_RXEN | RTL_CMD_TXEN, RTL_CMD);
108 
109  // get the card out of low power mode
110  m_pBase->write8(0x00, RTL_CFG1);
111 
112  // write the RxBuffer's address
113  m_pBase->write32(static_cast<uint32_t>(m_pRxBuffPhys), RTL_RXBUFF);
114 
115  // no missed packets
116  m_pBase->write8(0x00, RTL_RXMIS);
117 
118  // BMCR options
119  m_pBase->write16(RTL_BMCR_SPEED | RTL_BMCR_ANE | RTL_BMCR_DUPLEX, RTL_BMCR);
120 
121  // MSR options
122  m_pBase->write8(RTL_MSR_RXFCE, RTL_MSR);
123 
124  // write rx and tx config
125  m_pBase->write32(
126  RTL_RXCFG_FTH_NONE | RTL_RXCFG_RBLN_64K | RTL_RXCFG_MDMA_UNLM |
127  RTL_RXCFG_AR | RTL_RXCFG_AB | RTL_RXCFG_AM | RTL_RXCFG_APM |
128  RTL_RXCFG_AAP,
129  RTL_RXCFG);
130  m_pBase->write32(RTL_TXCFG_MDMA_2K | RTL_TXCFG_RR_48, RTL_TXCFG);
131 
132  // write multicast addresses
133  m_pBase->write32(0xFFFFFFFF, RTL_MAR);
134  m_pBase->write32(0xFFFFFFFF, RTL_MAR + 4);
135 
136  // lock BCMR registers
137  m_pBase->write8(RTL_CFG9346_LOCK, RTL_CFG9346);
138 
139  // enable Rx and Tx
140  m_pBase->write8(RTL_CMD_RXEN | RTL_CMD_TXEN, RTL_CMD);
141 
142  // enable all good irqs
143  m_pBase->write16(RTL_IMR_RXOK | RTL_IMR_RXERR, RTL_IMR);
144  m_pBase->write16(0xffff, RTL_ISR);
145  m_RxLock = false;
146  NOTICE("RTL8139: Reset");
147 }
148 
149 bool Rtl8139::send(size_t nBytes, uintptr_t buffer)
150 {
151  LockGuard<Spinlock> guard(m_TxLock);
152 
153  if (nBytes > RTL_PACK_MAX)
154  {
155  ERROR("RTL8139: Attempt to send a packet with size > 64 KB");
156  return false;
157  }
158 
159  // copy to the buffer and pad the packet
160  MemoryCopy(m_pTxBuffVirt, reinterpret_cast<void *>(buffer), nBytes);
161  for (int i = nBytes; i < RTL_BUFF_SIZE; i++)
162  m_pTxBuffVirt[i] = 0;
163 
164  // address & status for the write
165  m_pBase->write32(
166  static_cast<uint32_t>(m_pTxBuffPhys), RTL_TXADDR0 + m_TxCurr * 4);
167  m_pBase->write32(0x3F0000 | (nBytes & 0x1FFF), RTL_TXSTS0 + m_TxCurr * 4);
168 
169  // next descriptor, or go to 0 if 4 or more
170  m_TxCurr++;
171  m_TxCurr %= 4;
172  return true;
173 }
174 
175 void Rtl8139::recv()
176 {
177  while (m_RxLock)
178  ;
179  m_RxLock = true;
180 
181  // get the address of the start of the packet;
182  uintptr_t rxPacket = reinterpret_cast<uintptr_t>(m_pRxBuffVirt + m_RxCurr);
183  uint16_t status = *(reinterpret_cast<uint16_t *>(rxPacket));
184  // get the status and the lenght, both at the beginning of the packet
185  uint16_t length = *(reinterpret_cast<uint16_t *>(rxPacket + 2));
186 
187  // if bad packet, reset
188  if (!(status & RTL_RXSTS_RXOK) ||
189  (status & (RTL_RXSTS_ISE | RTL_RXSTS_CRC | RTL_RXSTS_FAE)) ||
190  (length >= RTL_PACK_MAX) || (length < RTL_PACK_MIN))
191  {
192  WARNING(
193  "RTL8139: Bad packet: len: " << length << ", status: " << status
194  << "!");
195  reset();
196  return;
197  }
198  // create packet buffer, needed later
199  uint8_t *packBuff = new uint8_t[length - 4];
200 
201  // check if passing over the end of the buffer
202  if (m_RxCurr + length > RTL_BUFF_SIZE)
203  {
204  // copy first the part of the packet until the end of the buffer and
205  // then the rest of it, at the beginning of the buffer
206  uint32_t left = RTL_BUFF_SIZE - (m_RxCurr + 4);
207  MemoryCopy(packBuff, reinterpret_cast<void *>(rxPacket + 4), left);
208  MemoryCopy(&packBuff[left], m_pRxBuffVirt, length - 4 - left);
209 
210  // adjust current offset
211  m_RxCurr = (length - left + 3) & ~3;
212  }
213  else
214  {
215  // copy the packet
216  MemoryCopy(
217  packBuff, reinterpret_cast<void *>(rxPacket + 4), length - 4);
218 
219  // adjust current offset
220  m_RxCurr = (m_RxCurr + length + 4 + 3) & ~3;
221  }
222  // adjust current offset (it never should be over the buffer's size)
223  m_RxCurr %= RTL_BUFF_SIZE;
224 
225  // send the packet to the stack
227  length - 4, reinterpret_cast<uintptr_t>(packBuff), this, 0);
228 
229  m_RxLock = false;
230 }
231 
232 bool Rtl8139::setStationInfo(StationInfo info)
233 {
234  // free the old DNS servers list, if there is one
235  if (m_StationInfo.dnsServers)
236  delete[] m_StationInfo.dnsServers;
237 
238  // MAC isn't changeable, so set it all manually
239  m_StationInfo.ipv4 = info.ipv4;
240  NOTICE(
241  "RTL8139: Setting ipv4, " << info.ipv4.toString() << ", "
242  << m_StationInfo.ipv4.toString() << "...");
243  m_StationInfo.ipv6 = info.ipv6;
244 
245  m_StationInfo.subnetMask = info.subnetMask;
246  NOTICE(
247  "RTL8139: Setting subnet mask, " << info.subnetMask.toString() << ", "
248  << m_StationInfo.subnetMask.toString()
249  << "...");
250  m_StationInfo.gateway = info.gateway;
251  NOTICE(
252  "RTL8139: Setting gateway, " << info.gateway.toString() << ", "
253  << m_StationInfo.gateway.toString()
254  << "...");
255 
256  // Callers do not free their dnsServers memory
257  m_StationInfo.dnsServers = info.dnsServers;
258  m_StationInfo.nDnsServers = info.nDnsServers;
259  NOTICE(
260  "RTL8139: Setting DNS servers [" << Dec << m_StationInfo.nDnsServers
261  << Hex << " servers being set]...");
262 
263  return true;
264 }
265 
267 {
268  return m_StationInfo;
269 }
270 
272 {
273  return !(m_pBase->read8(RTL_MSR) & RTL_MSR_LINK);
274 }
275 
276 bool Rtl8139::irq(irq_id_t number, InterruptState &state)
277 {
278  while (true)
279  {
280  // grab the interrupt status and acknowledge it ASAP
281  uint16_t irqStatus = m_pBase->read16(RTL_ISR);
282  m_pBase->write16(irqStatus, RTL_ISR);
283 
284  // no irq left, break
285  if ((irqStatus & (RTL_ISR_RXOK | RTL_ISR_TXOK | RTL_ISR_RXERR |
286  RTL_ISR_TXERR)) == 0)
287  break;
288 
289  // RxOK, receive the packet
290  if (irqStatus & RTL_ISR_RXOK)
291  recv();
292 
293  // if rx error, reset
294  if (irqStatus & RTL_ISR_RXERR)
295  {
296  WARNING("RTL8139: Rx error!");
297  reset();
298  }
299  // if tx error, reset
300  if (irqStatus & RTL_ISR_TXERR)
301  {
302  WARNING("RTL8139: Tx error!");
303  reset();
304  }
305  }
306  return true;
307 }
static PhysicalMemoryManager & instance()
virtual bool isConnected()
Definition: Rtl8139.cc:271
virtual bool irq(irq_id_t number, InterruptState &state)
Definition: Rtl8139.cc:276
Definition: String.h:49
IpAddress gateway
Automatically calculated?
SchedulerState & state()
Definition: Thread.cc:420
void receive(size_t nBytes, uintptr_t packet, Network *pCard, uint32_t offset)
size_t nDnsServers
Can contain IPv6 addresses.
#define WARNING(text)
Definition: Log.h:78
virtual StationInfo getStationInfo()
Definition: Rtl8139.cc:266
#define NOTICE(text)
Definition: Log.h:74
Definition: Log.h:136
static NetworkStack & instance()
Definition: NetworkStack.h:47
void registerDevice(Network *pDevice)
virtual irq_id_t registerIsaIrqHandler(uint8_t irq, IrqHandler *handler, bool bEdge=false)=0
#define ERROR(text)
Definition: Log.h:82
Definition: Log.h:138
virtual bool send(size_t nBytes, uintptr_t buffer)
Definition: Rtl8139.cc:149