UDI/ne2000 - Tweaks to get _core.c compiling
[tpg/acess2.git] / UDI / drivers / net_ne2000 / ne2000_core.c
1 /*
2  * UDI Ne2000 NIC Driver
3  * By John Hodge (thePowersGang)
4  *
5  * ne2000_core.c
6  * - UDI initialisation 
7  */
8 #include <udi.h>
9 #include <udi_nic.h>
10 #include "ne2000_common.h"
11
12 #define NE2K_META_BUS   1
13 #define NE2K_META_NIC   2
14
15 // === GLOBALS ===
16 #define PIO_op_RI(op, reg, sz, val)     {UDI_PIO_##op+UDI_PIO_DIRECT+UDI_PIO_##reg, UDI_PIO_##sz##BYTE, val}
17 #define PIO_MOV_RI1(reg, val)   PIO_op_RI(LOAD_IMM, reg, 1, val)
18 #define PIO_OUT_RI1(reg, ofs)   PIO_op_RI(OUT, reg, 1, ofs)
19 #define PIO_IN_RI1(reg, ofs)    PIO_op_RI(IN, reg, 1, ofs)
20 // --- Programmed IO ---
21 /// Ne2000 reset operation (reads MAC address too)
22 udi_pio_trans_t ne2k_pio_reset[] = {
23         // - Reset card
24         PIO_IN_RI1(R0, NE2K_REG_RESET),
25         PIO_OUT_RI1(R0, NE2K_REG_RESET),
26         // While ISR bit 7 is unset, spin
27         {UDI_PIO_LABEL, 0, 1},
28                 PIO_IN_RI1(R0, NE2K_REG_ISR),
29                 {UDI_PIO_AND_IMM+UDI_PIO_R0, UDI_PIO_1BYTE, 0x80},
30         {UDI_PIO_CSKIP+UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_NZ},
31         {UDI_PIO_BRANCH, 0, 1},
32         // ISR = 0x80 [Clear reset]
33         PIO_OUT_RI1(R0, NE2K_REG_ISR),
34         // - Init pass 1
35         // CMD = 0x40|0x21 [Page1, NoDMA, Stop]
36         PIO_MOV_RI1(R0, 0x40|0x21),
37         PIO_OUT_RI1(R0, NE2K_REG_CMD),
38         // CURR = First RX page
39         PIO_MOV_RI1(R0, NE2K_RX_FIRST_PG),
40         PIO_OUT_RI1(R0, NE2K_REG_CURR),
41         // CMD = 0x21 [Page0, NoDMA, Stop]
42         PIO_MOV_RI1(R0, 0x21),
43         PIO_OUT_RI1(R0, NE2K_REG_CMD),
44         // DCR = ? [WORD, ...]
45         PIO_MOV_RI1(R0, 0x49),
46         PIO_OUT_RI1(R0, NE2K_REG_DCR),
47         // IMR = 0 [Disable all]
48         PIO_MOV_RI1(R0, 0x00),
49         PIO_OUT_RI1(R0, NE2K_REG_IMR),
50         // ISR = 0xFF [ACK all]
51         PIO_MOV_RI1(R0, 0xFF),
52         PIO_OUT_RI1(R0, NE2K_REG_ISR),
53         // RCR = 0x20 [Monitor]
54         PIO_MOV_RI1(R0, 0x20),
55         PIO_OUT_RI1(R0, NE2K_REG_RCR),
56         // TCR = 0x02 [TX Off, Loopback]
57         PIO_MOV_RI1(R0, 0x02),
58         PIO_OUT_RI1(R0, NE2K_REG_TCR),
59         // - Read MAC address from EEPROM (24 bytes from 0)
60         PIO_MOV_RI1(R0, 0),
61         PIO_MOV_RI1(R1, 0),
62         PIO_OUT_RI1(R0, NE2K_REG_RSAR0),
63         PIO_OUT_RI1(R1, NE2K_REG_RSAR1),
64         PIO_MOV_RI1(R0, 6*4),
65         PIO_MOV_RI1(R1, 0),
66         PIO_OUT_RI1(R0, NE2K_REG_RBCR0),
67         PIO_OUT_RI1(R1, NE2K_REG_RBCR1),
68         // CMD = 0x0A [Start remote DMA]
69         PIO_MOV_RI1(R0, 0x0A),
70         PIO_OUT_RI1(R0, NE2K_REG_CMD),
71         // Read MAC address
72         PIO_MOV_RI1(R0, 0),     // - Buffer offset (incremented by 1 each iteration)
73         PIO_MOV_RI1(R1, NE2K_REG_MEM),  // - Reg offset (no increment)
74         PIO_MOV_RI1(R2, 6),     // - Six iterations
75         {UDI_PIO_REP_IN_IND, UDI_PIO_1BYTE,
76                 UDI_PIO_REP_ARGS(UDI_PIO_BUF, UDI_PIO_R0, 1, UDI_PIO_R1, 0, UDI_PIO_R2)},
77         // - Setup
78         // PSTART = First RX page [Receive area start]
79         PIO_MOV_RI1(R0, NE2K_RX_FIRST_PG),
80         PIO_OUT_RI1(R0, NE2K_REG_PSTART),
81         // BNRY = Last RX page - 1 [???]
82         PIO_MOV_RI1(R0, NE2K_RX_LAST_PG-1),
83         PIO_OUT_RI1(R0, NE2K_REG_BNRY),
84         // PSTOP = Last RX page [???]
85         PIO_MOV_RI1(R0, NE2K_RX_LAST_PG),
86         PIO_OUT_RI1(R0, NE2K_REG_PSTOP),
87         // > Clear all interrupt and set mask
88         // ISR = 0xFF [ACK all]
89         PIO_MOV_RI1(R0, 0xFF),
90         PIO_OUT_RI1(R0, NE2K_REG_ISR),
91         // IMR = 0x3F []
92         PIO_MOV_RI1(R0, 0x3F),
93         PIO_OUT_RI1(R0, NE2K_REG_IMR),
94         // CMD = 0x22 [NoDMA, Start]
95         PIO_MOV_RI1(R0, 0x22),
96         PIO_OUT_RI1(R0, NE2K_REG_CMD),
97         // RCR = 0x0F [Wrap, Promisc]
98         PIO_MOV_RI1(R0, 0x0F),
99         PIO_OUT_RI1(R0, NE2K_REG_RCR),
100         // TCR = 0x00 [Normal]
101         PIO_MOV_RI1(R0, 0x00),
102         PIO_OUT_RI1(R0, NE2K_REG_TCR),
103         // TPSR = 0x40 [TX Start]
104         PIO_MOV_RI1(R0, 0x40),
105         PIO_OUT_RI1(R0, NE2K_REG_TPSR),
106         // End
107         {UDI_PIO_END_IMM, UDI_PIO_2BYTE, 0}
108 };
109 struct {
110         udi_pio_trans_t *trans_list;
111         udi_ubit16_t    list_length;
112         udi_ubit16_t    pio_attributes;
113 } ne2k_pio_ops[] = {
114         {ne2k_pio_reset, ARRAY_SIZEOF(ne2k_pio_reset), 0}
115 };
116 const int NE2K_NUM_PIO_OPS = ARRAY_SIZEOF(ne2k_pio_ops);
117
118 // === CODE ===
119 // --- Management
120 void ne2k_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level)
121 {
122 }
123 void ne2k_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level)
124 {
125         ne2k_rdata_t    *rdata = UDI_GCB(cb)->context;
126         udi_instance_attr_list_t *attr_list = cb->attr_list;
127         
128         switch(enumeration_level)
129         {
130         case UDI_ENUMERATE_START:
131         case UDI_ENUMERATE_START_RESCAN:
132                 // Emit the ND binding
133                 DPT_SET_ATTR32(attr_list, "if_num", 0);
134                 attr_list ++;
135                 DPT_SET_ATTR_STRING(attr_list, "if_media", "eth", 3);
136                 attr_list ++;
137                 NE2K_SET_ATTR_STRFMT(attr_list, "identifier", 2*6+1, "%2X%2X%2X%2X%2X%2X",
138                         rdata->macaddr[0], rdata->macaddr[1], rdata->macaddr[2],
139                         rdata->macaddr[3], rdata->macaddr[4], rdata->macaddr[5] );
140                 attr_list ++;
141                 udi_enumerate_ack(cb, UDI_ENUMERATE_OK, 2);
142                 break;
143         case UDI_ENUMERATE_NEXT:
144                 udi_enumerate_ack(cb, UDI_ENUMERATE_DONE, 0);
145                 break;
146         }
147 }
148 void ne2k_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID)
149 {
150 }
151 void ne2k_final_cleanup_req(udi_mgmt_cb_t *cb)
152 {
153 }
154 // --- Bus
155 void ne2k_bus_dev_channel_event_ind(udi_channel_event_cb_t *cb)
156 {
157         switch(cb->event)
158         {
159         case UDI_CHANNEL_CLOSED:
160                 break;
161         case UDI_CHANNEL_BOUND: {
162                 udi_bus_bind_cb_t *bus_bind_cb = UDI_MCB(cb->params.parent_bound.bind_cb, udi_bus_bind_cb_t);
163                 udi_bus_bind_req( bus_bind_cb );
164                 // continue at ne2k_bus_dev_bus_bind_ack
165                 return; }
166         }
167 }
168 void ne2k_bus_dev_bus_bind_ack(udi_bus_bind_cb_t *cb,
169         udi_dma_constraints_t dma_constraints, udi_ubit8_t perferred_endianness, udi_status_t status)
170 {
171         udi_cb_t        *gcb = UDI_GCB(cb);
172         ne2k_rdata_t    *rdata = gcb->context;
173         
174         // Set up PIO handles
175         rdata->init.pio_index = -1;
176         ne2k_bus_dev_bind__pio_map(gcb, UDI_NULL_PIO_HANDLE);
177 }
178 void ne2k_bus_dev_bind__pio_map(udi_cb_t *gcb, udi_pio_handle_t new_pio_handle)
179 {
180         ne2k_rdata_t    *rdata = gcb->context;
181         
182         if( rdata->init.pio_index != -1 )
183         {
184                 rdata->pio_handles[rdata->init.pio_index] = new_pio_handle;
185         }
186         rdata->init.pio_index ++;
187         if( rdata->init.pio_index < NE2K_NUM_PIO_OPS )
188         {
189                 udi_pio_map(ne2k_bus_dev_bind__pio_map, gcb,
190                         UDI_PCI_BAR_0, 0, 0x20,
191                         ne2k_pio_ops[rdata->init.pio_index].trans_list,
192                         ne2k_pio_ops[rdata->init.pio_index].list_length,
193                         UDI_PIO_LITTLE_ENDIAN, 0, 0
194                         );
195         }
196         else
197         {
198                 // Next!
199         }
200 }
201 void ne2k_bus_dev_bus_unbind_ack(udi_bus_bind_cb_t *cb)
202 {
203 }
204 void ne2k_bus_dev_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status)
205 {
206 }
207 void ne2k_bus_dev_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb)
208 {
209 }
210 // --- ND Common
211 void ne2k_nd_ctrl_channel_event_ind(udi_channel_event_cb_t *cb)
212 {
213 }
214 void ne2k_nd_ctrl_bind_req(udi_nic_bind_cb_t *cb, udi_index_t tx_chan_index, udi_index_t rx_chan_index)
215 {
216 }
217 void ne2k_nd_ctrl_unbind_req(udi_nic_cb_t *cb)
218 {
219 }
220 void ne2k_nd_ctrl_enable_req(udi_nic_cb_t *cb)
221 {
222 }
223 void ne2k_nd_ctrl_disable_req(udi_nic_cb_t *cb)
224 {
225 }
226 void ne2k_nd_ctrl_ctrl_req(udi_nic_ctrl_cb_t *cb)
227 {
228 }
229 void ne2k_nd_ctrl_info_req(udi_nic_info_cb_t *cb, udi_boolean_t reset_statistics)
230 {
231 }
232
233 // === Definition structures ===
234 udi_mgmt_ops_t  ne2k_mgmt_ops = {
235         ne2k_usage_ind,
236         ne2k_enumerate_req,
237         ne2k_devmgmt_req,
238         ne2k_final_cleanup_req
239 };
240 udi_ubit8_t     ne2k_mgmt_op_flags[4] = {0,0,0,0};
241 udi_bus_device_ops_t    ne2k_bus_dev_ops = {
242         ne2k_bus_dev_channel_event_ind,
243         ne2k_bus_dev_bus_bind_ack,
244         ne2k_bus_dev_bus_unbind_ack,
245         ne2k_bus_dev_intr_attach_ack,
246         ne2k_bus_dev_intr_detach_ack
247 };
248 udi_ubit8_t     ne2k_bus_dev_ops_flags[5] = {0};
249 udi_nd_ctrl_ops_t       ne2k_nd_ctrl_ops = {
250         ne2k_nd_ctrl_channel_event_ind,
251         ne2k_nd_ctrl_bind_req,
252         ne2k_nd_ctrl_unbind_req,
253         ne2k_nd_ctrl_enable_req,
254         ne2k_nd_ctrl_disable_req,
255         ne2k_nd_ctrl_ctrl_req,
256         ne2k_nd_ctrl_info_req
257 };
258 udi_ubit8_t     ne2k_nd_ctrl_ops_flags[7] = {0};
259 udi_nd_tx_ops_t ne2k_nd_tx_ops = {
260         ne2k_nd_tx_channel_event_ind,
261         ne2k_nd_tx_tx_req,
262         ne2k_nd_tx_exp_tx_req
263 };
264 udi_ubit8_t     ne2k_nd_tx_ops_flags[3] = {0};
265 udi_nd_rx_ops_t ne2k_nd_rx_ops = {
266         ne2k_nd_rx_channel_event_ind,
267         ne2k_nd_rx_rx_rdy
268 };
269 udi_ubit8_t     ne2k_nd_rx_ops_flags[2] = {0};
270 udi_primary_init_t      ne2k_pri_init = {
271         .mgmt_ops = &ne2k_mgmt_ops,
272         .mgmt_op_flags = ne2k_mgmt_op_flags,
273         .mgmt_scratch_requirement = 0,
274         .enumeration_attr_list_length = 4,
275         .rdata_size = sizeof(ne2k_rdata_t),
276         .child_data_size = 0,
277         .per_parent_paths = 0
278 };
279 udi_ops_init_t  ne2k_ops_list[] = {
280         {
281                 1, NE2K_META_BUS, UDI_BUS_DEVICE_OPS_NUM,
282                 0,
283                 (udi_ops_vector_t*)&ne2k_bus_dev_ops,
284                 ne2k_bus_dev_ops_flags
285         },
286         {
287                 2, NE2K_META_NIC, UDI_ND_CTRL_OPS_NUM,
288                 0,
289                 (udi_ops_vector_t*)&ne2k_nd_ctrl_ops,
290                 ne2k_nd_ctrl_ops_flags
291         },
292         {
293                 3, NE2K_META_NIC, UDI_ND_TX_OPS_NUM,
294                 0,
295                 (udi_ops_vector_t*)&ne2k_nd_tx_ops,
296                 ne2k_nd_tx_ops_flags
297         },
298         {
299                 4, NE2K_META_NIC, UDI_ND_RX_OPS_NUM,
300                 0,
301                 (udi_ops_vector_t*)&ne2k_nd_rx_ops,
302                 ne2k_nd_rx_ops_flags
303         },
304         {0}
305 };
306 const udi_init_t        udi_init_info = {
307         .primary_init_info = &ne2k_pri_init,
308         .ops_init_list = ne2k_ops_list
309 };

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