]> git.sesse.net Git - pistorm/blob - platforms/amiga/net/net_driver_amiga/pi-net-amiga-2.c
Update Pi-NET to new device driver framework
[pistorm] / platforms / amiga / net / net_driver_amiga / pi-net-amiga-2.c
1 // SPDX-License-Identifier: MIT
2
3 #include <exec/resident.h>
4 #include <exec/errors.h>
5 #include <exec/memory.h>
6 #include <exec/lists.h>
7 #include <exec/alerts.h>
8 #include <exec/tasks.h>
9 #include <exec/io.h>
10 #include <exec/execbase.h>
11 #include <exec/interrupts.h>
12 #include <hardware/intbits.h>
13
14 #include <libraries/expansion.h>
15
16 #include <devices/trackdisk.h>
17 #include <devices/timer.h>
18 #include <devices/scsidisk.h>
19
20 #include <dos/filehandler.h>
21 #include <dos/dostags.h>
22
23 #include <proto/exec.h>
24 #include <proto/disk.h>
25 #include <proto/expansion.h>
26 #include <proto/utility.h>
27 #include <proto/dos.h>
28
29 #include <utility/tagitem.h>
30
31 //#include <clib/exec_protos.h>
32 #include <clib/alib_protos.h>
33 //#include <clib/debug_protos.h>
34 #include "sana2.h"
35 #include "../pi-net-enums.h"
36
37 #include <string.h>
38 #include <stdint.h>
39 #include <stdlib.h>
40
41 #define STR(s) #s
42 #define XSTR(s) STR(s)
43
44 #define DEVICE_NAME "pi-net.device"
45 #define DEVICE_DATE "(14 May 2021)"
46 #define DEVICE_ID_STRING "Pi-NET " XSTR(DEVICE_VERSION) "." XSTR(DEVICE_REVISION) " " DEVICE_DATE
47 #define DEVICE_VERSION 43
48 #define DEVICE_REVISION 10
49 #define DEVICE_PRIORITY 0
50
51 #pragma pack(4)
52 struct pinet_base {
53     struct Device* pi_dev;
54     struct Unit unit;
55     uint8_t MAC[6];
56     uint8_t IP[4];
57
58         struct List read_list;
59         struct SignalSemaphore read_list_sem;
60 };
61
62 struct ExecBase* SysBase = NULL;
63 uint8_t *saved_seg_list;
64 uint8_t is_open;
65
66 #define WRITESHORT(cmd, val) *(unsigned short *)((unsigned long)(PINET_OFFSET + cmd)) = val;
67 #define WRITELONG(cmd, val) *(unsigned long *)((unsigned long)(PINET_OFFSET + cmd)) = val;
68 #define WRITEBYTE(cmd, val) *(unsigned char *)((unsigned long)(PINET_OFFSET + cmd)) = val;
69
70 #define READBYTE(cmd, var) var = *(volatile unsigned char *)(PINET_OFFSET + cmd);
71 #define READSHORT(cmd, var) var = *(volatile unsigned short *)(PINET_OFFSET + cmd);
72 #define READLONG(cmd, var) var = *(volatile unsigned long *)(PINET_OFFSET + cmd);
73
74 int __attribute__((no_reorder)) _start()
75 {
76     return -1;
77 }
78
79 asm("romtag:                                \n"
80     "       dc.w    "XSTR(RTC_MATCHWORD)"   \n"
81     "       dc.l    romtag                  \n"
82     "       dc.l    endcode                 \n"
83     "       dc.b    "XSTR(RTF_AUTOINIT)"    \n"
84     "       dc.b    "XSTR(DEVICE_VERSION)"  \n"
85     "       dc.b    "XSTR(NT_DEVICE)"       \n"
86     "       dc.b    "XSTR(DEVICE_PRIORITY)" \n"
87     "       dc.l    _device_name            \n"
88     "       dc.l    _device_id_string       \n"
89     "       dc.l    _auto_init_tables       \n"
90     "endcode:                               \n");
91 char device_name[] = DEVICE_NAME;
92 char device_id_string[] = DEVICE_ID_STRING;
93
94 typedef struct BufferManagement
95 {
96   struct MinNode   bm_Node;
97   BOOL           (*bm_CopyFromBuffer)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
98   BOOL           (*bm_CopyToBuffer)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
99 } BufferManagement;
100
101 struct pinet_base *dev_base = NULL;
102
103 //#define exit(...)
104 //#define debug(...)
105 #define kprintf(...)
106
107 static struct Library __attribute__((used)) *init_device(struct Device* dev) {
108         uint8_t *p;
109         uint32_t i;
110         int32_t  ok;
111
112     // Unused variables
113     if (ok || i || p) { }
114
115     SysBase = *(struct ExecBase **)4L;
116
117     kprintf("Initializing net device.\n");
118
119     dev_base = AllocMem(sizeof(struct pinet_base), MEMF_PUBLIC | MEMF_CLEAR);
120     dev_base->pi_dev = dev;
121
122     kprintf("Grabbing MAC.\n");
123     for (int i = 0; i < 6; i++) {
124         READBYTE((PINET_CMD_MAC + i), dev_base->MAC[i]);
125     }
126     kprintf("Grabbing IP.\n");
127     for (int i = 0; i < 4; i++) {
128         READBYTE((PINET_CMD_IP + i), dev_base->IP[i]);
129     }
130
131         return (struct Library *)dev;
132 }
133
134 static uint8_t* __attribute__((used)) expunge(void) {
135     kprintf("Cleaning up.\n");
136     FreeMem(dev_base, sizeof(struct pinet_base));
137     return 0;
138 }
139
140 static void __attribute__((used)) open(struct IORequest *io, uint32_t num, uint32_t flags) {
141     struct IOSana2Req *ioreq = (struct IOSana2Req *)io;
142         int32_t ok = 0, ret = IOERR_OPENFAIL;
143     struct BufferManagement *bm;
144
145     kprintf("Opening net device %ld.\n", num);
146     dev_base->unit.unit_OpenCnt++;
147
148     // Unused variables
149     if (bm || ok) { }
150
151     if (num == 0 && dev_base->unit.unit_OpenCnt == 1) {
152         //kprintf("Trying to alloc buffer management.\n");
153         //if ((bm = (struct BufferManagement*)AllocVec(sizeof(struct BufferManagement), MEMF_CLEAR | MEMF_PUBLIC))) {
154             //kprintf("Setting up buffer copy funcs (1).\n");
155             //bm->bm_CopyToBuffer = (BOOL *)GetTagData(S2_CopyToBuff, 0, (struct TagItem *)ioreq->ios2_BufferManagement);
156             //kprintf("Setting up buffer copy funcs (2).\n");
157             //bm->bm_CopyFromBuffer = (BOOL *)GetTagData(S2_CopyFromBuff, 0, (struct TagItem *)ioreq->ios2_BufferManagement);
158
159             kprintf("Doing more things.\n");
160             ioreq->ios2_BufferManagement = NULL;//(VOID *)bm;
161             ioreq->ios2_Req.io_Error = 0;
162             ioreq->ios2_Req.io_Unit = (struct Unit *)&dev_base->unit;
163             ioreq->ios2_Req.io_Device = (struct Device *)dev_base->pi_dev;
164
165             kprintf("New list.\n");
166
167             NewList(&dev_base->read_list);
168             InitSemaphore(&dev_base->read_list_sem);
169
170             ret = 0;
171             ok = 1;
172         //}
173     }
174
175     if (ret == IOERR_OPENFAIL) {
176         kprintf("Failed to open device. Already open?\n");
177     }
178     else {
179         kprintf("Device opened, yay.\n");
180     }
181     ioreq->ios2_Req.io_Error = ret;
182     ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
183
184     kprintf("Opened device, return code: %ld\n", ret);
185 }
186
187 static uint8_t* __attribute__((used)) close(struct IORequest *io) {
188     return 0;
189 }
190
191 uint32_t pinet_read_frame(struct IOSana2Req *ioreq) {
192     return 0;
193 }
194
195 void pinet_write_frame(struct IOSana2Req *ioreq) {
196 }
197
198
199 static void __attribute__((used)) begin_io(struct IORequest *io) {
200     struct IOSana2Req *ioreq = (struct IOSana2Req *)io;
201     ULONG unit = (ULONG)ioreq->ios2_Req.io_Unit;
202     int mtu;
203
204     ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
205     ioreq->ios2_Req.io_Error = S2ERR_NO_ERROR;
206     ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
207
208     //D(("BeginIO command %ld unit %ld\n",(LONG)ioreq->ios2_Req.io_Command,unit));
209
210     // Unused variables
211     if (mtu || unit) {}
212
213     switch( ioreq->ios2_Req.io_Command ) {
214         case CMD_READ:
215             kprintf("Read\n");
216             if (pinet_read_frame(ioreq) != 0) {
217                 ioreq->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
218                 ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
219             }
220             ioreq = NULL;
221             break;
222         case S2_BROADCAST:
223             kprintf("Broadcast\n");
224             if (ioreq->ios2_DstAddr) {
225                 for (int i = 0; i < ADDRFIELDSIZE; i++) {
226                     ioreq->ios2_DstAddr[i] = 0xFF;
227                 }
228             } else {
229                 kprintf("Invalid ios2_DstAddr\n");
230             }
231             /* Fallthrough */
232         case CMD_WRITE: {
233             kprintf("Write\n");
234             pinet_write_frame(ioreq);
235             break;
236         }
237
238         case S2_READORPHAN:
239             ioreq->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
240             ioreq = NULL;
241             break;
242         case S2_ONLINE:
243         case S2_OFFLINE:
244         case S2_CONFIGINTERFACE:   /* forward request */
245             break;
246
247         case S2_GETSTATIONADDRESS:
248             for (int i = 0; i < ADDRFIELDSIZE; i++) {
249                 ioreq->ios2_SrcAddr[i] = dev_base->MAC[i];
250                 ioreq->ios2_DstAddr[i] = dev_base->MAC[i];
251             }
252             break;
253         case S2_DEVICEQUERY: {
254             struct Sana2DeviceQuery *devquery;
255
256             devquery = ioreq->ios2_StatData;
257             devquery->DevQueryFormat = 0;
258             devquery->DeviceLevel = 0;
259
260             if (devquery->SizeAvailable >= 18)
261                 devquery->AddrFieldSize = ADDRFIELDSIZE * 8;
262             if (devquery->SizeAvailable >= 22)
263                 devquery->MTU           = 1500;
264             if (devquery->SizeAvailable >= 26)
265                 devquery->BPS           =  1000 * 1000 * 100;
266             if (devquery->SizeAvailable >= 30)
267                 devquery->HardwareType  = S2WireType_Ethernet;
268
269             devquery->SizeSupplied = (devquery->SizeAvailable < 30) ? devquery->SizeAvailable : 30;
270             break;
271         }
272         case S2_GETSPECIALSTATS: {
273             struct Sana2SpecialStatHeader *s2ssh = (struct Sana2SpecialStatHeader *)ioreq->ios2_StatData;
274             s2ssh->RecordCountSupplied = 0;
275             break;
276         }
277         default: {
278             uint8_t cmd = ioreq->ios2_Req.io_Command;
279             if (cmd) {}
280             kprintf("Unknown/unhandled IO command %lx\n", cmd);
281             ioreq->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
282             ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
283             break;
284         }
285     }
286
287     if (ioreq) {
288         if (!(ioreq->ios2_Req.io_Flags & SANA2IOF_QUICK)) {
289             ReplyMsg((struct Message *)ioreq);
290         } else {
291             ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
292         }
293     }
294 }
295
296 static uint32_t __attribute__((used)) abort_io(struct IORequest* ioreq) {
297     struct IOSana2Req* ios2 = (struct IOSana2Req*)ioreq;
298
299     if (!ioreq) return IOERR_NOCMD;
300         ioreq->io_Error = IOERR_ABORTED;
301     ios2->ios2_WireError = 0;
302
303     return IOERR_ABORTED;
304 }
305
306 static uint32_t device_vectors[] = {
307     (uint32_t)open,
308     (uint32_t)close,
309     (uint32_t)expunge,
310     0,
311     (uint32_t)begin_io,
312     (uint32_t)abort_io,
313     -1
314 };
315
316 const uint32_t auto_init_tables[4] = {
317     sizeof(struct Library),
318     (uint32_t)device_vectors,
319     0,
320     (uint32_t)init_device
321 };