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