2ea4506c42956261b1cdb3cbee259c561646c5f0
[tpg/acess2.git] / KernelLand / Modules / Interfaces / UDI / trans / nsr.c
1 /*
2  * Acess2 UDI Layer
3  * - By John Hodge (thePowersGang)
4  *
5  * trans/nsr.c
6  * - "Network Service Requester" (UDI->IP Translation)
7  */
8 #define DEBUG   1
9 #include <udi.h>
10 #include <udi_nic.h>
11 #include <acess.h>
12 #include <trans_nsr.h>
13 #include <IPStack/include/adapters_api.h>
14 #include <workqueue.h>
15
16 #define NUM_RX_BUFFERS  4
17
18 enum {
19         ACESSNSR_OPS_CTRL = 1,
20         ACESSNSR_OPS_TX,
21         ACESSNSR_OPS_RX,
22 };
23 enum {
24         ACESSNSR_META_NIC = 1
25 };
26 enum {
27         ACESSNSR_CB_CTRL = 1,
28         ACESSNSR_CB_RX,
29         ACESSNSR_CB_TX
30 };
31
32 // === TYPES ===
33 typedef struct
34 {
35         udi_init_context_t      init_context;   
36         udi_cb_t        *active_cb;
37
38         udi_index_t     init_idx;
39         udi_buf_t       *rx_buffers[NUM_RX_BUFFERS];
40         udi_nic_rx_cb_t *rx_cbs[NUM_RX_BUFFERS];
41
42         tWorkqueue      RXQueue;
43
44         tIPStack_AdapterType    AdapterType;
45         void    *ipstack_handle;
46         
47         udi_channel_t   rx_channel;
48         udi_channel_t   tx_channel;
49 } acessnsr_rdata_t;
50
51 // === PROTOTYPES ===
52 // --- Management metalang
53 void acessnsr_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level);
54 void acessnsr_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID);
55 void acessnsr_final_cleanup_req(udi_mgmt_cb_t *cb);
56 // --- NSR Control
57 void acessnsr_ctrl_channel_event_ind(udi_channel_event_cb_t *cb);
58 void acessnsr_ctrl_ch_ev_ind__rx_channel_spawned(udi_cb_t *gcb, udi_channel_t channel);
59 void acessnsr_ctrl_ch_ev_ind__tx_channel_spawned(udi_cb_t *gcb, udi_channel_t channel);
60 void acessnsr_ctrl_bind_ack(udi_nic_bind_cb_t *cb, udi_status_t status);
61 void acessnsr_ctrl_bind_ack__rx_buf_allocated(udi_cb_t *gcb, udi_buf_t *new_buf);
62 void acessnsr_ctrl_bind_ack__rx_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb);
63 void acessnsr_ctrl_unbind_ack(udi_nic_cb_t *cb, udi_status_t status);
64 void acessnsr_ctrl_enable_ack(udi_nic_cb_t *cb, udi_status_t status);
65 void acessnsr_ctrl_disable_ack(udi_nic_cb_t *cb, udi_status_t status);
66 void acessnsr_ctrl_ctrl_ack(udi_nic_ctrl_cb_t *cb, udi_status_t status);
67 void acessnsr_ctrl_status_ind(udi_nic_status_cb_t *cb);
68 void acessnsr_ctrl_info_ack(udi_nic_info_cb_t *cb);
69 // --- NSR TX
70 void acessnsr_tx_channel_event_ind(udi_channel_event_cb_t *cb);
71 void acessnsr_tx_rdy(udi_nic_tx_cb_t *cb);
72 // --- NSR RX
73 void acessnsr_rx_channel_event_ind(udi_channel_event_cb_t *cb);
74 void acessnsr_rx_ind(udi_nic_rx_cb_t *cb);
75 void acessnsr_rx_exp_ind(udi_nic_rx_cb_t *cb);
76 // --- Acess IPStack
77  int    acessnsr_SendPacket(void *Card, tIPStackBuffer *Buffer);
78 tIPStackBuffer  *acessnsr_WaitForPacket(void *Card);
79
80 // === CODE ===
81 // --- Management metalang
82 void acessnsr_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level)
83 {
84         acessnsr_rdata_t *rdata = UDI_GCB(cb)->context;
85         switch(resource_level)
86         {
87         }
88
89         Workqueue_Init(&rdata->RXQueue, "AcessNSR RX", offsetof(udi_nic_rx_cb_t, chain));
90
91         udi_usage_res(cb);
92 }
93 void acessnsr_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID)
94 {
95         UNIMPLEMENTED();
96 }
97 void acessnsr_final_cleanup_req(udi_mgmt_cb_t *cb)
98 {
99         UNIMPLEMENTED();
100 }
101 // --- NSR Control
102 void acessnsr_ctrl_channel_event_ind(udi_channel_event_cb_t *cb)
103 {
104         acessnsr_rdata_t *rdata = UDI_GCB(cb)->context;
105         switch(cb->event)
106         {
107         case UDI_CHANNEL_CLOSED:
108                 break;
109         case UDI_CHANNEL_BOUND: {
110                 rdata->active_cb = UDI_GCB(cb);
111                 udi_channel_spawn(acessnsr_ctrl_ch_ev_ind__rx_channel_spawned,
112                         cb->params.parent_bound.bind_cb, UDI_GCB(cb)->channel,
113                         1, ACESSNSR_OPS_RX, rdata);
114                 // V V V V
115                 break; }
116         }
117 }
118 void acessnsr_ctrl_ch_ev_ind__rx_channel_spawned(udi_cb_t *gcb, udi_channel_t channel)
119 {
120         acessnsr_rdata_t *rdata = gcb->context;
121         rdata->rx_channel = channel;
122         udi_channel_spawn(acessnsr_ctrl_ch_ev_ind__tx_channel_spawned, gcb, gcb->channel,
123                 2, ACESSNSR_OPS_TX, rdata);
124         // V V V V
125 }
126 void acessnsr_ctrl_ch_ev_ind__tx_channel_spawned(udi_cb_t *gcb, udi_channel_t channel)
127 {
128         acessnsr_rdata_t *rdata = gcb->context;
129         rdata->tx_channel = channel;
130         udi_nic_bind_cb_t *bind_cb = UDI_MCB(gcb, udi_nic_bind_cb_t);
131         udi_nd_bind_req(bind_cb, 2, 1);
132         // V V V V
133 }
134 void acessnsr_ctrl_bind_ack(udi_nic_bind_cb_t *cb, udi_status_t status)
135 {
136         acessnsr_rdata_t *rdata = UDI_GCB(cb)->context;
137         // TODO: Parse cb and register with IPStack
138         // - Pass on capabilities and media type
139         switch(cb->media_type)
140         {
141         case UDI_NIC_ETHER:     rdata->AdapterType.Type = ADAPTERTYPE_ETHERNET_10M;     break;
142         case UDI_NIC_FASTETHER: rdata->AdapterType.Type = ADAPTERTYPE_ETHERNET_100M;    break;
143         case UDI_NIC_GIGETHER:  rdata->AdapterType.Type = ADAPTERTYPE_ETHERNET_1G;      break;
144         default:
145                 udi_channel_event_complete( UDI_MCB(rdata->active_cb,udi_channel_event_cb_t), UDI_OK );
146                 break;
147         }
148
149         if(cb->capabilities & UDI_NIC_CAP_TX_IP_CKSUM)
150                 rdata->AdapterType.Flags |= ADAPTERFLAG_OFFLOAD_IP4;
151         if(cb->capabilities & UDI_NIC_CAP_TX_TCP_CKSUM)
152                 rdata->AdapterType.Flags |= ADAPTERFLAG_OFFLOAD_TCP;
153         if(cb->capabilities & UDI_NIC_CAP_TX_UDP_CKSUM)
154                 rdata->AdapterType.Flags |= ADAPTERFLAG_OFFLOAD_UDP;
155         
156         rdata->AdapterType.Name = "udi";
157         rdata->AdapterType.SendPacket = acessnsr_SendPacket;
158         rdata->AdapterType.WaitForPacket = acessnsr_WaitForPacket;
159
160         rdata->ipstack_handle = IPStack_Adapter_Add(&rdata->AdapterType, rdata, cb->mac_addr);
161
162         // Allocate RX CBs and buffers
163         rdata->init_idx = -1;
164         acessnsr_ctrl_bind_ack__rx_buf_allocated(rdata->active_cb, NULL);
165         // V V V V
166 }
167 void acessnsr_ctrl_bind_ack__rx_buf_allocated(udi_cb_t *gcb, udi_buf_t *new_buf)
168 {
169         acessnsr_rdata_t *rdata = gcb->context;
170         if( rdata->init_idx != (udi_index_t)-1 )
171         {
172                 rdata->rx_buffers[rdata->init_idx] = new_buf;
173         }
174         rdata->init_idx ++;
175         if( rdata->init_idx < NUM_RX_BUFFERS )
176         {
177                 UDI_BUF_ALLOC(acessnsr_ctrl_bind_ack__rx_buf_allocated, gcb, NULL, 0, NULL);
178                 // A A A A
179                 return ;
180         }
181         
182         rdata->init_idx = -1;
183         acessnsr_ctrl_bind_ack__rx_cb_allocated(gcb, NULL);
184 }
185 void acessnsr_ctrl_bind_ack__rx_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb)
186 {
187         acessnsr_rdata_t *rdata = gcb->context;
188         if( rdata->init_idx != (udi_index_t)-1 )
189         {
190                 udi_nic_rx_cb_t *cb = UDI_MCB(new_cb, udi_nic_rx_cb_t);
191                 rdata->rx_cbs[rdata->init_idx] = cb;
192                 cb->rx_buf = rdata->rx_buffers[rdata->init_idx];
193                 udi_nd_rx_rdy(cb);
194         }
195         rdata->init_idx ++;
196         if( rdata->init_idx < NUM_RX_BUFFERS )
197         {
198                 udi_cb_alloc(acessnsr_ctrl_bind_ack__rx_cb_allocated, gcb, ACESSNSR_CB_RX, rdata->rx_channel);
199                 // A A A A
200                 return ;
201         }
202         udi_channel_event_complete( UDI_MCB(rdata->active_cb,udi_channel_event_cb_t), UDI_OK );
203         // = = = =
204 }
205 void acessnsr_ctrl_unbind_ack(udi_nic_cb_t *cb, udi_status_t status)
206 {
207         UNIMPLEMENTED();
208 }
209 void acessnsr_ctrl_enable_ack(udi_nic_cb_t *cb, udi_status_t status)
210 {
211         UNIMPLEMENTED();
212 }
213 void acessnsr_ctrl_disable_ack(udi_nic_cb_t *cb, udi_status_t status)
214 {
215         UNIMPLEMENTED();
216 }
217 void acessnsr_ctrl_ctrl_ack(udi_nic_ctrl_cb_t *cb, udi_status_t status)
218 {
219         UNIMPLEMENTED();
220 }
221 void acessnsr_ctrl_status_ind(udi_nic_status_cb_t *cb)
222 {
223         UNIMPLEMENTED();
224 }
225 void acessnsr_ctrl_info_ack(udi_nic_info_cb_t *cb)
226 {
227         UNIMPLEMENTED();
228 }
229 // --- NSR TX
230 void acessnsr_tx_channel_event_ind(udi_channel_event_cb_t *cb)
231 {
232         UNIMPLEMENTED();
233 }
234 void acessnsr_tx_rdy(udi_nic_tx_cb_t *cb)
235 {
236         UNIMPLEMENTED();
237 }
238 // --- NSR RX
239 void acessnsr_rx_channel_event_ind(udi_channel_event_cb_t *cb)
240 {
241         UNIMPLEMENTED();
242 }
243 void acessnsr_rx_ind(udi_nic_rx_cb_t *cb)
244 {
245         acessnsr_rdata_t *rdata = UDI_GCB(cb)->context;
246         udi_nic_rx_cb_t *next;
247         do {
248                 next = cb->chain;
249                 Workqueue_AddWork(&rdata->RXQueue, cb);
250         } while( (cb = next) );
251 }
252 void acessnsr_rx_exp_ind(udi_nic_rx_cb_t *cb)
253 {
254         UNIMPLEMENTED();
255 }
256 // --- Acess IPStack
257 int acessnsr_SendPacket(void *Card, tIPStackBuffer *Buffer)
258 {
259         UNIMPLEMENTED();
260         return 1;
261 }
262 void _FreeHeapSubBuf(void *Arg, size_t Pre, size_t Post, const void *DataBuf)
263 {
264         free(Arg);
265 }
266 tIPStackBuffer *acessnsr_WaitForPacket(void *Card)
267 {
268         acessnsr_rdata_t *rdata = Card;
269         udi_nic_rx_cb_t *cb = Workqueue_GetWork(&rdata->RXQueue);
270
271         tIPStackBuffer  *ret = IPStack_Buffer_CreateBuffer(1);
272         void    *data = malloc( cb->rx_buf->buf_size );
273         udi_buf_read(cb->rx_buf, 0, cb->rx_buf->buf_size, data);
274         IPStack_Buffer_AppendSubBuffer(ret, cb->rx_buf->buf_size, 0, data, _FreeHeapSubBuf, data);
275
276         udi_nd_rx_rdy(cb);
277         return ret;
278 }
279
280 // === UDI Bindings ===
281 udi_mgmt_ops_t  acessnsr_mgmt_ops = {
282         acessnsr_usage_ind,
283         udi_enumerate_no_children,
284         acessnsr_devmgmt_req,
285         acessnsr_final_cleanup_req
286 };
287 udi_ubit8_t     acessnsr_mgmt_ops_flags[4] = {0,0,0,0};
288
289 udi_primary_init_t      acessnsr_pri_init = {
290         .mgmt_ops = &acessnsr_mgmt_ops,
291         .mgmt_op_flags = acessnsr_mgmt_ops_flags,
292         .mgmt_scratch_requirement = 0,
293         .enumeration_attr_list_length = 4,
294         .rdata_size = sizeof(acessnsr_rdata_t),
295         .child_data_size = 0,
296         .per_parent_paths = 0
297 };
298
299 udi_nsr_ctrl_ops_t      acessnsr_ctrl_ops = {
300         acessnsr_ctrl_channel_event_ind,
301         acessnsr_ctrl_bind_ack,
302         acessnsr_ctrl_unbind_ack,
303         acessnsr_ctrl_enable_ack,
304         acessnsr_ctrl_ctrl_ack,
305         acessnsr_ctrl_info_ack,
306         acessnsr_ctrl_status_ind
307 };
308 udi_ubit8_t     acessnsr_ctrl_op_flags[7] = {0};
309
310 udi_nsr_tx_ops_t        acessnsr_tx_ops = {
311         acessnsr_tx_channel_event_ind,
312         acessnsr_tx_rdy
313 };
314 udi_ubit8_t     acessnsr_tx_ops_flags[2] = {0};
315
316 udi_nsr_rx_ops_t        acessnsr_rx_ops = {
317         acessnsr_rx_channel_event_ind,
318         acessnsr_rx_ind,
319         acessnsr_rx_exp_ind
320 };
321 udi_ubit8_t     acessnsr_rx_ops_flags[3] = {0};
322
323 udi_ops_init_t  acessnsr_ops_list[] = {
324         {
325                 ACESSNSR_OPS_CTRL, ACESSNSR_META_NIC, UDI_NSR_CTRL_OPS_NUM,
326                 0, (udi_ops_vector_t*)&acessnsr_ctrl_ops, acessnsr_ctrl_op_flags
327         },
328         {
329                 ACESSNSR_OPS_TX, ACESSNSR_META_NIC, UDI_NSR_TX_OPS_NUM,
330                 0, (udi_ops_vector_t*)&acessnsr_tx_ops, acessnsr_tx_ops_flags
331         },
332         {
333                 ACESSNSR_OPS_RX, ACESSNSR_META_NIC, UDI_NSR_RX_OPS_NUM,
334                 0, (udi_ops_vector_t*)&acessnsr_rx_ops, acessnsr_rx_ops_flags
335         },
336         {0}
337 };
338 udi_cb_init_t   acessnsr_cb_init_list[] = {
339         {ACESSNSR_CB_CTRL, ACESSNSR_META_NIC, UDI_NIC_BIND_CB_NUM, 0, 0,NULL},
340         {ACESSNSR_CB_RX, ACESSNSR_META_NIC, UDI_NIC_RX_CB_NUM, 0, 0,NULL},
341         {ACESSNSR_CB_TX, ACESSNSR_META_NIC, UDI_NIC_TX_CB_NUM, 0, 0,NULL},
342         {0}
343 };
344 const udi_init_t        acessnsr_init = {
345         .primary_init_info = &acessnsr_pri_init,
346         .ops_init_list = acessnsr_ops_list,
347         .cb_init_list = acessnsr_cb_init_list,
348 };
349 const char      acessnsr_udiprops[] = 
350         "properties_version 0x101\0"
351         "message 1 Acess2 Kernel\0"
352         "message 2 John Hodge ([email protected])\0"
353         "message 3 Acess2 NSR\0"
354         "supplier 1\0"
355         "contact 2\0"
356         "name 3\0"
357         "module acess_nsr\0"
358         "shortname acessnsr\0"
359         "requires udi 0x101\0"
360         "requires udi_nic 0x101\0"
361         "meta 1 udi_nic\0"
362         "message 101 Ethernet Adapter\0"
363         "device 101 1 if_media string eth\0"
364         "parent_bind_ops 1 0 1 1\0"
365         "\0";
366 size_t  acessnsr_udiprops_size = sizeof(acessnsr_udiprops);
367

UCC git Repository :: git.ucc.asn.au