source: mainline/uspace/srv/hw/netif/dp8390/dp8390_module.c@ c7a8442

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c7a8442 was c7a8442, checked in by Jakub Jermar <jakub@…>, 15 years ago

Move net_modules.[ch] to the standard library. Note that this functionality is
not directly related to networking so the next step regarding these two files
would be to somehow merge its functionality with what we already have in lib c.

  • Property mode set to 100644
File size: 9.4 KB
Line 
1/*
2 * Copyright (c) 2009 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup dp8390
30 * @{
31 */
32
33/** @file
34 * DP8390 network interface implementation.
35 */
36
37#include <assert.h>
38#include <async.h>
39#include <ddi.h>
40#include <errno.h>
41#include <err.h>
42#include <malloc.h>
43#include <ipc/ipc.h>
44#include <ipc/services.h>
45
46#include <net_messages.h>
47#include <net/modules.h>
48#include <packet/packet_client.h>
49#include <adt/measured_strings.h>
50#include <net_device.h>
51#include <nil_interface.h>
52#include <netif_interface.h>
53#include <netif_local.h>
54
55#include "dp8390.h"
56#include "dp8390_drv.h"
57#include "dp8390_port.h"
58
59/** DP8390 module name.
60 */
61#define NAME "dp8390"
62
63/** Returns the device from the interrupt call.
64 * @param[in] call The interrupt call.
65 */
66#define IRQ_GET_DEVICE(call) (device_id_t) IPC_GET_METHOD(*call)
67
68/** Returns the interrupt status register from the interrupt call.
69 * @param[in] call The interrupt call.
70 */
71#define IPC_GET_ISR(call) (int) IPC_GET_ARG2(*call)
72
73/** DP8390 kernel interrupt command sequence.
74 */
75static irq_cmd_t dp8390_cmds[] = {
76 { .cmd = CMD_PIO_READ_8,
77 .addr = NULL,
78 .dstarg = 2
79 },
80 {
81 .cmd = CMD_PREDICATE,
82 .value = 1,
83 .srcarg = 2
84 },
85 {
86 .cmd = CMD_ACCEPT
87 }
88};
89
90/** DP8390 kernel interrupt code.
91 */
92static irq_code_t dp8390_code = {
93 sizeof(dp8390_cmds) / sizeof(irq_cmd_t),
94 dp8390_cmds
95};
96
97/** Handles the interrupt messages.
98 * This is the interrupt handler callback function.
99 * @param[in] iid The interrupt message identifier.
100 * @param[in] call The interrupt message.
101 */
102static void irq_handler(ipc_callid_t iid, ipc_call_t * call)
103{
104 netif_device_t * device;
105 dpeth_t * dep;
106 packet_t received;
107 device_id_t device_id;
108 int phone;
109
110 device_id = IRQ_GET_DEVICE(call);
111 fibril_rwlock_write_lock(&netif_globals.lock);
112 if(find_device(device_id, &device) != EOK){
113 fibril_rwlock_write_unlock(&netif_globals.lock);
114 return;
115 }
116 dep = (dpeth_t *) device->specific;
117 if (dep->de_mode != DEM_ENABLED){
118 fibril_rwlock_write_unlock(&netif_globals.lock);
119 return;
120 }
121 assert(dep->de_flags &DEF_ENABLED);
122 dep->de_int_pending = 0;
123 dp_check_ints(dep, IPC_GET_ISR(call));
124 if(dep->received_queue){
125 received = dep->received_queue;
126 phone = device->nil_phone;
127 dep->received_queue = NULL;
128 dep->received_count = 0;
129 fibril_rwlock_write_unlock(&netif_globals.lock);
130 nil_received_msg(phone, device_id, received, NULL);
131 }else{
132 fibril_rwlock_write_unlock(&netif_globals.lock);
133 }
134 ipc_answer_0(iid, EOK);
135}
136
137/** Changes the network interface state.
138 * @param[in,out] device The network interface.
139 * @param[in] state The new state.
140 * @returns The new state.
141 */
142static int change_state(netif_device_t * device, device_state_t state)
143{
144 if (device->state != state) {
145 device->state = state;
146
147 printf("%s: State changed to %s\n", NAME,
148 (state == NETIF_ACTIVE) ? "active" : "stopped");
149
150 return state;
151 }
152
153 return EOK;
154}
155
156int netif_specific_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
157 return ENOTSUP;
158}
159
160int netif_get_device_stats(device_id_t device_id, device_stats_ref stats){
161 ERROR_DECLARE;
162
163 netif_device_t * device;
164 eth_stat_t * de_stat;
165
166 if(! stats){
167 return EBADMEM;
168 }
169 ERROR_PROPAGATE(find_device(device_id, &device));
170 de_stat = &((dpeth_t *) device->specific)->de_stat;
171 null_device_stats(stats);
172 stats->receive_errors = de_stat->ets_recvErr;
173 stats->send_errors = de_stat->ets_sendErr;
174 stats->receive_crc_errors = de_stat->ets_CRCerr;
175 stats->receive_frame_errors = de_stat->ets_frameAll;
176 stats->receive_missed_errors = de_stat->ets_missedP;
177 stats->receive_packets = de_stat->ets_packetR;
178 stats->send_packets = de_stat->ets_packetT;
179 stats->collisions = de_stat->ets_collision;
180 stats->send_aborted_errors = de_stat->ets_transAb;
181 stats->send_carrier_errors = de_stat->ets_carrSense;
182 stats->send_heartbeat_errors = de_stat->ets_CDheartbeat;
183 stats->send_window_errors = de_stat->ets_OWC;
184 return EOK;
185}
186
187int netif_get_addr_message(device_id_t device_id, measured_string_ref address){
188 ERROR_DECLARE;
189
190 netif_device_t * device;
191
192 if(! address){
193 return EBADMEM;
194 }
195 ERROR_PROPAGATE(find_device(device_id, &device));
196 address->value = (char *) (&((dpeth_t *) device->specific)->de_address);
197 address->length = CONVERT_SIZE(ether_addr_t, char, 1);
198 return EOK;
199}
200
201
202
203int netif_probe_message(device_id_t device_id, int irq, uintptr_t io){
204 ERROR_DECLARE;
205
206 netif_device_t * device;
207 dpeth_t * dep;
208
209 device = (netif_device_t *) malloc(sizeof(netif_device_t));
210 if(! device){
211 return ENOMEM;
212 }
213 dep = (dpeth_t *) malloc(sizeof(dpeth_t));
214 if(! dep){
215 free(device);
216 return ENOMEM;
217 }
218 bzero(device, sizeof(netif_device_t));
219 bzero(dep, sizeof(dpeth_t));
220 device->device_id = device_id;
221 device->nil_phone = -1;
222 device->specific = (void *) dep;
223 device->state = NETIF_STOPPED;
224 dep->de_irq = irq;
225 dep->de_mode = DEM_DISABLED;
226 //TODO address?
227 if(ERROR_OCCURRED(pio_enable((void *) io, DP8390_IO_SIZE, (void **) &dep->de_base_port))
228 || ERROR_OCCURRED(do_probe(dep))){
229 free(dep);
230 free(device);
231 return ERROR_CODE;
232 }
233 if(ERROR_OCCURRED(netif_device_map_add(&netif_globals.device_map, device->device_id, device))){
234 free(dep);
235 free(device);
236 return ERROR_CODE;
237 }
238 return EOK;
239}
240
241int netif_send_message(device_id_t device_id, packet_t packet, services_t sender){
242 ERROR_DECLARE;
243
244 netif_device_t * device;
245 dpeth_t * dep;
246 packet_t next;
247
248 ERROR_PROPAGATE(find_device(device_id, &device));
249 if(device->state != NETIF_ACTIVE){
250 netif_pq_release(packet_get_id(packet));
251 return EFORWARD;
252 }
253 dep = (dpeth_t *) device->specific;
254 // process packet queue
255 do{
256 next = pq_detach(packet);
257 if(do_pwrite(dep, packet, FALSE) != EBUSY){
258 netif_pq_release(packet_get_id(packet));
259 }
260 packet = next;
261 }while(packet);
262 return EOK;
263}
264
265int netif_start_message(netif_device_t * device){
266 ERROR_DECLARE;
267
268 dpeth_t * dep;
269
270 if(device->state != NETIF_ACTIVE){
271 dep = (dpeth_t *) device->specific;
272 dp8390_cmds[0].addr = (void *) (uintptr_t) (dep->de_dp8390_port + DP_ISR);
273 dp8390_cmds[2].addr = dp8390_cmds[0].addr;
274 ERROR_PROPAGATE(ipc_register_irq(dep->de_irq, device->device_id, device->device_id, &dp8390_code));
275 if(ERROR_OCCURRED(do_init(dep, DL_BROAD_REQ))){
276 ipc_unregister_irq(dep->de_irq, device->device_id);
277 return ERROR_CODE;
278 }
279 return change_state(device, NETIF_ACTIVE);
280 }
281 return EOK;
282}
283
284int netif_stop_message(netif_device_t * device){
285 dpeth_t * dep;
286
287 if(device->state != NETIF_STOPPED){
288 dep = (dpeth_t *) device->specific;
289 do_stop(dep);
290 ipc_unregister_irq(dep->de_irq, device->device_id);
291 return change_state(device, NETIF_STOPPED);
292 }
293 return EOK;
294}
295
296int netif_initialize(void){
297 ipcarg_t phonehash;
298
299 async_set_interrupt_received(irq_handler);
300
301 return REGISTER_ME(SERVICE_DP8390, &phonehash);
302}
303
304/** Default thread for new connections.
305 *
306 * @param[in] iid The initial message identifier.
307 * @param[in] icall The initial message call structure.
308 *
309 */
310static void netif_client_connection(ipc_callid_t iid, ipc_call_t * icall)
311{
312 /*
313 * Accept the connection
314 * - Answer the first IPC_M_CONNECT_ME_TO call.
315 */
316 ipc_answer_0(iid, EOK);
317
318 while(true) {
319 ipc_call_t answer;
320 int answer_count;
321
322 /* Clear the answer structure */
323 refresh_answer(&answer, &answer_count);
324
325 /* Fetch the next message */
326 ipc_call_t call;
327 ipc_callid_t callid = async_get_call(&call);
328
329 /* Process the message */
330 int res = netif_module_message(NAME, callid, &call, &answer,
331 &answer_count);
332
333 /* End if said to either by the message or the processing result */
334 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
335 return;
336
337 /* Answer the message */
338 answer_call(callid, res, &answer, answer_count);
339 }
340}
341
342/** Starts the module.
343 *
344 * @param argc The count of the command line arguments. Ignored parameter.
345 * @param argv The command line parameters. Ignored parameter.
346 *
347 * @returns EOK on success.
348 * @returns Other error codes as defined for each specific module start function.
349 *
350 */
351int main(int argc, char *argv[])
352{
353 ERROR_DECLARE;
354
355 /* Start the module */
356 if (ERROR_OCCURRED(netif_module_start(netif_client_connection)))
357 return ERROR_CODE;
358
359 return EOK;
360}
361
362/** @}
363 */
Note: See TracBrowser for help on using the repository browser.