ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/Linux/NetDriver/sheep_net.c
Revision: 1.3
Committed: 2001-02-02T20:52:58Z (23 years, 10 months ago) by cebix
Content type: text/plain
Branch: MAIN
CVS Tags: snapshot-17022001
Changes since 1.2: +1 -1 lines
Log Message:
- bumped version number to 0.9
- updated copyright dates

File Contents

# Content
1 /*
2 * sheep_net.c - Linux driver for SheepShaver/Basilisk II networking (access to raw Ethernet packets)
3 *
4 * sheep_net (C) 1999-2001 Mar"c" Hellwig and Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/version.h>
24 #include <linux/miscdevice.h>
25 #include <linux/netdevice.h>
26 #include <linux/etherdevice.h>
27 #include <linux/if_ether.h>
28 #include <linux/if_arp.h>
29 #include <linux/fs.h>
30 #include <linux/poll.h>
31 #include <linux/init.h>
32 #include <net/sock.h>
33 #include <asm/uaccess.h>
34
35 #define DEBUG 0
36
37 #define bug printk
38 #if DEBUG
39 #define D(x) (x);
40 #else
41 #define D(x) ;
42 #endif
43
44
45 // Constants
46 #define SHEEP_NET_MINOR 198 // Driver minor number
47 #define MAX_QUEUE 32 // Maximum number of packets in queue
48 #define PROT_MAGIC 1520 // Our "magic" protocol type
49
50 // Prototypes
51 static int sheep_net_open(struct inode *inode, struct file *f);
52 static int sheep_net_release(struct inode *inode, struct file *f);
53 static ssize_t sheep_net_read(struct file *f, char *buf, size_t count, loff_t *off);
54 static ssize_t sheep_net_write(struct file *f, const char *buf, size_t count, loff_t *off);
55 static unsigned int sheep_net_poll(struct file *f, struct poll_table_struct *wait);
56 static int sheep_net_ioctl(struct inode *inode, struct file *f, unsigned int code, unsigned long arg);
57 static int sheep_net_receiver(struct sk_buff *skb, struct device *dev, struct packet_type *pt);
58
59
60 /*
61 * Driver private variables
62 */
63
64 struct SheepVars {
65 struct device *ether; // The Ethernet device we're attached to
66 struct sock *skt; // Socket for communication with Ethernet card
67 struct sk_buff_head queue; // Receiver packet queue
68 struct packet_type pt; // Receiver packet type
69 struct wait_queue *wait; // Wait queue for blocking read operations
70 };
71
72
73 /*
74 * file_operations structure - has function pointers to the
75 * various entry points for device operations
76 */
77
78 static struct file_operations sheep_net_fops = {
79 NULL, // llseek
80 sheep_net_read,
81 sheep_net_write,
82 NULL, // readdir
83 sheep_net_poll,
84 sheep_net_ioctl,
85 NULL, // mmap
86 sheep_net_open,
87 NULL, // flush
88 sheep_net_release,
89 NULL, // fsync
90 NULL, // fasync
91 NULL, // check_media_change
92 NULL, // revalidate
93 NULL // lock
94 };
95
96
97 /*
98 * miscdevice structure for driver initialization
99 */
100
101 static struct miscdevice sheep_net_device = {
102 SHEEP_NET_MINOR, // minor number
103 "sheep_net", // name
104 &sheep_net_fops,
105 NULL,
106 NULL
107 };
108
109
110 /*
111 * Initialize module
112 */
113
114 int init_module(void)
115 {
116 int ret;
117
118 // Register driver
119 ret = misc_register(&sheep_net_device);
120 D(bug("Sheep net driver installed\n"));
121 return ret;
122 }
123
124
125 /*
126 * Deinitialize module
127 */
128
129 int cleanup_module(void)
130 {
131 int ret;
132
133 // Unregister driver
134 ret = misc_deregister(&sheep_net_device);
135 D(bug("Sheep net driver removed\n"));
136 return ret;
137 }
138
139
140 /*
141 * Driver open() function
142 */
143
144 static int sheep_net_open(struct inode *inode, struct file *f)
145 {
146 struct SheepVars *v;
147 D(bug("sheep_net: open\n"));
148
149 // Must be opened with read permissions
150 if ((f->f_flags & O_ACCMODE) == O_WRONLY)
151 return -EPERM;
152
153 // Allocate private variables
154 v = (struct SheepVars *)f->private_data = kmalloc(sizeof(struct SheepVars), GFP_USER);
155 if (v == NULL)
156 return -ENOMEM;
157 memset(v, 0, sizeof(struct SheepVars));
158 skb_queue_head_init(&v->queue);
159
160 // Yes, we're open
161 MOD_INC_USE_COUNT;
162 return 0;
163 }
164
165
166 /*
167 * Driver release() function
168 */
169
170 static int sheep_net_release(struct inode *inode, struct file *f)
171 {
172 struct SheepVars *v = (struct SheepVars *)f->private_data;
173 struct sk_buff *skb;
174 D(bug("sheep_net: close\n"));
175
176 // Detach from Ethernet card
177 if (v->ether) {
178 dev_remove_pack(&v->pt);
179 sk_free(v->skt);
180 v->skt = NULL;
181 v->ether = NULL;
182 }
183
184 // Empty packet queue
185 while ((skb = skb_dequeue(&v->queue)) != NULL)
186 dev_kfree_skb(skb);
187
188 // Free private variables
189 kfree(v);
190
191 // Sorry, we're closed
192 MOD_DEC_USE_COUNT;
193 return 0;
194 }
195
196
197 /*
198 * Driver read() function
199 */
200
201 static ssize_t sheep_net_read(struct file *f, char *buf, size_t count, loff_t *off)
202 {
203 struct SheepVars *v = (struct SheepVars *)f->private_data;
204 struct sk_buff *skb;
205 sigset_t sigs;
206 int i;
207 D(bug("sheep_net: read\n"));
208
209 for (;;) {
210
211 // Get next packet from queue
212 start_bh_atomic();
213 skb = skb_dequeue(&v->queue);
214 end_bh_atomic();
215 if (skb != NULL || (f->f_flags & O_NONBLOCK))
216 break;
217
218 // No packet in queue and in blocking mode, so block
219 interruptible_sleep_on(&v->wait);
220
221 // Signal received? Then bail out
222 signandsets(&sigs, &current->signal, &current->blocked);
223 for (i=0; i<_NSIG_WORDS; i++) {
224 if (sigs.sig[i])
225 return -EINTR;
226 }
227 }
228 if (skb == NULL)
229 return -EAGAIN;
230
231 // Pass packet to caller
232 if (count > skb->len)
233 count = skb->len;
234 if (copy_to_user(buf, skb->data, count))
235 count = -EFAULT;
236 dev_kfree_skb(skb);
237 return count;
238 }
239
240
241 /*
242 * Driver write() function
243 */
244
245 static ssize_t sheep_net_write(struct file *f, const char *buf, size_t count, loff_t *off)
246 {
247 struct SheepVars *v = (struct SheepVars *)f->private_data;
248 struct sk_buff *skb;
249 char *p;
250 D(bug("sheep_net: write\n"));
251
252 // Check packet size
253 if (count < sizeof(struct ethhdr))
254 return -EINVAL;
255 if (count > 1514)
256 count = 1514;
257
258 // Interface active?
259 if (v->ether == NULL)
260 return count;
261
262 // Allocate buffer for packet
263 skb = dev_alloc_skb(count);
264 if (skb == NULL)
265 return -ENOBUFS;
266
267 // Stuff packet in buffer
268 p = skb_put(skb, count);
269 if (copy_from_user(p, buf, count)) {
270 kfree_skb(skb);
271 return -EFAULT;
272 }
273
274 // Transmit packet
275 dev_lock_list();
276 atomic_add(skb->truesize, &v->skt->wmem_alloc);
277 skb->sk = v->skt;
278 skb->dev = v->ether;
279 skb->priority = 0;
280 skb->protocol = PROT_MAGIC; // "Magic" protocol value to recognize our packets in sheep_net_receiver()
281 skb->nh.raw = skb->h.raw = skb->data + v->ether->hard_header_len;
282 dev_unlock_list();
283 dev_queue_xmit(skb);
284 return count;
285 }
286
287
288 /*
289 * Driver poll() function
290 */
291
292 static unsigned int sheep_net_poll(struct file *f, struct poll_table_struct *wait)
293 {
294 struct SheepVars *v = (struct SheepVars *)f->private_data;
295 D(bug("sheep_net: poll\n"));
296
297 // Packets in queue? Then return
298 start_bh_atomic();
299 if (!skb_queue_empty(&v->queue)) {
300 end_bh_atomic();
301 return POLLIN | POLLRDNORM;
302 }
303
304 // Otherwise wait for packet
305 poll_wait(f, &v->wait, wait);
306 if (!skb_queue_empty(&v->queue)) {
307 end_bh_atomic();
308 return POLLIN | POLLRDNORM;
309 } else {
310 end_bh_atomic();
311 return 0;
312 }
313 }
314
315
316 /*
317 * Driver ioctl() function
318 */
319
320 static int sheep_net_ioctl(struct inode *inode, struct file *f, unsigned int code, unsigned long arg)
321 {
322 struct SheepVars *v = (struct SheepVars *)f->private_data;
323 D(bug("sheep_net: ioctl %04x\n", code));
324
325 switch (code) {
326
327 // Attach to Ethernet card
328 // arg: pointer to name of Ethernet device (char[8])
329 case SIOCSIFLINK: {
330 char name[8];
331
332 // Already attached?
333 if (v->ether)
334 return -EBUSY;
335
336 // Get Ethernet card name
337 if (copy_from_user(name, (void *)arg, 8))
338 return -EFAULT;
339 name[7] = 0;
340
341 // Find card
342 dev_lock_list();
343 v->ether = dev_get(name);
344 if (v->ether == NULL) {
345 dev_unlock_list();
346 return -ENODEV;
347 }
348
349 // Is it Ethernet?
350 if (v->ether->type != ARPHRD_ETHER) {
351 v->ether = NULL;
352 dev_unlock_list();
353 return -EINVAL;
354 }
355
356 // Allocate socket
357 v->skt = sk_alloc(0, GFP_USER, 1);
358 if (v->skt == NULL) {
359 v->ether = NULL;
360 dev_unlock_list();
361 return -ENOMEM;
362 }
363 v->skt->dead = 1;
364
365 // Attach packet handler
366 v->pt.type = htons(ETH_P_ALL);
367 v->pt.dev = v->ether;
368 v->pt.func = sheep_net_receiver;
369 v->pt.data = v;
370 dev_add_pack(&v->pt);
371 dev_unlock_list();
372 return 0;
373 }
374
375 // Get hardware address of Ethernet card
376 // arg: pointer to buffer (6 bytes) to store address
377 case SIOCGIFADDR:
378 if (v->ether == NULL)
379 return -ENODEV;
380 if (copy_to_user((void *)arg, v->ether->dev_addr, 6))
381 return -EFAULT;
382 return 0;
383
384 // Add multicast address
385 // arg: pointer to address (6 bytes)
386 case SIOCADDMULTI: {
387 char addr[6];
388 if (v->ether == NULL)
389 return -ENODEV;
390 if (copy_from_user(addr, (void *)arg, 6))
391 return -EFAULT;
392 return dev_mc_add(v->ether, addr, 6, 0);
393 }
394
395 // Remove multicast address
396 // arg: pointer to address (6 bytes)
397 case SIOCDELMULTI: {
398 char addr[6];
399 if (v->ether == NULL)
400 return -ENODEV;
401 if (copy_from_user(addr, (void *)arg, 6))
402 return -EFAULT;
403 return dev_mc_delete(v->ether, addr, 6, 0);
404 }
405
406 // Return size of first packet in queue
407 case FIONREAD: {
408 int count = 0;
409 struct sk_buff *skb;
410 start_bh_atomic();
411 skb = skb_peek(&v->queue);
412 if (skb)
413 count = skb->len;
414 end_bh_atomic();
415 return put_user(count, (int *)arg);
416 }
417
418 default:
419 return -ENOIOCTLCMD;
420 }
421 }
422
423
424 /*
425 * Packet receiver function
426 */
427
428 static int sheep_net_receiver(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
429 {
430 struct SheepVars *v = (struct SheepVars *)pt->data;
431 D(bug("sheep_net: packet received\n"));
432
433 // Packet sent by us? Then discard
434 if (skb->protocol == PROT_MAGIC) {
435 kfree_skb(skb);
436 return 0;
437 }
438
439 // Discard packets if queue gets too full
440 if (skb_queue_len(&v->queue) > MAX_QUEUE) {
441 kfree_skb(skb);
442 return 0;
443 }
444
445 // We also want the Ethernet header
446 skb_push(skb, skb->data - skb->mac.raw);
447
448 // Enqueue packet
449 start_bh_atomic();
450 skb_queue_tail(&v->queue, skb);
451 end_bh_atomic();
452
453 // Unblock blocked read
454 wake_up(&v->wait);
455 return 0;
456 }