]> git.sesse.net Git - pistorm/blob - platforms/amiga/net/net_driver_amiga/pi-net-amiga.c
Add license information to source
[pistorm] / platforms / amiga / net / net_driver_amiga / pi-net-amiga.c
1 // SPDX-License-Identifier: MIT
2
3 #include <exec/resident.h>
4 #include <exec/memory.h>
5 #include <exec/alerts.h>
6 #include <exec/io.h>
7 #include <exec/execbase.h>
8 #include <libraries/expansion.h>
9 #include <dos/filehandler.h>
10 #include <proto/exec.h>
11 #include <proto/utility.h>
12 #include <proto/dos.h>
13 #include <proto/expansion.h>
14 #include <clib/exec_protos.h>
15 #include <clib/alib_protos.h>
16 #include <dos/dostags.h>
17 #include <utility/tagitem.h>
18 #include <exec/lists.h>
19 #include <exec/errors.h>
20 #include <exec/interrupts.h>
21 #include <exec/tasks.h>
22 #include <hardware/intbits.h>
23 #include <string.h>
24 #include "sana2.h"
25 #include "../pi-net-enums.h"
26
27 #include <clib/debug_protos.h>
28 #include <stdint.h>
29 #include <stdlib.h>
30
31 #define WRITESHORT(cmd, val) *(unsigned short *)((unsigned long)(PINET_OFFSET + cmd)) = val;
32 #define WRITELONG(cmd, val) *(unsigned long *)((unsigned long)(PINET_OFFSET + cmd)) = val;
33 #define WRITEBYTE(cmd, val) *(unsigned char *)((unsigned long)(PINET_OFFSET + cmd)) = val;
34
35 #define READBYTE(cmd, var) var = *(volatile unsigned char *)(PINET_OFFSET + cmd);
36 #define READSHORT(cmd, var) var = *(volatile unsigned short *)(PINET_OFFSET + cmd);
37 #define READLONG(cmd, var) var = *(volatile unsigned long *)(PINET_OFFSET + cmd);
38
39 //typedef BOOL (*BMFunc)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
40
41 typedef struct BufferManagement
42 {
43   struct MinNode   bm_Node;
44   BOOL           (*bm_CopyFromBuffer)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
45   BOOL           (*bm_CopyToBuffer)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
46 } BufferManagement;
47
48 #pragma pack(4)
49 struct pinet_base {
50     struct Device* pi_dev;
51     struct Unit unit;
52     uint8_t MAC[6];
53     uint8_t IP[4];
54
55         struct List read_list;
56         struct SignalSemaphore read_list_sem;
57 };
58
59 struct ExecBase* SysBase = NULL;
60
61 const char DevName[] = "pi-net.device";
62 const char DevIdString[] = "Pi-NET 0.1";
63
64 const UWORD DevVersion = 1;
65 const UWORD DevRevision = 0;
66
67 #include "stabs.h"
68
69 struct pinet_base *dev_base = NULL;
70
71 struct WBStartup *_WBenchMsg = NULL;
72
73 //#define exit(...)
74 //#define debug(...)
75 //#define KPrintF(...)
76
77 uint32_t __UserDevInit(struct Device* dev) {
78         uint8_t *p;
79         uint32_t i;
80         int32_t  ok;
81
82     SysBase = *(struct ExecBase **)4L;
83
84     KPrintF("Initializing net device.\n");
85
86     dev_base = AllocMem(sizeof(struct pinet_base), MEMF_PUBLIC | MEMF_CLEAR);
87     dev_base->pi_dev = dev;
88
89     KPrintF("Grabbing MAC.\n");
90     for (int i = 0; i < 6; i++) {
91         READBYTE((PINET_CMD_MAC + i), dev_base->MAC[i]);
92     }
93     KPrintF("Grabbing IP.\n");
94     for (int i = 0; i < 4; i++) {
95         READBYTE((PINET_CMD_IP + i), dev_base->IP[i]);
96     }
97
98         return (uint32_t)dev;
99 }
100
101 uint32_t __UserDevCleanup(void) {
102     KPrintF("Cleaning up.\n");
103     FreeMem(dev_base, sizeof(struct pinet_base));
104     return 0;
105 }
106
107 uint32_t __UserDevOpen(struct IORequest *io, uint32_t num, uint32_t flags) {
108     struct IOSana2Req *ioreq = (struct IOSana2Req *)io;
109         uint32_t ok = 0, ret = IOERR_OPENFAIL;
110     struct BufferManagement *bm;
111
112     KPrintF("Opening net device %ld.\n", num);
113     dev_base->unit.unit_OpenCnt++;
114
115     if (num == 0 && dev_base->unit.unit_OpenCnt == 1) {
116         //KPrintF("Trying to alloc buffer management.\n");
117         //if ((bm = (struct BufferManagement*)AllocVec(sizeof(struct BufferManagement), MEMF_CLEAR | MEMF_PUBLIC))) {
118             //KPrintF("Setting up buffer copy funcs (1).\n");
119             //bm->bm_CopyToBuffer = (BOOL *)GetTagData(S2_CopyToBuff, 0, (struct TagItem *)ioreq->ios2_BufferManagement);
120             //KPrintF("Setting up buffer copy funcs (2).\n");
121             //bm->bm_CopyFromBuffer = (BOOL *)GetTagData(S2_CopyFromBuff, 0, (struct TagItem *)ioreq->ios2_BufferManagement);
122
123             KPrintF("Doing more things.\n");
124             ioreq->ios2_BufferManagement = NULL;//(VOID *)bm;
125             ioreq->ios2_Req.io_Error = 0;
126             ioreq->ios2_Req.io_Unit = (struct Unit *)&dev_base->unit;
127             ioreq->ios2_Req.io_Device = (struct Device *)dev_base->pi_dev;
128
129             KPrintF("New list.\n");
130
131             NewList(&dev_base->read_list);
132             InitSemaphore(&dev_base->read_list_sem);
133
134             ret = 0;
135             ok = 1;
136         //}
137     }
138
139     if (ret == IOERR_OPENFAIL) {
140         KPrintF("Failed to open device. Already open?\n");
141     }
142     else {
143         KPrintF("Device opened, yay.\n");
144     }
145     ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
146
147     KPrintF("Opened device, return code: %ld\n", ret);
148
149     return ret;
150 }
151
152 uint32_t __UserDevClose(struct IORequest *io) {
153   return 0;
154 }
155
156 uint32_t pinet_read_frame(struct IOSana2Req *ioreq) {
157     uint32_t datasize;
158     uint8_t *frame_ptr;
159     uint8_t broadcast;
160     uint32_t err = 0;
161     struct BufferManagement *bm;
162
163     /*uint8_t* frm = (uint8_t *)(PINET_OFFSET + PINET_CMD_FRAME);
164     uint32_t sz   = ((uint32_t)frm[0] << 8) | ((uint32_t)frm[1]);
165     uint32_t ser  = ((uint32_t)frm[2] << 8) | ((uint32_t)frm[3]);
166     uint16_t tp   = ((uint16_t)frm[16] << 8) | ((uint16_t)frm[17]);
167
168     if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
169         frame_ptr = frm + 4;
170         datasize = sz;
171         req->ios2_Req.io_Flags = SANA2IOF_RAW;
172     }
173     else {
174         frame_ptr = frm + 4 + ETH_HDR_SIZE;
175         datasize = sz - ETH_HDR_SIZE;
176         req->ios2_Req.io_Flags = 0;
177     }
178
179     req->ios2_DataLength = datasize;
180
181     //D(("datasize: %lx\n",datasize));
182     //D(("frame_ptr: %lx\n",frame_ptr));
183     //D(("ios2_Data: %lx\n",req->ios2_Data));
184     //D(("bufmgmt: %lx\n",req->ios2_BufferManagement));
185
186     // copy frame to device user (probably tcp/ip system)
187     bm = (struct BufferManagement *)req->ios2_BufferManagement;
188     if (!(*bm->bm_CopyToBuffer)(req->ios2_Data, frame_ptr, datasize)) {
189         //D(("rx copybuf error\n"));
190         req->ios2_Req.io_Error = S2ERR_SOFTWARE;
191         req->ios2_WireError = S2WERR_BUFF_ERROR;
192         err = 1;
193     }
194     else {
195         req->ios2_Req.io_Error = req->ios2_WireError = 0;
196         err = 0;
197     }
198
199     memcpy(req->ios2_SrcAddr, frame+4+6, HW_ADDRFIELDSIZE);
200     memcpy(req->ios2_DstAddr, frame+4, HW_ADDRFIELDSIZE);
201
202     //D(("RXSZ %ld\n",(LONG)sz));
203     //D(("RXPT %ld\n",(LONG)tp));
204
205     //D(("RXSER %ld\n",(LONG)ser));
206     //D(("RXDST %lx...\n",*((ULONG*)(req->ios2_DstAddr))));
207     //D(("RXSRC %lx\n",*((ULONG*)(req->ios2_SrcAddr))));
208     //D(("RXSRC %lx\n",*((ULONG*)(frame_ptr))));
209
210     broadcast = TRUE;
211     for (int i=0; i<HW_ADDRFIELDSIZE; i++) {
212         if (frame[i+4] != 0xff) {
213         broadcast = FALSE;
214         break;
215         }
216     }
217     if (broadcast) {
218         req->ios2_Req.io_Flags |= SANA2IOF_BCAST;
219     }
220
221     req->ios2_PacketType = tp;*/
222
223     return err;
224 }
225
226 void pinet_write_frame(struct IOSana2Req *ioreq) {
227
228 }
229
230 void exit(int status) { }
231
232 ADDTABL_1(__BeginIO,a1);
233 void __BeginIO(struct IORequest *io) {
234     struct IOSana2Req *ioreq = (struct IOSana2Req *)io;
235     ULONG unit = (ULONG)ioreq->ios2_Req.io_Unit;
236     int mtu;
237
238     ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
239     ioreq->ios2_Req.io_Error = S2ERR_NO_ERROR;
240     ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
241
242     //D(("BeginIO command %ld unit %ld\n",(LONG)ioreq->ios2_Req.io_Command,unit));
243
244     switch( ioreq->ios2_Req.io_Command ) {
245         case CMD_READ:
246             KPrintF("Read\n");
247             if (pinet_read_frame(ioreq) != 0) {
248                 ioreq->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
249                 ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
250             }
251             ioreq = NULL;
252             break;
253         case S2_BROADCAST:
254             KPrintF("Broadcast\n");
255             if (ioreq->ios2_DstAddr) {
256                 for (int i = 0; i < ADDRFIELDSIZE; i++) {
257                     ioreq->ios2_DstAddr[i] = 0xFF;
258                 }
259             } else {
260                 KPrintF("Invalid ios2_DstAddr\n");
261             }
262             /* Fallthrough */
263         case CMD_WRITE: {
264             KPrintF("Write\n");
265             pinet_write_frame(ioreq);
266             break;
267         }
268
269         case S2_READORPHAN:
270             ioreq->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
271             ioreq = NULL;
272             break;
273         case S2_ONLINE:
274         case S2_OFFLINE:
275         case S2_CONFIGINTERFACE:   /* forward request */
276             break;
277
278         case S2_GETSTATIONADDRESS:
279             for (int i = 0; i < ADDRFIELDSIZE; i++) {
280                 ioreq->ios2_SrcAddr[i] = dev_base->MAC[i];
281                 ioreq->ios2_DstAddr[i] = dev_base->MAC[i];
282             }
283             break;
284         case S2_DEVICEQUERY: {
285             struct Sana2DeviceQuery *devquery;
286
287             devquery = ioreq->ios2_StatData;
288             devquery->DevQueryFormat = 0;
289             devquery->DeviceLevel = 0;
290
291             if (devquery->SizeAvailable >= 18)
292                 devquery->AddrFieldSize = ADDRFIELDSIZE * 8;
293             if (devquery->SizeAvailable >= 22)
294                 devquery->MTU           = 1500;
295             if (devquery->SizeAvailable >= 26)
296                 devquery->BPS           =  1000 * 1000 * 100;
297             if (devquery->SizeAvailable >= 30)
298                 devquery->HardwareType  = S2WireType_Ethernet;
299
300             devquery->SizeSupplied = (devquery->SizeAvailable < 30) ? devquery->SizeAvailable : 30;
301             break;
302         }
303         case S2_GETSPECIALSTATS: {
304             struct Sana2SpecialStatHeader *s2ssh = (struct Sana2SpecialStatHeader *)ioreq->ios2_StatData;
305             s2ssh->RecordCountSupplied = 0;
306             break;
307         }
308         default: {
309             uint8_t cmd = ioreq->ios2_Req.io_Command;
310             KPrintF("Unknown/unhandled IO command %lx\n", cmd);
311             ioreq->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
312             ioreq->ios2_WireError = S2WERR_GENERIC_ERROR;
313             break;
314         }
315     }
316
317     if (ioreq) {
318         if (!(ioreq->ios2_Req.io_Flags & SANA2IOF_QUICK)) {
319             ReplyMsg((struct Message *)ioreq);
320         } else {
321             ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
322         }
323     }
324 }
325
326 ADDTABL_1(__AbortIO,a1);
327 void __AbortIO(struct IORequest* ioreq) {
328     struct IOSana2Req* ios2 = (struct IOSana2Req*)ioreq;
329
330     if (!ioreq) return;
331         ioreq->io_Error = IOERR_ABORTED;
332     ios2->ios2_WireError = 0;
333 }
334
335 ADDTABL_1(__TermIO,a1);
336 void __TermIO(struct IORequest *ioreq) {
337     struct IOSana2Req* ios2 = (struct IOSana2Req*)ioreq;
338
339     if (!(ios2->ios2_Req.io_Flags & SANA2IOF_QUICK)) {
340         ReplyMsg((struct Message *)ioreq);
341     } else {
342         ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;
343     }
344 }
345
346 /*ULONG get_frame_serial(UBYTE* frame) {
347   UBYTE* frm = (UBYTE*)frame;
348   ULONG ser  = ((ULONG)frm[2]<<8)|((ULONG)frm[3]);
349   return ser;
350 }
351
352 ULONG read_frame(struct IOSana2Req *req, volatile UBYTE *frame)
353 {
354   ULONG datasize;
355   BYTE *frame_ptr;
356   BOOL broadcast;
357   ULONG err = 0;
358   struct BufferManagement *bm;
359
360   UBYTE* frm = (UBYTE*)frame;
361   ULONG sz   = ((ULONG)frm[0]<<8)|((ULONG)frm[1]);
362   ULONG ser  = ((ULONG)frm[2]<<8)|((ULONG)frm[3]);
363   USHORT tp  = ((USHORT)frm[16]<<8)|((USHORT)frm[17]);
364
365   if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
366     frame_ptr = frm+4;
367     datasize = sz;
368     req->ios2_Req.io_Flags = SANA2IOF_RAW;
369   }
370   else {
371     frame_ptr = frm+4+HW_ETH_HDR_SIZE;
372     datasize = sz-HW_ETH_HDR_SIZE;
373     req->ios2_Req.io_Flags = 0;
374   }
375
376   req->ios2_DataLength = datasize;
377
378   //D(("datasize: %lx\n",datasize));
379   //D(("frame_ptr: %lx\n",frame_ptr));
380   //D(("ios2_Data: %lx\n",req->ios2_Data));
381   //D(("bufmgmt: %lx\n",req->ios2_BufferManagement));
382
383   // copy frame to device user (probably tcp/ip system)
384   bm = (struct BufferManagement *)req->ios2_BufferManagement;
385   if (!(*bm->bm_CopyToBuffer)(req->ios2_Data, frame_ptr, datasize)) {
386     //D(("rx copybuf error\n"));
387     req->ios2_Req.io_Error = S2ERR_SOFTWARE;
388     req->ios2_WireError = S2WERR_BUFF_ERROR;
389     err = 1;
390   }
391   else {
392     req->ios2_Req.io_Error = req->ios2_WireError = 0;
393     err = 0;
394   }
395
396   memcpy(req->ios2_SrcAddr, frame+4+6, HW_ADDRFIELDSIZE);
397   memcpy(req->ios2_DstAddr, frame+4, HW_ADDRFIELDSIZE);
398
399   //D(("RXSZ %ld\n",(LONG)sz));
400   //D(("RXPT %ld\n",(LONG)tp));
401
402   //D(("RXSER %ld\n",(LONG)ser));
403   //D(("RXDST %lx...\n",*((ULONG*)(req->ios2_DstAddr))));
404   //D(("RXSRC %lx\n",*((ULONG*)(req->ios2_SrcAddr))));
405   //D(("RXSRC %lx\n",*((ULONG*)(frame_ptr))));
406
407   broadcast = TRUE;
408   for (int i=0; i<HW_ADDRFIELDSIZE; i++) {
409     if (frame[i+4] != 0xff) {
410       broadcast = FALSE;
411       break;
412     }
413   }
414   if (broadcast) {
415     req->ios2_Req.io_Flags |= SANA2IOF_BCAST;
416   }
417
418   req->ios2_PacketType = tp;
419
420   return err;
421 }
422
423 ULONG write_frame(struct IOSana2Req *req, UBYTE *frame)
424 {
425    ULONG rc=0;
426    struct BufferManagement *bm;
427    USHORT sz=0;
428
429    if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
430       sz = req->ios2_DataLength;
431    } else {
432       sz = req->ios2_DataLength + HW_ETH_HDR_SIZE;
433       *((USHORT*)(frame+6+6)) = (USHORT)req->ios2_PacketType;
434       memcpy(frame, req->ios2_DstAddr, HW_ADDRFIELDSIZE);
435       memcpy(frame+6, HW_MAC, HW_ADDRFIELDSIZE);
436       frame+=HW_ETH_HDR_SIZE;
437    }
438
439    if (sz>0) {
440      bm = (struct BufferManagement *)req->ios2_BufferManagement;
441
442      if (!(*bm->bm_CopyFromBuffer)(frame, req->ios2_Data, req->ios2_DataLength)) {
443        rc = 1; // FIXME error code
444        //D(("tx copybuf err\n"));
445      }
446      else {
447        // buffer was copied to zz9000, send it
448        volatile USHORT* reg = (volatile USHORT*)(ZZ9K_REGS+0x80); // FIXME send_frame reg
449        *reg = sz;
450
451        // get feedback
452        rc = *reg;
453        if (rc!=0) {
454          D(("tx err: %d\n",rc));
455        }
456      }
457    }
458
459    return rc;
460 }*/
461
462 ADDTABL_END();