ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/BeOS/SheepNet/sheep_net.cpp
Revision: 1.3
Committed: 2001-03-31T11:44:48Z (23 years, 7 months ago) by cebix
Branch: MAIN
CVS Tags: snapshot-29052001, release-0_9-1
Changes since 1.2: +2 -2 lines
Log Message:
updated copyright dates

File Contents

# Content
1 /*
2 * sheep_net.cpp - Net server add-on for SheepShaver and Basilisk II
3 *
4 * SheepShaver (C) 1997-2001 Mar"c" Hellwig and Christian Bauer
5 * Basilisk II (C) 1997-2001 Christian Bauer
6 *
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 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 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