3 * Realtek 8139 ethernet card
5 * Copyright (C) 2009 Pawel Dziepak
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "manes/manec.h"
27 #include "services/interrupt_manager.h"
29 #include "arch/low/lowlevel.h"
30 #include "arch/low/hlt.h"
32 using namespace resources
;
34 extern p
<net::nic
> faar
;
36 bool rtl8139::init_device(p
<did
> id
) {
38 this->id
= *id
.cast
<pci_did
>();
45 bool rtl8139::check_device(p
<did
> id
) {
46 p
<pci_did
> pid
= id
.cast
<pci_did
>();
51 /* It must be an ethernet card */
52 unsigned int devclass
= pid
->get_devclass() >> 8;
53 if (devclass
!= 0x0200)
56 unsigned int devid
= pid
->get_devid();
57 /* It must be a *compatible* ethernet card */
58 if (devid
!= 0x813910ec)
64 void rtl8139::send_data(const buffer
&x
) {
69 net::mac_addr
rtl8139::get_haddr() const {
72 return net::mac_addr::from_be(*(u32
*)addr
, ((u16
*)addr
)[2]);
76 void rtl8139::irq_handler() {
77 u16 status
= id
.inw(isr
);
85 //rec.method(this, &rtl8139::receive_packet);
86 //manes::manec::get()->get<services::asynch_tasks>("/asnych_tasks")->add_task(rec);
87 } else if (status
& 2) {
88 if (!(id
.inb(cmd
) & 1))
89 asm("cli\nhlt"::"a"(0xd00d00));
98 arch::unlock_irqs(id
.irq
);
102 void rtl8139::init() {
104 manes::manec::get()->get
<services::interrupt_manager
>("/interrupt_manager")->register_interrupt(id
.irq
+ 0x20, delegate
<void>::method(this, &rtl8139::irq_handler
));
111 while (id
.inb(cmd
) & 0x10);
113 /* Prepare receive buffer */
114 rec_buffer
= new char[8192 + 16];
115 id
.outl(rbstart
, (u32
)rec_buffer
);
118 /* IRQ on Transmit OK and Receive OK */
120 id
.outw(isr
, 0xffff);
122 /* Configure receiver */
123 id
.outl(rec_conf
, (0xf | (1 << 7)) & ~(u32
)1);
125 /* Enable receiver and transmitter */
129 void rtl8139::send_packet(const buffer
&x
) {
130 assert("rtl8139: packet is too big", x
.get_size() >= 0x700);
132 id
.outl(tsad0
+ send_index
* 4, (u32
)x
.get_address());
135 id
.outl(tsd0
+ send_index
* 4, x
.get_size());
136 send_index
= (send_index
+ 1) % 4;
139 void rtl8139::receive_packet() {
140 while ((id
.inb(cmd
) & 1) == 0) {
141 packet
*pkg
= (packet
*)((u32
)rec_buffer
+ received_index
);
142 u32 size
= pkg
->size
;
143 u32 status
= pkg
->status
;
145 received_index
= (received_index
+ size
+ 4 + 3) & ~3;
146 //received_index %= 8192 + 16;
149 u8
* buf
= new u8
[size
];
150 memcpy(buf
, pkg
, size
);
153 id
.outw(capr
, received_index
- 16);
160 receiver(buffer((void*)&pkg
[1], pkg
->size
- 4));
166 void rtl8139::get_mac_addr(u8
*addr
) const {
167 for (int i
= 0; i
< 6; i
++)
172 void rtl8139::register_type() {
173 manes::manec::get()->register_driver
<rtl8139
>("rtl8139", "nic", delegate
<bool, p
<did
> >::function(&rtl8139::check_device
));