]> git.sesse.net Git - pistorm/blob - a314/a314device/a314driver.c
6db2dc69af178c34bbdbb0e3f0489a9f3ea5f39c
[pistorm] / a314 / a314device / a314driver.c
1 /*
2  * Copyright (c) 2018 Niklas Ekström
3  */
4
5 #include <exec/types.h>
6 #include <exec/interrupts.h>
7 #include <exec/lists.h>
8 #include <exec/memory.h>
9 #include <exec/nodes.h>
10 #include <exec/ports.h>
11 #include <exec/io.h>
12 #include <exec/errors.h>
13 #include <exec/libraries.h>
14 #include <exec/devices.h>
15 #include <exec/execbase.h>
16
17 #include <libraries/dos.h>
18
19 #include <proto/exec.h>
20
21 #include <string.h>
22
23 #include "a314.h"
24 #include "debug.h"
25 #include "device.h"
26 #include "protocol.h"
27 #include "sockets.h"
28 #include "fix_mem_region.h"
29 #include "startup.h"
30
31 int used_in_r2a()
32 {
33         return (ca->r2a_tail - ca->r2a_head) & 255;
34 }
35
36 int used_in_a2r()
37 {
38         return (ca->a2r_tail - ca->a2r_head) & 255;
39 }
40
41 BOOL room_in_a2r(int len)
42 {
43         return used_in_a2r() + 3 + len <= 255;
44 }
45
46 void append_a2r_packet(UBYTE type, UBYTE stream_id, UBYTE length, UBYTE *data)
47 {
48         UBYTE index = ca->a2r_tail;
49         ca->a2r_buffer[index++] = length;
50         ca->a2r_buffer[index++] = type;
51         ca->a2r_buffer[index++] = stream_id;
52         for (int i = 0; i < (int)length; i++)
53                 ca->a2r_buffer[index++] = *data++;
54         ca->a2r_tail = index;
55 }
56
57 void close_socket(struct Socket *s, BOOL should_send_reset)
58 {
59         debug_printf("Called close socket\n");
60
61         if (s->pending_connect != NULL)
62         {
63                 struct A314_IORequest *ior = s->pending_connect;
64                 ior->a314_Request.io_Error = A314_CONNECT_RESET;
65                 ReplyMsg((struct Message *)ior);
66
67                 s->pending_connect = NULL;
68         }
69
70         if (s->pending_read != NULL)
71         {
72                 struct A314_IORequest *ior = s->pending_read;
73                 ior->a314_Length = 0;
74                 ior->a314_Request.io_Error = A314_READ_RESET;
75                 ReplyMsg((struct Message *)ior);
76
77                 s->pending_read = NULL;
78         }
79
80         if (s->pending_write != NULL)
81         {
82                 struct A314_IORequest *ior = s->pending_write;
83                 ior->a314_Length = 0;
84                 ior->a314_Request.io_Error = A314_WRITE_RESET; // A314_EOS_RESET == A314_WRITE_RESET
85                 ReplyMsg((struct Message *)ior);
86
87                 s->pending_write = NULL;
88         }
89
90         if (s->rq_head != NULL)
91         {
92                 struct QueuedData *qd = s->rq_head;
93                 while (qd != NULL)
94                 {
95                         struct QueuedData *next = qd->next;
96                         FreeMem(qd, sizeof(struct QueuedData) + qd->length);
97                         qd = next;
98                 }
99                 s->rq_head = NULL;
100                 s->rq_tail = NULL;
101         }
102
103         remove_from_send_queue(s);
104
105         // No operations can be pending when SOCKET_CLOSED is set.
106         // However, may not be able to delete socket yet, because is waiting to send PKT_RESET.
107         s->flags |= SOCKET_CLOSED;
108
109         BOOL should_delete_socket = TRUE;
110
111         if (should_send_reset)
112         {
113                 if (send_queue_head == NULL && room_in_a2r(0))
114                 {
115                         append_a2r_packet(PKT_RESET, s->stream_id, 0, NULL);
116                 }
117                 else
118                 {
119                         s->flags |= SOCKET_SHOULD_SEND_RESET;
120                         add_to_send_queue(s, 0);
121                         should_delete_socket = FALSE;
122                 }
123         }
124
125         if (should_delete_socket)
126                 delete_socket(s);
127 }
128
129 // When a message is received on R2A it is written to this buffer,
130 // to avoid dealing with the issue that R2A is a circular buffer.
131 // This is somewhat inefficient, so may want to change that to read from R2A directly.
132 UBYTE received_packet[256];
133
134 static void handle_pkt_connect_response(UBYTE length, struct Socket *s)
135 {
136         debug_printf("Received a CONNECT RESPONSE packet from rpi\n");
137
138         if (s->pending_connect == NULL)
139         {
140                 debug_printf("SERIOUS ERROR: received a CONNECT RESPONSE even though no connect was pending\n");
141                 // Should reset stream?
142         }
143         else if (length != 1)
144         {
145                 debug_printf("SERIOUS ERROR: received a CONNECT RESPONSE whose length was not 1\n");
146                 // Should reset stream?
147         }
148         else
149         {
150                 UBYTE result = received_packet[0];
151                 if (result == 0)
152                 {
153                         struct A314_IORequest *ior = s->pending_connect;
154                         ior->a314_Request.io_Error = A314_CONNECT_OK;
155                         ReplyMsg((struct Message *)ior);
156
157                         s->pending_connect = NULL;
158                 }
159                 else
160                 {
161                         struct A314_IORequest *ior = s->pending_connect;
162                         ior->a314_Request.io_Error = A314_CONNECT_UNKNOWN_SERVICE;
163                         ReplyMsg((struct Message *)ior);
164
165                         s->pending_connect = NULL;
166
167                         close_socket(s, FALSE);
168                 }
169         }
170 }
171
172 static void handle_pkt_data(UBYTE length, struct Socket *s)
173 {
174         debug_printf("Received a DATA packet from rpi\n");
175
176         if (s->pending_read != NULL)
177         {
178                 struct A314_IORequest *ior = s->pending_read;
179
180                 if (ior->a314_Length < length)
181                         close_socket(s, TRUE);
182                 else
183                 {
184                         memcpy(ior->a314_Buffer, received_packet, length);
185                         ior->a314_Length = length;
186                         ior->a314_Request.io_Error = A314_READ_OK;
187                         ReplyMsg((struct Message *)ior);
188
189                         s->pending_read = NULL;
190                 }
191         }
192         else
193         {
194                 struct QueuedData *qd = (struct QueuedData *)AllocMem(sizeof(struct QueuedData) + length, 0);
195                 qd->next = NULL,
196                 qd->length = length;
197                 memcpy(qd->data, received_packet, length);
198
199                 if (s->rq_head == NULL)
200                         s->rq_head = qd;
201                 else
202                         s->rq_tail->next = qd;
203                 s->rq_tail = qd;
204         }
205 }
206
207 static void handle_pkt_eos(struct Socket *s)
208 {
209         debug_printf("Received a EOS packet from rpi\n");
210
211         s->flags |= SOCKET_RCVD_EOS_FROM_RPI;
212
213         if (s->pending_read != NULL)
214         {
215                 struct A314_IORequest *ior = s->pending_read;
216                 ior->a314_Length = 0;
217                 ior->a314_Request.io_Error = A314_READ_EOS;
218                 ReplyMsg((struct Message *)ior);
219
220                 s->pending_read = NULL;
221
222                 s->flags |= SOCKET_SENT_EOS_TO_APP;
223
224                 if (s->flags & SOCKET_SENT_EOS_TO_RPI)
225                         close_socket(s, FALSE);
226         }
227 }
228
229 static void handle_r2a_packet(UBYTE type, UBYTE stream_id, UBYTE length)
230 {
231         struct Socket *s = find_socket_by_stream_id(stream_id);
232
233         if (s != NULL && type == PKT_RESET)
234         {
235                 debug_printf("Received a RESET packet from rpi\n");
236                 close_socket(s, FALSE);
237                 return;
238         }
239
240         if (s == NULL || (s->flags & SOCKET_CLOSED))
241         {
242                 // Ignore this packet. The only packet that can do anything useful on a closed
243                 // channel is CONNECT, which is not handled at this time.
244                 return;
245         }
246
247         if (type == PKT_CONNECT_RESPONSE)
248         {
249                 handle_pkt_connect_response(length, s);
250         }
251         else if (type == PKT_DATA)
252         {
253                 handle_pkt_data(length, s);
254         }
255         else if (type == PKT_EOS)
256         {
257                 handle_pkt_eos(s);
258         }
259 }
260
261 void handle_packets_received_r2a()
262 {
263         while (used_in_r2a() != 0)
264         {
265                 UBYTE index = ca->r2a_head;
266
267                 UBYTE len = ca->r2a_buffer[index++];
268                 UBYTE type = ca->r2a_buffer[index++];
269                 UBYTE stream_id = ca->r2a_buffer[index++];
270
271                 for (int i = 0; i < len; i++)
272                         received_packet[i] = ca->r2a_buffer[index++];
273
274                 ca->r2a_head = index;
275
276                 handle_r2a_packet(type, stream_id, len);
277         }
278 }
279
280 void handle_room_in_a2r()
281 {
282         while (send_queue_head != NULL)
283         {
284                 struct Socket *s = send_queue_head;
285
286                 if (!room_in_a2r(s->send_queue_required_length))
287                         break;
288
289                 remove_from_send_queue(s);
290
291                 if (s->pending_connect != NULL)
292                 {
293                         struct A314_IORequest *ior = s->pending_connect;
294                         int len = ior->a314_Length;
295                         append_a2r_packet(PKT_CONNECT, s->stream_id, (UBYTE)len, ior->a314_Buffer);
296                 }
297                 else if (s->pending_write != NULL)
298                 {
299                         struct A314_IORequest *ior = s->pending_write;
300                         int len = ior->a314_Length;
301
302                         if (ior->a314_Request.io_Command == A314_WRITE)
303                         {
304                                 append_a2r_packet(PKT_DATA, s->stream_id, (UBYTE)len, ior->a314_Buffer);
305
306                                 ior->a314_Request.io_Error = A314_WRITE_OK;
307                                 ReplyMsg((struct Message *)ior);
308
309                                 s->pending_write = NULL;
310                         }
311                         else // A314_EOS
312                         {
313                                 append_a2r_packet(PKT_EOS, s->stream_id, 0, NULL);
314
315                                 ior->a314_Request.io_Error = A314_EOS_OK;
316                                 ReplyMsg((struct Message *)ior);
317
318                                 s->pending_write = NULL;
319
320                                 s->flags |= SOCKET_SENT_EOS_TO_RPI;
321
322                                 if (s->flags & SOCKET_SENT_EOS_TO_APP)
323                                         close_socket(s, FALSE);
324                         }
325                 }
326                 else if (s->flags & SOCKET_SHOULD_SEND_RESET)
327                 {
328                         append_a2r_packet(PKT_RESET, s->stream_id, 0, NULL);
329                         delete_socket(s);
330                 }
331                 else
332                 {
333                         debug_printf("SERIOUS ERROR: Was in send queue but has nothing to send\n");
334                 }
335         }
336 }
337
338 static void handle_app_connect(struct A314_IORequest *ior, struct Socket *s)
339 {
340         debug_printf("Received a CONNECT request from application\n");
341
342         if (s != NULL)
343         {
344                 ior->a314_Request.io_Error = A314_CONNECT_SOCKET_IN_USE;
345                 ReplyMsg((struct Message *)ior);
346         }
347         else if (ior->a314_Length + 3 > 255)
348         {
349                 ior->a314_Request.io_Error = A314_CONNECT_RESET;
350                 ReplyMsg((struct Message *)ior);
351         }
352         else
353         {
354                 s = create_socket(ior->a314_Request.io_Message.mn_ReplyPort->mp_SigTask, ior->a314_Socket);
355
356                 s->pending_connect = ior;
357                 s->flags = 0;
358
359                 int len = ior->a314_Length;
360                 if (send_queue_head == NULL && room_in_a2r(len))
361                 {
362                         append_a2r_packet(PKT_CONNECT, s->stream_id, (UBYTE)len, ior->a314_Buffer);
363                 }
364                 else
365                 {
366                         add_to_send_queue(s, len);
367                 }
368         }
369 }
370
371 static void handle_app_read(struct A314_IORequest *ior, struct Socket *s)
372 {
373         debug_printf("Received a READ request from application\n");
374
375         if (s == NULL || (s->flags & SOCKET_CLOSED))
376         {
377                 ior->a314_Length = 0;
378                 ior->a314_Request.io_Error = A314_READ_RESET;
379                 ReplyMsg((struct Message *)ior);
380         }
381         else
382         {
383                 if (s->pending_connect != NULL || s->pending_read != NULL)
384                 {
385                         ior->a314_Length = 0;
386                         ior->a314_Request.io_Error = A314_READ_RESET;
387                         ReplyMsg((struct Message *)ior);
388
389                         close_socket(s, TRUE);
390                 }
391                 else if (s->rq_head != NULL)
392                 {
393                         struct QueuedData *qd = s->rq_head;
394                         int len = qd->length;
395
396                         if (ior->a314_Length < len)
397                         {
398                                 ior->a314_Length = 0;
399                                 ior->a314_Request.io_Error = A314_READ_RESET;
400                                 ReplyMsg((struct Message *)ior);
401
402                                 close_socket(s, TRUE);
403                         }
404                         else
405                         {
406                                 s->rq_head = qd->next;
407                                 if (s->rq_head == NULL)
408                                         s->rq_tail = NULL;
409
410                                 memcpy(ior->a314_Buffer, qd->data, len);
411                                 FreeMem(qd, sizeof(struct QueuedData) + len);
412
413                                 ior->a314_Length = len;
414                                 ior->a314_Request.io_Error = A314_READ_OK;
415                                 ReplyMsg((struct Message *)ior);
416                         }
417                 }
418                 else if (s->flags & SOCKET_RCVD_EOS_FROM_RPI)
419                 {
420                         ior->a314_Length = 0;
421                         ior->a314_Request.io_Error = A314_READ_EOS;
422                         ReplyMsg((struct Message *)ior);
423
424                         s->flags |= SOCKET_SENT_EOS_TO_APP;
425
426                         if (s->flags & SOCKET_SENT_EOS_TO_RPI)
427                                 close_socket(s, FALSE);
428                 }
429                 else
430                         s->pending_read = ior;
431         }
432 }
433
434 static void handle_app_write(struct A314_IORequest *ior, struct Socket *s)
435 {
436         debug_printf("Received a WRITE request from application\n");
437
438         if (s == NULL || (s->flags & SOCKET_CLOSED))
439         {
440                 ior->a314_Length = 0;
441                 ior->a314_Request.io_Error = A314_WRITE_RESET;
442                 ReplyMsg((struct Message *)ior);
443         }
444         else
445         {
446                 int len = ior->a314_Length;
447                 if (s->pending_connect != NULL || s->pending_write != NULL || (s->flags & SOCKET_RCVD_EOS_FROM_APP) || len + 3 > 255)
448                 {
449                         ior->a314_Length = 0;
450                         ior->a314_Request.io_Error = A314_WRITE_RESET;
451                         ReplyMsg((struct Message *)ior);
452
453                         close_socket(s, TRUE);
454                 }
455                 else
456                 {
457                         if (send_queue_head == NULL && room_in_a2r(len))
458                         {
459                                 append_a2r_packet(PKT_DATA, s->stream_id, (UBYTE)len, ior->a314_Buffer);
460
461                                 ior->a314_Request.io_Error = A314_WRITE_OK;
462                                 ReplyMsg((struct Message *)ior);
463                         }
464                         else
465                         {
466                                 s->pending_write = ior;
467                                 add_to_send_queue(s, len);
468                         }
469                 }
470         }
471 }
472
473 static void handle_app_eos(struct A314_IORequest *ior, struct Socket *s)
474 {
475         debug_printf("Received an EOS request from application\n");
476
477         if (s == NULL || (s->flags & SOCKET_CLOSED))
478         {
479                 ior->a314_Request.io_Error = A314_EOS_RESET;
480                 ReplyMsg((struct Message *)ior);
481         }
482         else
483         {
484                 if (s->pending_connect != NULL || s->pending_write != NULL || (s->flags & SOCKET_RCVD_EOS_FROM_APP))
485                 {
486                         ior->a314_Length = 0;
487                         ior->a314_Request.io_Error = A314_EOS_RESET;
488                         ReplyMsg((struct Message *)ior);
489
490                         close_socket(s, TRUE);
491                 }
492                 else
493                 {
494                         s->flags |= SOCKET_RCVD_EOS_FROM_APP;
495
496                         if (send_queue_head == NULL && room_in_a2r(0))
497                         {
498                                 append_a2r_packet(PKT_EOS, s->stream_id, 0, NULL);
499
500                                 ior->a314_Request.io_Error = A314_EOS_OK;
501                                 ReplyMsg((struct Message *)ior);
502
503                                 s->flags |= SOCKET_SENT_EOS_TO_RPI;
504
505                                 if (s->flags & SOCKET_SENT_EOS_TO_APP)
506                                         close_socket(s, FALSE);
507                         }
508                         else
509                         {
510                                 s->pending_write = ior;
511                                 add_to_send_queue(s, 0);
512                         }
513                 }
514         }
515 }
516
517 static void handle_app_reset(struct A314_IORequest *ior, struct Socket *s)
518 {
519         debug_printf("Received a RESET request from application\n");
520
521         if (s == NULL || (s->flags & SOCKET_CLOSED))
522         {
523                 ior->a314_Request.io_Error = A314_RESET_OK;
524                 ReplyMsg((struct Message *)ior);
525         }
526         else
527         {
528                 ior->a314_Request.io_Error = A314_RESET_OK;
529                 ReplyMsg((struct Message *)ior);
530
531                 close_socket(s, TRUE);
532         }
533 }
534
535 static void handle_app_request(struct A314_IORequest *ior)
536 {
537         struct Socket *s = find_socket(ior->a314_Request.io_Message.mn_ReplyPort->mp_SigTask, ior->a314_Socket);
538
539         switch (ior->a314_Request.io_Command)
540         {
541         case A314_CONNECT:
542                 handle_app_connect(ior, s);
543                 break;
544         case A314_READ:
545                 handle_app_read(ior, s);
546                 break;
547         case A314_WRITE:
548                 handle_app_write(ior, s);
549                 break;
550         case A314_EOS:
551                 handle_app_eos(ior, s);
552                 break;
553         case A314_RESET:
554                 handle_app_reset(ior, s);
555                 break;
556         default:
557                 ior->a314_Request.io_Error = IOERR_NOCMD;
558                 ReplyMsg((struct Message *)ior);
559                 break;
560         }
561 }
562
563 void task_main()
564 {
565         while (TRUE)
566         {
567                 debug_printf("Waiting for signal\n");
568
569                 ULONG signal = Wait(SIGF_MSGPORT | SIGF_INT);
570
571                 UBYTE prev_a2r_tail = ca->a2r_tail;
572                 UBYTE prev_r2a_head = ca->r2a_head;
573
574                 if (signal & SIGF_MSGPORT)
575                 {
576                         ca->a_enable = 0;
577
578                         struct Message *msg;
579                         while (msg = GetMsg(&task_mp))
580                                 handle_app_request((struct A314_IORequest *)msg);
581                 }
582
583                 UBYTE a_enable = 0;
584                 while (a_enable == 0)
585                 {
586                         handle_packets_received_r2a();
587                         handle_room_in_a2r();
588
589                         UBYTE r_events = 0;
590                         if (ca->a2r_tail != prev_a2r_tail)
591                                 r_events |= R_EVENT_A2R_TAIL;
592                         if (ca->r2a_head != prev_r2a_head)
593                                 r_events |= R_EVENT_R2A_HEAD;
594
595                         UBYTE discard_value = ca->a_events;
596
597                         if (ca->r2a_head == ca->r2a_tail)
598                         {
599                                 if (send_queue_head == NULL)
600                                         a_enable = A_EVENT_R2A_TAIL;
601                                 else if (!room_in_a2r(send_queue_head->send_queue_required_length))
602                                         a_enable = A_EVENT_R2A_TAIL | A_EVENT_A2R_HEAD;
603
604                                 if (a_enable != 0)
605                                 {
606                                         ca->a_enable = a_enable;
607                                         if (r_events != 0)
608                                                 ca->r_events = r_events;
609                                 }
610                         }
611                 }
612         }
613
614         // There is currently no way to unload a314.device.
615
616         //debug_printf("Shutting down\n");
617
618         //RemIntServer(INTB_PORTS, &ports_interrupt);
619         //RemIntServer(INTB_VERTB, &vertb_interrupt);
620         //FreeMem(ca, sizeof(struct ComArea));
621
622         // Stack and task structure should be reclaimed.
623 }