netdevmedium compiles
[akaros.git] / kern / src / net / netdevmedium.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 static void     netdevbind(struct Ipifc *ifc, int argc, char **argv);
17 static void     netdevunbind(struct Ipifc *ifc);
18 static void     netdevbwrite(struct Ipifc *ifc, struct block *bp, int version,
19                                 uint8_t *ip);
20 static void     netdevread(void *a);
21
22 typedef struct  Netdevrock Netdevrock;
23 struct Netdevrock
24 {
25         struct Fs       *f;             /* file system we belong to */
26         struct proc     *readp;         /* reading process */
27         struct chan     *mchan;         /* Data channel */
28 };
29
30 struct medium netdevmedium =
31 {
32 .name=          "netdev",
33 .hsize=         0,
34 .mintu= 0,
35 .maxtu= 64000,
36 .maclen=        0,
37 .bind=          netdevbind,
38 .unbind=        netdevunbind,
39 .bwrite=        netdevbwrite,
40 .unbindonclose= 0,
41 };
42
43 /*
44  *  called to bind an IP ifc to a generic network device
45  *  called with ifc qlock'd
46  */
47 static void
48 netdevbind(struct Ipifc *ifc, int argc, char **argv)
49 {
50         struct chan *mchan;
51         Netdevrock *er;
52
53         if(argc < 2)
54                 error(Ebadarg);
55
56         mchan = namec(argv[2], Aopen, ORDWR, 0);
57
58         er = kzmalloc(sizeof(*er), 0);
59         er->mchan = mchan;
60         er->f = ifc->conv->p->f;
61
62         ifc->arg = er;
63
64         kproc("netdevread", netdevread, ifc, 0);
65 }
66
67 /*
68  *  called with ifc wlock'd
69  */
70 static void
71 netdevunbind(struct Ipifc *ifc)
72 {
73         Netdevrock *er = ifc->arg;
74 /*
75         if(er->readp != NULL)
76                 postnote(er->readp, 1, "unbind", 0);
77 */
78         /* wait for readers to die *
79         while(er->readp != NULL)
80         tsleep(&up->sleep, return0, 0, 300);*/
81
82         if(er->mchan != NULL)
83                 cclose(er->mchan);
84
85         kfree(er);
86 }
87
88 /*
89  *  called by ipoput with a single block to write
90  */
91 static void
92 netdevbwrite(struct Ipifc *ifc, struct block *bp, int unused_int, uint8_t *unused_uint8_p_t)
93 {
94         Netdevrock *er = ifc->arg;
95
96         if(bp->next)
97                 bp = concatblock(bp);
98         if(BLEN(bp) < ifc->mintu)
99                 bp = adjustblock(bp, ifc->mintu);
100
101         devtab[er->mchan->type]->bwrite(er->mchan, bp, 0);
102         ifc->out++;
103 }
104
105 /*
106  *  process to read from the device
107  */
108 static void
109 netdevread(void *a)
110 {
111         ERRSTACK(2);
112         struct Ipifc *ifc;
113         struct block *bp;
114         Netdevrock *er;
115         char *argv[1];
116
117         ifc = a;
118         er = ifc->arg;
119         er->readp = current;    /* hide identity under a rock for unbind */
120         if(waserror()){
121                 er->readp = NULL;
122                 //      pexit("hangup", 1);
123         }
124         for(;;){
125                 bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);
126                 if(bp == NULL){
127                         /*
128                          * get here if mchan is a pipe and other side hangs up
129                          * clean up this interface & get out
130 ZZZ is this a good idea?
131                          */
132                         poperror();
133                         er->readp = NULL;
134                         argv[0] = "unbind";
135                         if(!waserror())
136                                 ifc->conv->p->ctl(ifc->conv, argv, 1);
137                         //              pexit("hangup", 1);
138                 }
139                 if(!canrlock(&ifc->rwlock)){
140                         freeb(bp);
141                         continue;
142                 }
143                 if(waserror()){
144                         runlock(&ifc->rwlock);
145                         nexterror();
146                 }
147                 ifc->in++;
148                 if(ifc->lifc == NULL)
149                         freeb(bp);
150                 else
151                         ipiput4(er->f, ifc, bp);
152                 runlock(&ifc->rwlock);
153                 poperror();
154         }
155 }
156
157 void
158 netdevmediumlink(void)
159 {
160         addipmedium(&netdevmedium);
161 }