1 /* Network multiplexing for incoming traffic.
3 * This file is part of 0cpm Firmerware.
5 * 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
7 * 0cpm Firmerware is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 3.
11 * 0cpm Firmerware is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with 0cpm Firmerware. If not, see <http://www.gnu.org/licenses/>.
23 * interface to the networking code; it mainly involves scheduling.
36 #include <0cpm/netinet.h>
37 #include <0cpm/netfun.h>
38 #include <0cpm/cons.h>
41 /* TODO: Current return function from netinput
43 typedef void *retfn (uint8_t *pout, intptr_t *mem);
46 /* The can_recv and can_send flags store whether
47 * the network is in a state to permit either of
48 * these operations on the network interface.
50 static bool can_send = false;
51 static bool can_recv = false;
54 /* IRQ handling structures dealing with reads and
55 * writes on the network card.
57 static void network_recv_handler (irq_t *irq);
58 static void network_send_handler (irq_t *irq);
60 /* The network receive handler is fired as soon as network
61 * packets arrive. The network send handler is fired as soon
62 * as network packets have completed sending.
64 static irq_t recv_irq = { network_recv_handler, NULL, CPU_PRIO_UNKNOWN };
65 static irq_t send_irq = { network_send_handler, NULL, CPU_PRIO_UNKNOWN };
69 /* This upcall is used to report that the network
70 * has new data available. The bottom half will
71 * call this for the first packet to arrive after
72 * having failed an attempt to read input.
73 * More calls are possible for later arrivals of
74 * even more packets, and will be silently ignored
77 void top_network_can_recv (void) {
81 //ht162x_led_set (15, 1, true); // shown as (101)
85 /* This upcall is used to report that the network
86 * is certain to accept a full-size network packet.
87 * It is called by the bottom half after having
88 * failed an attempt to send output.
89 * Additional calls on the same matter are silently
92 void top_network_can_send (void) {
95 irq_fire (&send_irq); // Polling, so safe
100 /* This upcall is made to report that the network
101 * has gone offline. This may be detected at the
102 * hardware level, as a result of unplugging the
103 * cable and/or loosing sync.
104 * The state resulting from this is implied at the
105 * time of booting the device.
107 void top_network_offline (void) {
109 netcore_bootstrap_shutdown (); // TODO: wait 5 min, then call the user
113 /* This upcall is made to report that the network
114 * has come online. This is also called when the
115 * network card has been initialised properly.
117 void top_network_online (void) {
118 top_network_can_send (); // Polling, so safe
119 netcore_bootstrap_initiate ();
122 /* As the processor now has time for it, process
123 * the reception of network packets. Where simple
124 * stimulus-response action is possible, do that.
126 packet_t myrbuf;//TODO:ELSEWHERE//
127 packet_t mywbuf; // TODO: Allocate:ELSEWHERE
128 intptr_t mymem [MEM_NETVAR_COUNT];//TODO:ELSEWHERE//
129 static void network_recv_handler (irq_t *irq) {
130 intptr_t netinput (uint8_t *pkt, uint16_t pktlen, intptr_t *mem);
131 void ht162x_putchar (uint8_t idx, uint8_t ch, bool notify);
133 //TODO:TEST// ht162x_putchar (1, '0', true);
136 // TODO: rescheduling would be better than looping
138 uint16_t rbuflen = sizeof (myrbuf.data);
140 //TODO:TEST// ht162x_putchar (1, '1', true);
141 go = bottom_network_recv (myrbuf.data, &rbuflen);
143 goto done;//TODO//break;
145 //TODO:TEST// ht162x_putchar (1, '2', true);
146 //TODO:OVERZEALOUS// bottom_printf ("Received a network packet\n");
147 bzero (mymem, sizeof (mymem));
148 rf = (retfn *) netinput (myrbuf.data, rbuflen, mymem);
149 //TODO:TEST// ht162x_putchar (1, '3', true);
151 uint8_t *stop = (*rf) (mywbuf.data, mymem);
152 //TODO:TEST// ht162x_putchar (1, '4', true);
154 //TODO:TEST// ht162x_putchar (1, '5', true);
155 mymem [MEM_ALL_DONE] = (intptr_t) stop;
156 netcore_send_buffer (mymem, mywbuf.data);
157 //TODO:TEST// ht162x_putchar (1, '6', true);
159 //TODO:TEST// else ht162x_putchar (1, '7', true);
164 //TODO:TEST// ht162x_putchar (1, '8', true);
165 bottom_critical_region_begin ();
171 bottom_critical_region_end ();
173 //TODO:TEST// ht162x_putchar (1, '9', true);
177 /* As the processor now has time for it, process
178 * the sending of network packets.
180 static void network_send_handler (irq_t *irq) {
183 // TODO: Go over priority queues, bottom_network_send()