ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/Linux/NetDriver/sheep_net.c
Revision: 1.1.1.1 (vendor branch)
Committed: 1999-10-03T14:16:25Z (25 years, 1 month ago) by cebix
Content type: text/plain
Branch: cebix
CVS Tags: release-0_7-2, snapshot-21101999, start, snapshot-22121999, release-0_8-1, snapshot-02111999
Changes since 1.1: +0 -0 lines
Log Message:
Imported sources

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * sheep_net.c - Linux driver for SheepShaver/Basilisk II networking (access to raw Ethernet packets)
3     *
4     * sheep_net (C) 1999 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     }