3 * - By John Hodge (thePowersGang)
6 * - "Network Service Requester" (UDI->IP Translation)
12 #include <trans_nsr.h>
13 #include <IPStack/include/adapters_api.h>
14 #include <workqueue.h>
16 #define NUM_RX_BUFFERS 4
19 ACESSNSR_OPS_CTRL = 1,
35 udi_init_context_t init_context;
39 udi_buf_t *rx_buffers[NUM_RX_BUFFERS];
40 udi_nic_rx_cb_t *rx_cbs[NUM_RX_BUFFERS];
44 tIPStack_AdapterType AdapterType;
47 udi_channel_t rx_channel;
48 udi_channel_t tx_channel;
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);
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);
70 void acessnsr_tx_channel_event_ind(udi_channel_event_cb_t *cb);
71 void acessnsr_tx_rdy(udi_nic_tx_cb_t *cb);
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);
77 int acessnsr_SendPacket(void *Card, tIPStackBuffer *Buffer);
78 tIPStackBuffer *acessnsr_WaitForPacket(void *Card);
81 // --- Management metalang
82 void acessnsr_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level)
84 acessnsr_rdata_t *rdata = UDI_GCB(cb)->context;
85 switch(resource_level)
89 Workqueue_Init(&rdata->RXQueue, "AcessNSR RX", offsetof(udi_nic_rx_cb_t, chain));
93 void acessnsr_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID)
97 void acessnsr_final_cleanup_req(udi_mgmt_cb_t *cb)
102 void acessnsr_ctrl_channel_event_ind(udi_channel_event_cb_t *cb)
104 acessnsr_rdata_t *rdata = UDI_GCB(cb)->context;
107 case UDI_CHANNEL_CLOSED:
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);
118 void acessnsr_ctrl_ch_ev_ind__rx_channel_spawned(udi_cb_t *gcb, udi_channel_t channel)
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);
126 void acessnsr_ctrl_ch_ev_ind__tx_channel_spawned(udi_cb_t *gcb, udi_channel_t channel)
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);
134 void acessnsr_ctrl_bind_ack(udi_nic_bind_cb_t *cb, udi_status_t status)
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)
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;
145 udi_channel_event_complete( UDI_MCB(rdata->active_cb,udi_channel_event_cb_t), UDI_OK );
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;
156 rdata->AdapterType.Name = "udi";
157 rdata->AdapterType.SendPacket = acessnsr_SendPacket;
158 rdata->AdapterType.WaitForPacket = acessnsr_WaitForPacket;
160 rdata->ipstack_handle = IPStack_Adapter_Add(&rdata->AdapterType, rdata, cb->mac_addr);
162 // Allocate RX CBs and buffers
163 rdata->init_idx = -1;
164 acessnsr_ctrl_bind_ack__rx_buf_allocated(rdata->active_cb, NULL);
167 void acessnsr_ctrl_bind_ack__rx_buf_allocated(udi_cb_t *gcb, udi_buf_t *new_buf)
169 acessnsr_rdata_t *rdata = gcb->context;
170 if( rdata->init_idx != (udi_index_t)-1 )
172 rdata->rx_buffers[rdata->init_idx] = new_buf;
175 if( rdata->init_idx < NUM_RX_BUFFERS )
177 UDI_BUF_ALLOC(acessnsr_ctrl_bind_ack__rx_buf_allocated, gcb, NULL, 0, NULL);
182 rdata->init_idx = -1;
183 acessnsr_ctrl_bind_ack__rx_cb_allocated(gcb, NULL);
185 void acessnsr_ctrl_bind_ack__rx_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb)
187 acessnsr_rdata_t *rdata = gcb->context;
188 if( rdata->init_idx != (udi_index_t)-1 )
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];
196 if( rdata->init_idx < NUM_RX_BUFFERS )
198 udi_cb_alloc(acessnsr_ctrl_bind_ack__rx_cb_allocated, gcb, ACESSNSR_CB_RX, rdata->rx_channel);
202 udi_channel_event_complete( UDI_MCB(rdata->active_cb,udi_channel_event_cb_t), UDI_OK );
205 void acessnsr_ctrl_unbind_ack(udi_nic_cb_t *cb, udi_status_t status)
209 void acessnsr_ctrl_enable_ack(udi_nic_cb_t *cb, udi_status_t status)
213 void acessnsr_ctrl_disable_ack(udi_nic_cb_t *cb, udi_status_t status)
217 void acessnsr_ctrl_ctrl_ack(udi_nic_ctrl_cb_t *cb, udi_status_t status)
221 void acessnsr_ctrl_status_ind(udi_nic_status_cb_t *cb)
225 void acessnsr_ctrl_info_ack(udi_nic_info_cb_t *cb)
230 void acessnsr_tx_channel_event_ind(udi_channel_event_cb_t *cb)
234 void acessnsr_tx_rdy(udi_nic_tx_cb_t *cb)
239 void acessnsr_rx_channel_event_ind(udi_channel_event_cb_t *cb)
243 void acessnsr_rx_ind(udi_nic_rx_cb_t *cb)
245 acessnsr_rdata_t *rdata = UDI_GCB(cb)->context;
246 udi_nic_rx_cb_t *next;
249 Workqueue_AddWork(&rdata->RXQueue, cb);
250 } while( (cb = next) );
252 void acessnsr_rx_exp_ind(udi_nic_rx_cb_t *cb)
257 int acessnsr_SendPacket(void *Card, tIPStackBuffer *Buffer)
262 void _FreeHeapSubBuf(void *Arg, size_t Pre, size_t Post, const void *DataBuf)
266 tIPStackBuffer *acessnsr_WaitForPacket(void *Card)
268 acessnsr_rdata_t *rdata = Card;
269 udi_nic_rx_cb_t *cb = Workqueue_GetWork(&rdata->RXQueue);
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);
280 // === UDI Bindings ===
281 udi_mgmt_ops_t acessnsr_mgmt_ops = {
283 udi_enumerate_no_children,
284 acessnsr_devmgmt_req,
285 acessnsr_final_cleanup_req
287 udi_ubit8_t acessnsr_mgmt_ops_flags[4] = {0,0,0,0};
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
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
308 udi_ubit8_t acessnsr_ctrl_op_flags[7] = {0};
310 udi_nsr_tx_ops_t acessnsr_tx_ops = {
311 acessnsr_tx_channel_event_ind,
314 udi_ubit8_t acessnsr_tx_ops_flags[2] = {0};
316 udi_nsr_rx_ops_t acessnsr_rx_ops = {
317 acessnsr_rx_channel_event_ind,
321 udi_ubit8_t acessnsr_rx_ops_flags[3] = {0};
323 udi_ops_init_t acessnsr_ops_list[] = {
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
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
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
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},
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,
349 const char acessnsr_udiprops[] =
350 "properties_version 0x101\0"
351 "message 1 Acess2 Kernel\0"
353 "message 3 Acess2 NSR\0"
358 "shortname acessnsr\0"
359 "requires udi 0x101\0"
360 "requires udi_nic 0x101\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"
366 size_t acessnsr_udiprops_size = sizeof(acessnsr_udiprops);