ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/BeOS/SheepNet/sheep_net.cpp
Revision: 1.5
Committed: 2008-01-01T09:40:32Z (16 years, 10 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +2 -2 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * sheep_net.cpp - Net server add-on for SheepShaver and Basilisk II
3     *
4 gbeauche 1.5 * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer
5     * Basilisk II (C) 1997-2008 Christian Bauer
6 cebix 1.1 *
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.
11     *
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.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     #include <KernelKit.h>
23     #include <SupportKit.h>
24     #include <add-ons/net_server/NetDevice.h>
25     #include <add-ons/net_server/NetProtocol.h>
26     #include <stdio.h>
27     #include <stdlib.h>
28     #include <stdarg.h>
29     #include <string.h>
30     #include <time.h>
31    
32     #include "sheep_net.h"
33    
34     #define DEBUG 0
35    
36     #if DEBUG==1
37     #define bug pprintf
38     #elif DEBUG==2
39     #define bug kprintf
40     #endif
41    
42     #if DEBUG
43     #define D(x) (x)
44     #else
45     #define D(x) ;
46     #endif
47    
48     static int pprintf(const char* format, ...)
49     {
50     port_id PortNum;
51     int len,Ret;
52     char Buffer[1024];
53     va_list ap;
54    
55     if ((PortNum = find_port("PortLogger")) == B_NAME_NOT_FOUND)
56     return(PortNum);
57     for (len=0; len<1024; len++)
58     Buffer[len]='\0';
59     va_start(ap, format);
60     vsprintf(Buffer, format, ap);
61     Ret = write_port(PortNum, 0, Buffer, strlen(Buffer));
62     return(Ret);
63     }
64    
65    
66     // Constants
67     #define NETDUMP_PRIO 1 // Default is 0
68    
69     const uint32 buffer_size = (sizeof(net_buffer) / B_PAGE_SIZE + 1) * B_PAGE_SIZE;
70    
71    
72     // SheepNet add-on object
73     class SheepNetAddOn : public BNetProtocol, BPacketHandler {
74     public:
75     void AddDevice(BNetDevice *dev, const char *name);
76     bool PacketReceived(BNetPacket *buf, BNetDevice *dev);
77     };
78    
79    
80     // Global variables
81     static bool shutdown_now = false;
82     static bool active = false;
83    
84     static thread_id write_thread; // Packet writer
85     static sem_id write_sem; // Semaphore to trigger packet writing
86     static BNetDevice *EtherCard = NULL; // The Ethernet card we are attached to
87     static area_id buffer_area; // Packet buffer area
88     static net_buffer *net_buffer_ptr; // Pointer to packet buffer
89    
90     static uint32 rd_pos; // Current read position in packet buffer
91     static uint32 wr_pos; // Current write position in packet buffer
92    
93    
94     /*
95     * Clear packet buffer
96     */
97    
98     static void clear(void)
99     {
100     int i;
101     for (i=0;i<READ_PACKET_COUNT;i++) {
102     net_buffer_ptr->read[i].cmd = 0;
103     net_buffer_ptr->read[i].length = 0;
104     net_buffer_ptr->read[i].card = 0;
105     net_buffer_ptr->read[i].reserved = 0;
106     }
107     for (i=0;i<WRITE_PACKET_COUNT;i++) {
108     net_buffer_ptr->write[i].cmd = 0;
109     net_buffer_ptr->write[i].length = 0;
110     net_buffer_ptr->write[i].card = 0;
111     net_buffer_ptr->write[i].reserved = 0;
112     }
113     rd_pos = wr_pos = 0;
114     }
115    
116    
117     /*
118     * Packet writer thread
119     */
120    
121     static status_t write_packet_func(void *arg)
122     {
123     while (!shutdown_now) {
124    
125     // Read and execute command
126     net_packet *p = &net_buffer_ptr->write[wr_pos];
127     while (p->cmd & IN_USE) {
128     D(bug("wp: %d\n", wr_pos));
129     switch (p->cmd >> 8) {
130    
131     case ACTIVATE_SHEEP_NET:
132     D(bug("activate sheep-net\n"));
133     active = false;
134     clear();
135     active = true;
136     goto next;
137    
138     case DEACTIVATE_SHEEP_NET:
139     D(bug("deactivate sheep-net\n"));
140     active = false;
141     clear();
142     goto next;
143    
144     case SHUTDOWN_SHEEP_NET:
145     D(bug("shutdown sheep-net\n"));
146     active = false;
147     clear();
148     shutdown_now = true;
149     goto next;
150    
151     case ADD_MULTICAST: {
152     const char *data = (const char *)p->data;
153     D(bug("add multicast %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5]));
154     if (active) {
155     status_t result;
156     if ((result = EtherCard->AddMulticastAddress(data)) != B_OK) {
157     // !! handle error !! error while creating multicast address
158     D(bug("error while creating multicast address %d\n", result));
159     }
160     }
161     break;
162     }
163    
164     case REMOVE_MULTICAST: {
165     const char *data = (const char *)p->data;
166     D(bug("remove multicast %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5]));
167     if (active) {
168     status_t result;
169     if ((result = EtherCard->RemoveMulticastAddress(data)) != B_OK) {
170     // !! handle error !! error while removing multicast address
171     D(bug("error while removing multicast address %d\n", result));
172     }
173     }
174     break;
175     }
176    
177     case SHEEP_PACKET: {
178     uint32 length = p->length;
179     // D(bug("sheep packet %d\n", length));
180     if (active) {
181     BStandardPacket *packet = new BStandardPacket(length);
182     packet->Write(0, (const char *)p->data, length);
183     EtherCard->SendPacket(packet);
184     }
185     break;
186     }
187    
188     default:
189     D(bug("error: unknown port packet type\n"));
190     break;
191     }
192     p->cmd = 0; // Free packet
193     wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT;
194     p = &net_buffer_ptr->write[wr_pos];
195     }
196    
197     // Wait for next packet
198     next: acquire_sem_etc(write_sem, 1, B_TIMEOUT, 25000);
199     }
200     return 0;
201     }
202    
203    
204     /*
205     * Init the net add-on
206     */
207    
208     static void init_addon()
209     {
210     int i;
211     D(bug("init sheep-net\n"));
212    
213     // Create packet buffer
214 cebix 1.2 if ((buffer_area = create_area("packet buffer", (void **)&net_buffer_ptr, B_ANY_ADDRESS, buffer_size, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA)) < B_NO_ERROR) {
215 cebix 1.1 D(bug("FATAL ERROR: can't create shared area\n"));
216     return;
217     }
218    
219     // Init packet buffer
220     clear();
221     EtherCard->Address((char *)net_buffer_ptr->ether_addr);
222     net_buffer_ptr->read_sem = -1;
223     net_buffer_ptr->read_ofs = (uint32)(net_buffer_ptr->read) - (uint32)net_buffer_ptr;
224     net_buffer_ptr->read_packet_size = sizeof(net_packet);
225     net_buffer_ptr->read_packet_count = READ_PACKET_COUNT;
226     if ((write_sem = create_sem(0, "ether write")) < B_NO_ERROR) {
227     D(bug("FATAL ERROR: can't create semaphore\n"));
228     return;
229     }
230     net_buffer_ptr->write_sem = write_sem;
231     net_buffer_ptr->write_ofs = (uint32)(net_buffer_ptr->write) - (uint32)net_buffer_ptr;
232     net_buffer_ptr->write_packet_size = sizeof(net_packet);
233     net_buffer_ptr->write_packet_count = WRITE_PACKET_COUNT;
234    
235     // Start packet writer thread
236     write_thread = spawn_thread(write_packet_func, "sheep_net ether write", B_URGENT_DISPLAY_PRIORITY, NULL);
237     resume_thread(write_thread);
238     }
239    
240    
241     /*
242     * Add-on attached to Ethernet card
243     */
244    
245     void SheepNetAddOn::AddDevice(BNetDevice *dev, const char *name)
246     {
247     if (dev->Type() != B_ETHER_NET_DEVICE)
248     return;
249     if (EtherCard != NULL) {
250     // !! handle error !! support for multiple ethernet cards ...
251     D(bug("error: SheepShaver doesn't support multiple Ethernetcards !\n"));
252     return;
253     }
254     EtherCard = dev;
255     init_addon();
256     register_packet_handler(this, dev, NETDUMP_PRIO);
257     }
258    
259    
260     /*
261     * Ethernet packet received
262     */
263    
264     bool SheepNetAddOn::PacketReceived(BNetPacket *pkt, BNetDevice *dev)
265     {
266     if (shutdown_now) {
267     unregister_packet_handler(this, dev);
268     return false;
269     }
270     // D(bug("read_packet_func %d\n", pkt->Size()));
271     if (active) {
272     D(bug("rp: %d\n", rd_pos));
273     net_packet *p = &net_buffer_ptr->read[rd_pos];
274     if (p->cmd & IN_USE) {
275     D(bug("error: full read buffer ... lost packet\n"));
276     } else {
277     memcpy(p->data, pkt->Data(), pkt->Size());
278     p->length = pkt->Size();
279     p->cmd = IN_USE | (SHEEP_PACKET << 8);
280     rd_pos = (rd_pos + 1) % READ_PACKET_COUNT;
281     release_sem(net_buffer_ptr->read_sem);
282     }
283     }
284     //D(bug("%02x %02x %02x %02x %02x %02x", (uchar) (pkt->Data())[0],(uchar) (pkt->Data())[1],(uchar) (pkt->Data())[2],(uchar) (pkt->Data())[3],(uchar) (pkt->Data())[4],(uchar) (pkt->Data())[5]));
285     return false;
286     }
287    
288     #pragma export on
289     extern "C" BNetProtocol *open_protocol(const char *device)
290     {
291     SheepNetAddOn *dev = new SheepNetAddOn;
292     return dev;
293     }
294     #pragma export off