enum {
ACESSNSR_CB_CTRL = 1,
ACESSNSR_CB_RX,
- ACESSNSR_CB_TX
+ ACESSNSR_CB_TX,
+ ACESSNSR_CB_STD,
};
// === TYPES ===
{
udi_init_context_t init_context;
udi_cb_t *active_cb;
-
- udi_index_t init_idx;
- udi_buf_t *rx_buffers[NUM_RX_BUFFERS];
- udi_nic_rx_cb_t *rx_cbs[NUM_RX_BUFFERS];
+ udi_channel_t saved_active_channel;
tWorkqueue RXQueue;
void acessnsr_ctrl_ch_ev_ind__rx_channel_spawned(udi_cb_t *gcb, udi_channel_t channel);
void acessnsr_ctrl_ch_ev_ind__tx_channel_spawned(udi_cb_t *gcb, udi_channel_t channel);
void acessnsr_ctrl_bind_ack(udi_nic_bind_cb_t *cb, udi_status_t status);
-void acessnsr_ctrl_bind_ack__rx_buf_allocated(udi_cb_t *gcb, udi_buf_t *new_buf);
-void acessnsr_ctrl_bind_ack__rx_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb);
-void acessnsr_ctrl_bind_ack__tx_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb);
+void acessnsr_ctrl_bind_ack__rx_cbs_allocated(udi_cb_t *gcb, udi_cb_t *first_new_cb);
+void acessnsr_ctrl_bind_ack__tx_cbs_allocated(udi_cb_t *gcb, udi_cb_t *first_new_cb);
+void acessnsr_ctrl_bind_ack__std_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb);
void acessnsr_ctrl_unbind_ack(udi_nic_cb_t *cb, udi_status_t status);
void acessnsr_ctrl_enable_ack(udi_nic_cb_t *cb, udi_status_t status);
void acessnsr_ctrl_disable_ack(udi_nic_cb_t *cb, udi_status_t status);
break;
}
+ // - Register with IPStack
if(cb->capabilities & UDI_NIC_CAP_TX_IP_CKSUM)
rdata->AdapterType.Flags |= ADAPTERFLAG_OFFLOAD_IP4;
if(cb->capabilities & UDI_NIC_CAP_TX_TCP_CKSUM)
rdata->AdapterType.Flags |= ADAPTERFLAG_OFFLOAD_TCP;
if(cb->capabilities & UDI_NIC_CAP_TX_UDP_CKSUM)
rdata->AdapterType.Flags |= ADAPTERFLAG_OFFLOAD_UDP;
-
rdata->AdapterType.Name = "udi";
rdata->AdapterType.SendPacket = acessnsr_SendPacket;
rdata->AdapterType.WaitForPacket = acessnsr_WaitForPacket;
-
rdata->ipstack_handle = IPStack_Adapter_Add(&rdata->AdapterType, rdata, cb->mac_addr);
// Allocate RX CBs and buffers
- rdata->init_idx = -1;
- acessnsr_ctrl_bind_ack__rx_buf_allocated(rdata->active_cb, NULL);
+ // EVIL: Save and change channel of event CB
+ rdata->saved_active_channel = rdata->active_cb->channel;
+ rdata->active_cb->channel = rdata->rx_channel;
+ udi_cb_alloc_batch( acessnsr_ctrl_bind_ack__rx_cbs_allocated, rdata->active_cb,
+ ACESSNSR_CB_RX, NUM_RX_BUFFERS, TRUE, 0, NULL);
// V V V V
}
-void acessnsr_ctrl_bind_ack__rx_buf_allocated(udi_cb_t *gcb, udi_buf_t *new_buf)
+void acessnsr_ctrl_bind_ack__rx_cbs_allocated(udi_cb_t *gcb, udi_cb_t *first_new_cb)
{
acessnsr_rdata_t *rdata = gcb->context;
- if( rdata->init_idx != (udi_index_t)-1 )
- {
- rdata->rx_buffers[rdata->init_idx] = new_buf;
- }
- rdata->init_idx ++;
- if( rdata->init_idx < NUM_RX_BUFFERS )
- {
- UDI_BUF_ALLOC(acessnsr_ctrl_bind_ack__rx_buf_allocated, gcb, NULL, 0, NULL);
- // A A A A
- return ;
- }
+ // Send of the entire list
+ ASSERT(first_new_cb);
+ udi_nd_rx_rdy( UDI_MCB(first_new_cb, udi_nic_rx_cb_t) );
- rdata->init_idx = -1;
- acessnsr_ctrl_bind_ack__rx_cb_allocated(gcb, NULL);
+ // Allocate batch (no buffers)
+ gcb->channel = rdata->tx_channel;
+ udi_cb_alloc_batch( acessnsr_ctrl_bind_ack__tx_cbs_allocated, gcb,
+ ACESSNSR_CB_TX, NUM_TX_DESCS, FALSE, 0, NULL);
+ // V V V V
}
-void acessnsr_ctrl_bind_ack__rx_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb)
+void acessnsr_ctrl_bind_ack__tx_cbs_allocated(udi_cb_t *gcb, udi_cb_t *first_new_cb)
{
acessnsr_rdata_t *rdata = gcb->context;
- if( rdata->init_idx != (udi_index_t)-1 )
- {
- udi_nic_rx_cb_t *cb = UDI_MCB(new_cb, udi_nic_rx_cb_t);
- rdata->rx_cbs[rdata->init_idx] = cb;
- cb->rx_buf = rdata->rx_buffers[rdata->init_idx];
- udi_nd_rx_rdy(cb);
- }
- rdata->init_idx ++;
- if( rdata->init_idx < NUM_RX_BUFFERS )
+ ASSERT(first_new_cb);
+
{
- udi_cb_alloc(acessnsr_ctrl_bind_ack__rx_cb_allocated, gcb, ACESSNSR_CB_RX, rdata->rx_channel);
- // A A A A
- return ;
+ udi_nic_tx_cb_t *cb, *next_cb;
+ cb = UDI_MCB(first_new_cb, udi_nic_tx_cb_t);
+ ASSERT(cb);
+ do {
+ next_cb = cb->chain;
+ cb->chain = NULL;
+ Workqueue_AddWork( &rdata->TXWorkQueue, cb );
+ } while(next_cb);
}
- rdata->init_idx = -1;
- acessnsr_ctrl_bind_ack__tx_cb_allocated(gcb, NULL);
+
+ // Allocate standard control CB (for enable/disable)
+ udi_cb_alloc(acessnsr_ctrl_bind_ack__std_cb_allocated, gcb,
+ ACESSNSR_CB_STD, rdata->saved_active_channel);
// V V V V
}
-void acessnsr_ctrl_bind_ack__tx_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb)
+void acessnsr_ctrl_bind_ack__std_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb)
{
- acessnsr_rdata_t *rdata = gcb->context;
- if( rdata->init_idx != (udi_index_t)-1 )
- {
- //udi_assert(new_cb);
- ASSERT(new_cb);
- Workqueue_AddWork( &rdata->TXWorkQueue, UDI_MCB(new_cb, udi_nic_tx_cb_t) );
- }
- rdata->init_idx ++;
- if( rdata->init_idx < NUM_TX_DESCS )
- {
- udi_cb_alloc(acessnsr_ctrl_bind_ack__tx_cb_allocated, gcb, ACESSNSR_CB_TX, rdata->tx_channel);
- // A A A A
- return ;
- }
- udi_channel_event_complete( UDI_MCB(rdata->active_cb,udi_channel_event_cb_t), UDI_OK );
- // = = = =
+ // Final Operations:
+ // - Enable card (RX won't happen until this is called)
+ udi_nd_enable_req( UDI_MCB(new_cb, udi_nic_cb_t) );
+ // Continued in acessnsr_ctrl_enable_ack
}
void acessnsr_ctrl_unbind_ack(udi_nic_cb_t *cb, udi_status_t status)
{
}
void acessnsr_ctrl_enable_ack(udi_nic_cb_t *cb, udi_status_t status)
{
- UNIMPLEMENTED();
+ udi_cb_t *gcb = UDI_GCB(cb);
+ acessnsr_rdata_t *rdata = gcb->context;
+
+ rdata->active_cb->channel = rdata->saved_active_channel;
+ udi_channel_event_complete( UDI_MCB(rdata->active_cb,udi_channel_event_cb_t), UDI_OK );
+ // = = = =
}
void acessnsr_ctrl_disable_ack(udi_nic_cb_t *cb, udi_status_t status)
{
int acessnsr_SendPacket(void *Card, tIPStackBuffer *Buffer)
{
acessnsr_rdata_t *rdata = Card;
+ LOG("Card=%p,Buffer=%p", Card, Buffer);
udi_nic_tx_cb_t *cb = Workqueue_GetWork(&rdata->TXWorkQueue);
ASSERT(cb);
acessnsr_txdesc_t *tx = UDI_GCB(cb)->scratch;
ASSERT(tx);
-
+
+ LOG("Mutex acquire #1 %p", cb);
Mutex_Acquire(&tx->CompleteMutex);
tx->IPBuffer = Buffer;
tx->BufIdx = -1;
Mutex_Release(&tx->CompleteMutex);
// TODO: TX status
- Workqueue_AddWork(&rdata->TXWorkQueue, tx);
+ LOG("Release %p", cb);
+ Workqueue_AddWork(&rdata->TXWorkQueue, cb);
return 0;
}
void acessnsr_SendPacket__buf_write_complete(udi_cb_t *gcb, udi_buf_t *buf)
const void *bufptr;
if( (tx->BufIdx = IPStack_Buffer_GetBuffer(tx->IPBuffer, tx->BufIdx, &buflen, &bufptr )) != -1 )
{
+ Debug_HexDump("NSR", bufptr, buflen);
udi_buf_write(acessnsr_SendPacket__buf_write_complete, gcb,
bufptr, buflen, cb->tx_buf, (cb->tx_buf ? cb->tx_buf->buf_size : 0), 0, NULL);
// A A A A
udi_nd_tx_req(cb);
// continued in acessnsr_tx_rdy
}
-void _FreeHeapSubBuf(void *Arg, size_t Pre, size_t Post, const void *DataBuf)
+static void _FreeHeapSubBuf(void *Arg, size_t Pre, size_t Post, const void *DataBuf)
{
free(Arg);
}
tIPStackBuffer *ret = IPStack_Buffer_CreateBuffer(1);
void *data = malloc( cb->rx_buf->buf_size );
udi_buf_read(cb->rx_buf, 0, cb->rx_buf->buf_size, data);
+ Debug_HexDump("NSR WaitForPacket", data, cb->rx_buf->buf_size);
IPStack_Buffer_AppendSubBuffer(ret, cb->rx_buf->buf_size, 0, data, _FreeHeapSubBuf, data);
udi_nd_rx_rdy(cb);
{ACESSNSR_CB_CTRL, ACESSNSR_META_NIC, UDI_NIC_BIND_CB_NUM, 0, 0,NULL},
{ACESSNSR_CB_RX, ACESSNSR_META_NIC, UDI_NIC_RX_CB_NUM, 0, 0,NULL},
{ACESSNSR_CB_TX, ACESSNSR_META_NIC, UDI_NIC_TX_CB_NUM, sizeof(acessnsr_txdesc_t), 0,NULL},
+ {ACESSNSR_CB_STD, ACESSNSR_META_NIC, UDI_NIC_TX_CB_NUM, 0, 0,NULL},
{0}
};
const udi_init_t acessnsr_init = {