1 // SPDX-License-Identifier: MIT
3 #include <exec/resident.h>
4 #include <exec/memory.h>
5 #include <exec/alerts.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>
25 #include "../pi-net-enums.h"
27 #include <clib/debug_protos.h>
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;
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);
39 //typedef BOOL (*BMFunc)(void* a __asm("a0"), void* b __asm("a1"), long c __asm("d0"));
41 typedef struct BufferManagement
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"));
50 struct Device* pi_dev;
55 struct List read_list;
56 struct SignalSemaphore read_list_sem;
59 struct ExecBase* SysBase = NULL;
61 const char DevName[] = "pi-net.device";
62 const char DevIdString[] = "Pi-NET 0.1";
64 const UWORD DevVersion = 1;
65 const UWORD DevRevision = 0;
69 struct pinet_base *dev_base = NULL;
71 struct WBStartup *_WBenchMsg = NULL;
75 //#define KPrintF(...)
77 uint32_t __UserDevInit(struct Device* dev) {
82 SysBase = *(struct ExecBase **)4L;
84 KPrintF("Initializing net device.\n");
86 dev_base = AllocMem(sizeof(struct pinet_base), MEMF_PUBLIC | MEMF_CLEAR);
87 dev_base->pi_dev = dev;
89 KPrintF("Grabbing MAC.\n");
90 for (int i = 0; i < 6; i++) {
91 READBYTE((PINET_CMD_MAC + i), dev_base->MAC[i]);
93 KPrintF("Grabbing IP.\n");
94 for (int i = 0; i < 4; i++) {
95 READBYTE((PINET_CMD_IP + i), dev_base->IP[i]);
101 uint32_t __UserDevCleanup(void) {
102 KPrintF("Cleaning up.\n");
103 FreeMem(dev_base, sizeof(struct pinet_base));
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;
112 KPrintF("Opening net device %ld.\n", num);
113 dev_base->unit.unit_OpenCnt++;
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);
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;
129 KPrintF("New list.\n");
131 NewList(&dev_base->read_list);
132 InitSemaphore(&dev_base->read_list_sem);
139 if (ret == IOERR_OPENFAIL) {
140 KPrintF("Failed to open device. Already open?\n");
143 KPrintF("Device opened, yay.\n");
145 ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
147 KPrintF("Opened device, return code: %ld\n", ret);
152 uint32_t __UserDevClose(struct IORequest *io) {
156 uint32_t pinet_read_frame(struct IOSana2Req *ioreq) {
161 struct BufferManagement *bm;
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]);
168 if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
171 req->ios2_Req.io_Flags = SANA2IOF_RAW;
174 frame_ptr = frm + 4 + ETH_HDR_SIZE;
175 datasize = sz - ETH_HDR_SIZE;
176 req->ios2_Req.io_Flags = 0;
179 req->ios2_DataLength = datasize;
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));
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;
195 req->ios2_Req.io_Error = req->ios2_WireError = 0;
199 memcpy(req->ios2_SrcAddr, frame+4+6, HW_ADDRFIELDSIZE);
200 memcpy(req->ios2_DstAddr, frame+4, HW_ADDRFIELDSIZE);
202 //D(("RXSZ %ld\n",(LONG)sz));
203 //D(("RXPT %ld\n",(LONG)tp));
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))));
211 for (int i=0; i<HW_ADDRFIELDSIZE; i++) {
212 if (frame[i+4] != 0xff) {
218 req->ios2_Req.io_Flags |= SANA2IOF_BCAST;
221 req->ios2_PacketType = tp;*/
226 void pinet_write_frame(struct IOSana2Req *ioreq) {
230 void exit(int status) { }
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;
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;
242 //D(("BeginIO command %ld unit %ld\n",(LONG)ioreq->ios2_Req.io_Command,unit));
244 switch( ioreq->ios2_Req.io_Command ) {
247 if (pinet_read_frame(ioreq) != 0) {
248 ioreq->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
249 ioreq->ios2_WireError = S2WERR_BUFF_ERROR;
254 KPrintF("Broadcast\n");
255 if (ioreq->ios2_DstAddr) {
256 for (int i = 0; i < ADDRFIELDSIZE; i++) {
257 ioreq->ios2_DstAddr[i] = 0xFF;
260 KPrintF("Invalid ios2_DstAddr\n");
265 pinet_write_frame(ioreq);
270 ioreq->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
275 case S2_CONFIGINTERFACE: /* forward request */
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];
284 case S2_DEVICEQUERY: {
285 struct Sana2DeviceQuery *devquery;
287 devquery = ioreq->ios2_StatData;
288 devquery->DevQueryFormat = 0;
289 devquery->DeviceLevel = 0;
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;
300 devquery->SizeSupplied = (devquery->SizeAvailable < 30) ? devquery->SizeAvailable : 30;
303 case S2_GETSPECIALSTATS: {
304 struct Sana2SpecialStatHeader *s2ssh = (struct Sana2SpecialStatHeader *)ioreq->ios2_StatData;
305 s2ssh->RecordCountSupplied = 0;
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;
318 if (!(ioreq->ios2_Req.io_Flags & SANA2IOF_QUICK)) {
319 ReplyMsg((struct Message *)ioreq);
321 ioreq->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
326 ADDTABL_1(__AbortIO,a1);
327 void __AbortIO(struct IORequest* ioreq) {
328 struct IOSana2Req* ios2 = (struct IOSana2Req*)ioreq;
331 ioreq->io_Error = IOERR_ABORTED;
332 ios2->ios2_WireError = 0;
335 ADDTABL_1(__TermIO,a1);
336 void __TermIO(struct IORequest *ioreq) {
337 struct IOSana2Req* ios2 = (struct IOSana2Req*)ioreq;
339 if (!(ios2->ios2_Req.io_Flags & SANA2IOF_QUICK)) {
340 ReplyMsg((struct Message *)ioreq);
342 ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;
346 /*ULONG get_frame_serial(UBYTE* frame) {
347 UBYTE* frm = (UBYTE*)frame;
348 ULONG ser = ((ULONG)frm[2]<<8)|((ULONG)frm[3]);
352 ULONG read_frame(struct IOSana2Req *req, volatile UBYTE *frame)
358 struct BufferManagement *bm;
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]);
365 if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
368 req->ios2_Req.io_Flags = SANA2IOF_RAW;
371 frame_ptr = frm+4+HW_ETH_HDR_SIZE;
372 datasize = sz-HW_ETH_HDR_SIZE;
373 req->ios2_Req.io_Flags = 0;
376 req->ios2_DataLength = datasize;
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));
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;
392 req->ios2_Req.io_Error = req->ios2_WireError = 0;
396 memcpy(req->ios2_SrcAddr, frame+4+6, HW_ADDRFIELDSIZE);
397 memcpy(req->ios2_DstAddr, frame+4, HW_ADDRFIELDSIZE);
399 //D(("RXSZ %ld\n",(LONG)sz));
400 //D(("RXPT %ld\n",(LONG)tp));
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))));
408 for (int i=0; i<HW_ADDRFIELDSIZE; i++) {
409 if (frame[i+4] != 0xff) {
415 req->ios2_Req.io_Flags |= SANA2IOF_BCAST;
418 req->ios2_PacketType = tp;
423 ULONG write_frame(struct IOSana2Req *req, UBYTE *frame)
426 struct BufferManagement *bm;
429 if (req->ios2_Req.io_Flags & SANA2IOF_RAW) {
430 sz = req->ios2_DataLength;
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;
440 bm = (struct BufferManagement *)req->ios2_BufferManagement;
442 if (!(*bm->bm_CopyFromBuffer)(frame, req->ios2_Data, req->ios2_DataLength)) {
443 rc = 1; // FIXME error code
444 //D(("tx copybuf err\n"));
447 // buffer was copied to zz9000, send it
448 volatile USHORT* reg = (volatile USHORT*)(ZZ9K_REGS+0x80); // FIXME send_frame reg
454 D(("tx err: %d\n",rc));