static int32_t release_async_request (struct devstruct *dev, uaecptr request) { struct asyncreq *ar, *prevar; uae_sem_wait (&async_sem); ar = dev->ar; prevar = NULL; while (ar) { if (ar->request == request) { if (prevar == NULL) dev->ar = ar->next; else prevar->next = ar->next; uae_sem_post (&async_sem); xfree (ar); if (log_uaeserial) write_log (_T("%s:%d async request %x removed\n"), getdevname(), dev->unit, request); return 1; } prevar = ar; ar = ar->next; } uae_sem_post (&async_sem); write_log (_T("%s:%d async request %x not found for removal!\n"), getdevname(), dev->unit, request); return 0; }
static uae_u32 REGPARAM2 dev_beginio (TrapContext *context) { uae_u32 request = m68k_areg (regs, 1); uae_u8 flags = get_byte (request + 30); int command = get_word (request + 28); struct priv_s2devstruct *pdev = getps2devstruct (request); struct s2devstruct *dev; put_byte (request + 8, NT_MESSAGE); if (!pdev) { write_log (_T("%s unknown iorequest (1) %08x\n"), getdevname (), request); put_byte (request + 31, 32); return get_byte (request + 31); } dev = gets2devstruct (pdev->unit); if (!dev) { write_log (_T("%s unknown iorequest (2) %08x\n"), getdevname (), request); put_byte (request + 31, 32); return get_byte (request + 31); } put_byte (request + 31, 0); if ((flags & 1) && dev_canquick (dev, request)) { if (dev_do_io (dev, request, 1)) write_log (_T("%s: command %d bug with IO_QUICK\n"), SANA2NAME, command); return get_byte (request + 31); } else { if (command == CMD_WRITE || command == S2_BROADCAST || command == S2_MULTICAST) { struct s2packet *s2p; if (!pdev->copyfrombuff || !pdev->copytobuff) { put_long (request + 32, S2ERR_BAD_ARGUMENT); put_byte (request + 31, S2WERR_BUFF_ERROR); } else { if (command == S2_BROADCAST) { uaecptr dstaddr = request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES; put_byte (dstaddr + 0, 0xff); put_byte (dstaddr + 1, 0xff); put_byte (dstaddr + 2, 0xff); put_byte (dstaddr + 3, 0xff); put_byte (dstaddr + 4, 0xff); put_byte (dstaddr + 5, 0xff); } s2p = createwritepacket (context, request); if (s2p) { uae_sem_wait (&async_sem); add_async_packet (dev, s2p, request); uae_sem_post (&async_sem); } if (!s2p) { put_long (request + 32, S2WERR_BUFF_ERROR); put_byte (request + 31, S2ERR_NO_RESOURCES); } } } put_byte (request + 30, get_byte (request + 30) & ~1); write_comm_pipe_u32 (&dev->requests, request, 1); return 0; } }
static void abort_async (struct s2devstruct *dev, uaecptr request) { struct asyncreq *ar = get_async_request (dev, request, 1); if (!ar) { write_log (_T("%s:%d: abort async but no request %x found!\n"), getdevname(), dev->unit, request); return; } if (log_net) write_log (_T("%s:%d asyncronous request=%08X aborted\n"), getdevname(), dev->unit, request); do_abort_async (dev, request); }
static void abort_async (struct devstruct *dev, uaecptr request) { struct asyncreq *ar = get_async_request (dev, request, 1); if (!ar) { write_log (_T("%s:%d: abort async but no request %x found!\n"), getdevname(), dev->unit, request); return; } if (log_uaeserial) write_log (_T("%s:%d asyncronous request=%08X aborted\n"), getdevname(), dev->unit, request); put_byte (request + 31, IOERR_ABORTED); put_byte (request + 30, get_byte (request + 30) | 0x20); write_comm_pipe_u32 (&dev->requests, request, 1); }
static uint32_t REGPARAM2 dev_init (TrapContext *context) { uint32_t base = m68k_dreg (regs, 0); if (log_uaeserial) write_log (_T("%s init\n"), getdevname ()); return base; }
static void dev_reset (void) { int i; struct s2devstruct *dev; int unitnum = 0; write_log (_T("%s reset\n"), getdevname()); for (i = 0; i < MAX_TOTAL_NET_DEVICES; i++) { dev = &devst[i]; if (dev->opencnt) { struct asyncreq *ar = dev->ar; while (ar) { if (!ar->ready) { dev->ar->ready = 1; do_abort_async (dev, ar->request); } ar = ar->next; } write_comm_pipe_u32 (&dev->requests, 0, 1); uae_sem_wait (&dev->sync_sem); } while (dev->mc) delmulticastaddresses (dev, dev->mc->start, dev->mc->end); memset (dev, 0, sizeof (struct s2devstruct)); } for (i = 0; i < MAX_OPEN_DEVICES; i++) memset (&pdevst[i], 0, sizeof (struct priv_s2devstruct)); uaenet_vsync_requested = 0; uaenet_int_requested = 0; irq_init = 0; }
static void *dev_thread (void *devs) { struct s2devstruct *dev = (struct s2devstruct*)devs; uae_set_thread_priority (NULL, 1); dev->thread_running = 1; uae_sem_post (&dev->sync_sem); for (;;) { uaecptr request = (uaecptr)read_comm_pipe_u32_blocking (&dev->requests); uae_sem_wait (&change_sem); if (!request) { dev->thread_running = 0; uae_sem_post (&dev->sync_sem); uae_sem_post (&change_sem); write_log (_T("%s: dev_thread killed\n"), getdevname ()); return 0; } else if (get_async_request (dev, request, 1)) { uae_ReplyMsg (request); release_async_request (dev, request); rem_async_packet (dev, request); } else if (dev_do_io (dev, request, 0) == 0) { uae_ReplyMsg (request); rem_async_packet (dev, request); } else { add_async_request (dev, request); ethernet_trigger (dev->sysdata); } uae_sem_post (&change_sem); } return 0; }
static int dev_do_io (struct s2devstruct *dev, uaecptr request, int quick) { uae_u32 command = get_word (request + 28); struct priv_s2devstruct *pdev = getps2devstruct (request); uaecptr data = get_long (request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4); put_byte (request + 31, 0); if (!pdev) { write_log (_T("%s unknown iorequest %08x\n"), getdevname (), request); return 0; } if (command == NSCMD_DEVICEQUERY) { uae_u32 data = get_long (request + 40); /* io_data */ put_long (data + 0, 0); put_long (data + 4, 16); /* size */ put_word (data + 8, 7); /* NSDEVTYPE_SANA2 */ put_word (data + 10, 0); put_long (data + 12, nscmd_cmd); put_long (request + 32, 16); /* io_actual */ return 0; } else if (get_word (request + 0x12) < SANA2_IOREQSIZE) { put_byte (request + 31, IOERR_BADLENGTH); return 0; } return dev_do_io_2 (dev, request, quick); }
static uae_u32 REGPARAM2 dev_init_2 (TrapContext *context, int type) { uae_u32 base = m68k_dreg (&context->regs,0); if (log_scsi) write_log ("%s init\n", getdevname (type)); return base; }
static uae_u32 REGPARAM2 dev_beginio (TrapContext *context) { uae_u32 request = m68k_areg (&context->regs, 1); uae_u8 flags = get_byte (request + 30); int command = get_word (request + 28); struct priv_devstruct *pdev = getpdevstruct (request); struct devstruct *dev = getdevstruct (pdev->unit); put_byte (request+8, NT_MESSAGE); if (!dev || !pdev) { put_byte (request + 31, 32); return get_byte (request + 31); } put_byte (request+31, 0); if ((flags & 1) && dev_canquick (dev, request)) { if (dev_do_io (dev, request)) write_log ("device %s command %d bug with IO_QUICK\n", getdevname (pdev->type), command); return get_byte (request + 31); } else { add_async_request (dev, request, ASYNC_REQUEST_TEMP, 0); put_byte (request+30, get_byte (request + 30) & ~1); write_comm_pipe_u32 (&dev->requests, request, 1); return 0; } }
static void signalasync (struct s2devstruct *dev, struct asyncreq *ar, int actual, int err) { uaecptr request = ar->request; int command = get_word (request + 28); if (log_net) write_log (_T("%s:%d CMD=%d async request %x completed\n"), getdevname(), dev->unit, command, request); put_long (request + 32, actual); put_byte (request + 31, err); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); }
static uae_u32 REGPARAM2 dev_abortio (TrapContext *context) { uae_u32 request = m68k_areg (regs, 1); struct priv_s2devstruct *pdev = getps2devstruct (request); struct s2devstruct *dev; if (!pdev) { write_log (_T("%s abortio but no request %08x found!\n"), getdevname(), request); put_byte (request + 31, 32); return get_byte (request + 31); } dev = gets2devstruct (pdev->unit); if (!dev) { write_log (_T("%s (%d) abortio but no request %08x found!\n"), getdevname(), pdev->unit, request); put_byte (request + 31, 32); return get_byte (request + 31); } if (log_net) write_log (_T("%s:%d abortio %08x\n"), getdevname(), dev->unit, request); abort_async (dev, request); return 0; }
static uae_u32 REGPARAM2 dev_open_2 (TrapContext *context, int type) { uaecptr ioreq = m68k_areg (&context->regs, 1); uae_u32 unit = m68k_dreg (&context->regs, 0); uae_u32 flags = m68k_dreg (&context->regs, 1); struct devstruct *dev = getdevstruct (unit); struct priv_devstruct *pdev = 0; int i; if (log_scsi) write_log ("opening %s:%d ioreq=%08.8X\n", getdevname (type), unit, ioreq); if (!dev) return openfail (ioreq, 32); /* badunitnum */ if (!dev->opencnt) { for (i = 0; i < MAX_OPEN_DEVICES; i++) { pdev = &pdevst[i]; if (pdev->inuse == 0) break; } if (type == UAEDEV_SCSI_ID && sys_command_open (DF_SCSI, dev->unitnum)) { pdev->scsi = 1; pdev->mode = DF_SCSI; } if (type == UAEDEV_DISK_ID && sys_command_open (DF_IOCTL, dev->unitnum)) { pdev->ioctl = 1; pdev->mode = DF_IOCTL; } if (!pdev->scsi && !pdev->ioctl) return openfail (ioreq, -1); pdev->type = type; pdev->unit = unit; pdev->flags = flags; pdev->inuse = 1; put_long (ioreq + 24, pdev - pdevst); start_thread (dev); } else { for (i = 0; i < MAX_OPEN_DEVICES; i++) { pdev = &pdevst[i]; if (pdev->inuse && pdev->unit == (int)unit) break; } if (i == MAX_OPEN_DEVICES) return openfail (ioreq, -1); put_long (ioreq + 24, pdev - pdevst); } dev->opencnt++; put_word (m68k_areg (&context->regs, 6) + 32, get_word (m68k_areg (&context->regs, 6) + 32) + 1); put_byte (ioreq + 31, 0); put_byte (ioreq + 8, 7); return 0; }
static uint32_t REGPARAM2 dev_close (TrapContext *context) { uint32_t request = m68k_areg (regs, 1); struct devstruct *dev; dev = getdevstruct (get_long (request + 24)); if (!dev) return 0; if (log_uaeserial) write_log (_T("%s:%d close, req=%x\n"), getdevname(), dev->unit, request); dev_close_3 (dev); put_long (request + 24, 0); put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) - 1); return 0; }
static uint32_t REGPARAM2 dev_open (TrapContext *context) { uaecptr ioreq = m68k_areg (regs, 1); uint32_t unit = m68k_dreg (regs, 0); uint32_t flags = m68k_dreg (regs, 1); struct devstruct *dev; int32_t i, err; if (get_word (ioreq + 0x12) < IOSTDREQ_SIZE) return openfail (ioreq, IOERR_BADLENGTH); for (i = 0; i < MAX_TOTAL_DEVICES; i++) { if (devst[i].open && devst[i].unit == (int32_t)unit && devst[i].exclusive) return openfail (ioreq, IOERR_UNITBUSY); } for (i = 0; i < MAX_TOTAL_DEVICES; i++) { if (!devst[i].open) break; } if (i == MAX_TOTAL_DEVICES) return openfail (ioreq, IOERR_OPENFAIL); dev = &devst[i]; dev->sysdata = xcalloc (uint8_t, uaeser_getdatalength ()); if (!uaeser_open (dev->sysdata, dev, unit)) { xfree (dev->sysdata); return openfail (ioreq, IOERR_OPENFAIL); } dev->unit = unit; dev->open = 1; dev->uniq = ++uniq; dev->exclusive = (get_word (ioreq + io_SerFlags) & SERF_SHARED) ? 0 : 1; put_long (ioreq + 24, dev->uniq); resetparams (dev, ioreq); err = setparams (dev, ioreq); if (err) { uaeser_close (dev->sysdata); dev->open = 0; xfree (dev->sysdata); return openfail (ioreq, err); } if (log_uaeserial) write_log (_T("%s:%d open ioreq=%08X\n"), getdevname(), unit, ioreq); start_thread (dev); put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) + 1); put_byte (ioreq + 31, 0); put_byte (ioreq + 8, 7); return 0; }
static uae_u32 REGPARAM2 dev_close_2 (TrapContext *context) { uae_u32 request = m68k_areg (&context->regs, 1); struct priv_devstruct *pdev = getpdevstruct (request); struct devstruct *dev; if (!pdev) return 0; dev = getdevstruct (pdev->unit); if (log_scsi) write_log ("%s:%d close, req=%08.8X\n", getdevname (pdev->type), pdev->unit, request); if (!dev) return 0; dev_close_3 (dev, pdev); put_long (request + 24, 0); put_word (m68k_areg (&context->regs, 6) + 32, get_word (m68k_areg (&context->regs, 6) + 32) - 1); return 0; }
static int32_t setparams (struct devstruct *dev, uaecptr req) { int32_t v; int32_t rbuffer, baud, rbits, wbits, sbits, rtscts, parity, xonxoff; rbuffer = get_long (req + io_RBufLen); v = get_long (req + io_ExtFlags); if (v) { write_log (_T("UAESER: io_ExtFlags=%08x, not supported\n"), v); return 5; } baud = get_long (req + io_Baud); v = get_byte (req + io_SerFlags); if (v & SERF_EOFMODE) { write_log (_T("UAESER: SERF_EOFMODE not supported\n")); return 5; } xonxoff = (v & SERF_XDISABLED) ? 0 : 1; if (xonxoff) { xonxoff |= (get_long (req + io_CtlChar) << 8) & 0x00ffff00; } rtscts = (v & SERF_7WIRE) ? 1 : 0; parity = 0; if (v & SERF_PARTY_ON) parity = (v & SERF_PARTY_ODD) ? 1 : 2; rbits = get_byte (req + io_ReadLen); wbits = get_byte (req + io_WriteLen); sbits = get_byte (req + io_StopBits); if ((rbits != 7 && rbits != 8) || (wbits != 7 && wbits != 8) || (sbits != 1 && sbits != 2) || rbits != wbits) { write_log (_T("UAESER: Read=%d, Write=%d, Stop=%d, not supported\n"), rbits, wbits, sbits); return 5; } write_log (_T("%s:%d BAUD=%d BUF=%d BITS=%d+%d RTSCTS=%d PAR=%d XO=%06X\n"), getdevname(), dev->unit, baud, rbuffer, rbits, sbits, rtscts, parity, xonxoff); v = uaeser_setparams (dev->sysdata, baud, rbuffer, rbits, sbits, rtscts, parity, xonxoff); if (v) { write_log (_T("->failed\n")); return v; } return 0; }
static int32_t add_async_request (struct devstruct *dev, uaecptr request) { struct asyncreq *ar, *ar2; if (log_uaeserial) write_log (_T("%s:%d async request %x added\n"), getdevname(), dev->unit, request); uae_sem_wait (&async_sem); ar = xcalloc (struct asyncreq, 1); ar->request = request; if (!dev->ar) { dev->ar = ar; } else { ar2 = dev->ar; while (ar2->next) ar2 = ar2->next; ar2->next = ar; } uae_sem_post (&async_sem); return 1; }
static uae_u32 REGPARAM2 dev_abortio (TrapContext *context) { uae_u32 request = m68k_areg (&context->regs, 1); struct priv_devstruct *pdev = getpdevstruct (request); struct devstruct *dev; if (!pdev) { put_byte (request + 31, 32); return get_byte (request + 31); } dev = getdevstruct (pdev->unit); if (!dev) { put_byte (request + 31, 32); return get_byte (request + 31); } put_byte (request + 31, -2); if (log_scsi) write_log ("abortio %s unit=%d, request=%08.8X\n", getdevname (pdev->type), pdev->unit, request); abort_async (dev, request, -2, 0); return 0; }
static uint32_t REGPARAM2 dev_beginio (TrapContext *context) { uint32_t request = m68k_areg (regs, 1); uint8_t flags = get_byte (request + 30); int32_t command = get_word (request + 28); struct devstruct *dev = getdevstruct (get_long (request + 24)); put_byte (request + 8, NT_MESSAGE); if (!dev) { put_byte (request + 31, 32); return get_byte (request + 31); } put_byte (request + 31, 0); if ((flags & 1) && dev_canquick (dev, request)) { if (dev_do_io (dev, request, 1)) write_log (_T("device %s:%d command %d bug with IO_QUICK\n"), getdevname(), dev->unit, command); return get_byte (request + 31); } else { put_byte (request + 30, get_byte (request + 30) & ~1); write_comm_pipe_u32 (&dev->requests, request, 1); return 0; } }
void uaeser_signal (void *vdev, int32_t sigmask) { struct devstruct *dev = (struct devstruct*)vdev; struct asyncreq *ar; int32_t i = 0; uae_sem_wait (&async_sem); ar = dev->ar; while (ar) { if (!ar->ready) { uaecptr request = ar->request; uint32_t io_data = get_long (request + 40); // 0x28 uint32_t io_length = get_long (request + 36); // 0x24 int32_t command = get_word (request + 28); uint32_t io_error = 0, io_actual = 0; uint8_t *addr; int32_t io_done = 0; switch (command) { case SDCMD_BREAK: if (ar == dev->ar) { uaeser_break (dev->sysdata, get_long (request + io_BrkTime)); io_done = 1; } break; case CMD_READ: if (sigmask & 1) { addr = memmap(io_data, io_length); if (addr) { if (uaeser_read (dev->sysdata, addr, io_length)) { io_error = 0; io_actual = io_length; io_done = 1; } } else { io_error = IOERR_BADADDRESS; io_done = 1; } } break; case CMD_WRITE: if (sigmask & 2) { io_error = IOERR_BADADDRESS; addr = memmap(io_data, io_length); if (addr && uaeser_write (dev->sysdata, addr, io_length)) io_error = 0; io_actual = io_length; io_done = 1; } break; default: write_log (_T("%s:%d incorrect async request %x (cmd=%d) signaled?!"), getdevname(), dev->unit, request, command); break; } if (io_done) { if (log_uaeserial) write_log (_T("%s:%d async request %x completed\n"), getdevname(), dev->unit, request); put_long (request + 32, io_actual); put_byte (request + 31, io_error); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); } } ar = ar->next; } uae_sem_post (&async_sem); }
void netdev_install (void) { uae_u32 functable, datatable; uae_u32 initcode, openfunc, closefunc, expungefunc; uae_u32 beginiofunc, abortiofunc; if (!currprefs.sana2) return; if (log_net) write_log (_T("netdev_install(): 0x%x\n"), here ()); ethernet_enumerate_free (); ethernet_enumerate (td, NULL); ROM_netdev_resname = ds (getdevname()); ROM_netdev_resid = ds (_T("UAE net.device 0.2")); timerdevname = ds (_T("timer.device")); /* initcode */ initcode = here (); calltrap (deftrap2 (dev_init, TRAPFLAG_EXTRA_STACK, _T("uaenet.init"))); dw (RTS); /* Open */ openfunc = here (); calltrap (deftrap2 (dev_open, TRAPFLAG_EXTRA_STACK, _T("uaenet.open"))); dw (RTS); /* Close */ closefunc = here (); calltrap (deftrap2 (dev_close, TRAPFLAG_EXTRA_STACK, _T("uaenet.close"))); dw (RTS); /* Expunge */ expungefunc = here (); calltrap (deftrap2 (dev_expunge, TRAPFLAG_EXTRA_STACK, _T("uaenet.expunge"))); dw (RTS); /* BeginIO */ beginiofunc = here (); calltrap (deftrap2 (dev_beginio, TRAPFLAG_EXTRA_STACK, _T("uaenet.beginio"))); dw (RTS); /* AbortIO */ abortiofunc = here (); calltrap (deftrap2 (dev_abortio, TRAPFLAG_EXTRA_STACK, _T("uaenet.abortio"))); dw (RTS); /* FuncTable */ functable = here (); dl (openfunc); /* Open */ dl (closefunc); /* Close */ dl (expungefunc); /* Expunge */ dl (EXPANSION_nullfunc); /* Null */ dl (beginiofunc); /* BeginIO */ dl (abortiofunc); /* AbortIO */ dl (0xFFFFFFFFul); /* end of table */ /* DataTable */ datatable = here (); dw (0xE000); /* INITBYTE */ dw (0x0008); /* LN_TYPE */ dw (0x0300); /* NT_DEVICE */ dw (0xC000); /* INITLONG */ dw (0x000A); /* LN_NAME */ dl (ROM_netdev_resname); dw (0xE000); /* INITBYTE */ dw (0x000E); /* LIB_FLAGS */ dw (0x0600); /* LIBF_SUMUSED | LIBF_CHANGED */ dw (0xD000); /* INITWORD */ dw (0x0014); /* LIB_VERSION */ dw (0x0004); /* 0.4 */ dw (0xD000); /* INITWORD */ dw (0x0016); /* LIB_REVISION */ dw (0x0000); /* end of table already ??? */ dw (0xC000); /* INITLONG */ dw (0x0018); /* LIB_IDSTRING */ dl (ROM_netdev_resid); dw (0x0000); /* end of table */ ROM_netdev_init = here (); dl (0x00000100); /* size of device base */ dl (functable); dl (datatable); dl (initcode); nscmd_cmd = here (); dw (CMD_READ); dw (CMD_WRITE); dw (CMD_FLUSH); dw (S2_DEVICEQUERY); dw (S2_GETSTATIONADDRESS); dw (S2_CONFIGINTERFACE); dw (S2_ADDMULTICASTADDRESS); dw (S2_DELMULTICASTADDRESS); dw (S2_MULTICAST); dw (S2_BROADCAST); dw (S2_TRACKTYPE); dw (S2_UNTRACKTYPE); dw (S2_GETTYPESTATS); dw (S2_GETSPECIALSTATS); dw (S2_GETGLOBALSTATS); dw (S2_ONEVENT); dw (S2_READORPHAN); dw (S2_ONLINE); dw (S2_OFFLINE); dw (S2_ADDMULTICASTADDRESSES); dw (S2_DELMULTICASTADDRESSES); dw (NSCMD_DEVICEQUERY); dw (0); }
static uae_u32 REGPARAM2 uaenet_int_handler (TrapContext *ctx) { int i, j; int gotit; struct asyncreq *ar; if (uae_sem_trywait (&async_sem)) { uaenet_int_requested = 0; uaenet_int_late = 1; return 0; } for (i = 0; i < MAX_OPEN_DEVICES; i++) pdevst[i].tmp = 0; for (i = 0; i < MAX_TOTAL_NET_DEVICES; i++) { struct s2devstruct *dev = &devst[i]; struct s2packet *p; if (dev->online) { while (dev->readqueue) { uae_u16 type; p = dev->readqueue; type = (p->data[2 * ADDR_SIZE] << 8) | p->data[2 * ADDR_SIZE + 1]; ar = dev->ar; gotit = 0; while (ar) { if (!ar->ready) { uaecptr request = ar->request; int command = get_word (request + 28); uae_u32 packettype = get_long (request + 32 + 4); if (command == CMD_READ && (packettype == type || (packettype <= 1500 && type <= 1500))) { struct priv_s2devstruct *pdev = getps2devstruct (request); if (pdev && pdev->tmp == 0) { if (handleread (ctx, pdev, request, p->data, p->len, command)) { if (log_net) write_log (_T("-> %p Accepted, CMD_READ, REQ=%08X LEN=%d\n"), p, request, p->len); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); dev->packetsreceived++; gotit = 1; pdev->tmp = 1; } else { if (log_net) write_log (_T("-> %p PacketFilter() rejected, CMD_READ, REQ=%08X LEN=%d\n"), p, request, p->len); pdev->tmp = -1; } } } } ar = ar->next; } ar = dev->ar; while (ar) { if (!ar->ready) { uaecptr request = ar->request; int command = get_word (request + 28); if (command == S2_READORPHAN) { struct priv_s2devstruct *pdev = getps2devstruct (request); if (pdev && pdev->tmp <= 0) { if (log_net) write_log (_T("-> %p Accepted, S2_READORPHAN, REQ=%08X LEN=%d\n"), p, request, p->len); handleread (ctx, pdev, request, p->data, p->len, command); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); dev->packetsreceived++; dev->unknowntypesreceived++; gotit = 1; pdev->tmp = 1; } } } ar = ar->next; } if (!gotit) { if (log_net) write_log (_T("-> %p packet dropped, LEN=%d\n"), p, p->len); for (j = 0; j < MAX_OPEN_DEVICES; j++) { if (pdevst[j].unit == dev->unit) { if (pdevst[j].tracks[type]) pdevst[j].packetsdropped++; } } } dev->readqueue = dev->readqueue->next; freepacket (p); } } else { while (dev->readqueue) { p = dev->readqueue; dev->readqueue = dev->readqueue->next; freepacket (p); } } ar = dev->ar; while (ar) { if (!ar->ready) { uaecptr request = ar->request; int command = get_word (request + 28); if (command == S2_ONLINE) { struct priv_s2devstruct *pdev = getps2devstruct (request); dev->packetsreceived = 0; dev->packetssent = 0; dev->baddata = 0; dev->overruns = 0; dev->unknowntypesreceived = 0; dev->reconfigurations = 0; if (pdev && pdev->timerbase) { m68k_areg (regs, 0) = pdev->tempbuf; CallLib (ctx, pdev->timerbase, -0x42); /* GetSysTime() */ } else { put_long (pdev->tempbuf + 0, 0); put_long (pdev->tempbuf + 4, 0); } dev->online_secs = get_long (pdev->tempbuf + 0); dev->online_micro = get_long (pdev->tempbuf + 4); checkevents (dev, S2EVENT_ONLINE, 0); dev->online = 1; ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); uaenet_vsync_requested--; } else if (command == CMD_FLUSH) { /* do not reply CMD_FLUSH until all other requests are gone */ if (dev->ar->next == NULL) { if (log_net) write_log (_T("CMD_FLUSH replied %08x\n"), request); ar->ready = 1; write_comm_pipe_u32 (&dev->requests, request, 1); uaenet_vsync_requested--; } else { struct priv_s2devstruct *pdev = getps2devstruct (request); if (pdev) { dev->flush_timeout--; if (dev->flush_timeout <= 0) { dev->flush_timeout = FLUSH_TIMEOUT; if (dev->flush_timeout_cnt > 1) write_log (_T("WARNING: %s:%d CMD_FLUSH possibly frozen..\n"), getdevname(), pdev->unit); dev->flush_timeout_cnt++; flush (pdev); } } } } } ar = ar->next; } } if (uaenet_int_late) uaenet_int_requested = 1; else uaenet_int_requested = 0; uaenet_int_late = 0; uae_sem_post (&async_sem); return 0; }
int main(int argc, char *argv[]) { const char *fwname, *udevname; char msgdev[256], datadev[256]; struct uath_fwmsg txmsg, rxmsg; char *txdata; struct stat sb; int msg, data, fw, timeout, b, c; int bufsize = 512, verbose = 0; ssize_t len; udevname = NULL; while ((c = getopt(argc, argv, "d:v")) != -1) { switch (c) { case 'd': udevname = optarg; break; case 'v': verbose = 1; break; default: usage(); /*NOTREACHED*/ } } argc -= optind; argv += optind; if (udevname == NULL) errx(-1, "No device name; use -d to specify the ugen device"); if (argc > 1) usage(); if (argc == 1) fwname = argv[0]; else fwname = _PATH_FIRMWARE "/ar5523.bin"; fw = open(fwname, O_RDONLY, 0); if (fw < 0) err(-1, "open(%s)", fwname); if (fstat(fw, &sb) < 0) err(-1, "fstat(%s)", fwname); txdata = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fw, 0); if (txdata == MAP_FAILED) err(-1, "mmap(%s)", fwname); len = sb.st_size; /* XXX verify device is an AR5005 part */ if (getdevname(udevname, msgdev, datadev)) err(-1, "getdevname error"); msg = open(msgdev, O_RDWR, 0); if (msg < 0) err(-1, "open(%s)", msgdev); timeout = UATH_DATA_TIMEOUT; if (ioctl(msg, USB_SET_RX_TIMEOUT, &timeout) < 0) err(-1, "%s: USB_SET_RX_TIMEOUT(%u)", msgdev, UATH_DATA_TIMEOUT); if (ioctl(msg, USB_SET_RX_BUFFER_SIZE, &bufsize) < 0) err(-1, "%s: USB_SET_RX_BUFFER_SIZE(%u)", msgdev, bufsize); data = open(datadev, O_WRONLY, 0); if (data < 0) err(-1, "open(%s)", datadev); timeout = UATH_DATA_TIMEOUT; if (ioctl(data, USB_SET_TX_TIMEOUT, &timeout) < 0) err(-1, "%s: USB_SET_TX_TIMEOUT(%u)", datadev, UATH_DATA_TIMEOUT); VERBOSE("Load firmware %s to %s\n", fwname, udevname); bzero(&txmsg, sizeof (struct uath_fwmsg)); txmsg.flags = htobe32(UATH_WRITE_BLOCK); txmsg.total = htobe32(len); b = 0; while (len > 0) { int mlen; mlen = len; if (mlen > UATH_MAX_FWBLOCK_SIZE) mlen = UATH_MAX_FWBLOCK_SIZE; txmsg.remain = htobe32(len - mlen); txmsg.len = htobe32(mlen); /* send firmware block meta-data */ VERBOSE("send block %2u: %zd bytes remaining", b, len - mlen); if (write(msg, &txmsg, sizeof(txmsg)) != sizeof(txmsg)) { VERBOSE("%s", "\n"); err(-1, "error sending msg (%s)", msgdev); break; } /* send firmware block data */ VERBOSE("%s", "\n : data..."); if (write(data, txdata, mlen) != mlen) { VERBOSE("%s", "\n"); err(-1, "error sending data (%s)", datadev); break; } /* wait for ack from firmware */ VERBOSE("%s", "\n : wait for ack..."); bzero(&rxmsg, sizeof(rxmsg)); if (read(msg, &rxmsg, sizeof(rxmsg)) != sizeof(rxmsg)) { VERBOSE("%s", "\n"); err(-1, "error reading msg (%s)", msgdev); break; } VERBOSE("flags=0x%x total=%d\n", be32toh(rxmsg.flags), be32toh(rxmsg.rxtotal)); len -= mlen; txdata += mlen; b++; } sleep(1); close(fw); close(msg); close(data); return 0; }
static uae_u32 REGPARAM2 dev_open_2 (TrapContext *context) { uaecptr ioreq = m68k_areg (regs, 1); uae_u32 unit = m68k_dreg (regs, 0); uae_u32 flags = m68k_dreg (regs, 1); uaecptr buffermgmt; struct s2devstruct *dev = gets2devstruct (unit); struct priv_s2devstruct *pdev = 0; int i; uaecptr tagp, tagpnext; if (!dev) return openfail (ioreq, IOERR_OPENFAIL); if (!initint(context)) return openfail (ioreq, IOERR_SELFTEST); if (log_net) write_log (_T("opening %s:%d opencnt=%d ioreq=%08X\n"), SANA2NAME, unit, dev->opencnt, ioreq); if (get_word (ioreq + 0x12) < IOSTDREQ_SIZE) return openfail (ioreq, IOERR_BADLENGTH); if ((flags & SANA2OPF_PROM) && dev->opencnt > 0) return openfail (ioreq, IOERR_UNITBUSY); for (i = 0; i < MAX_OPEN_DEVICES; i++) { pdev = &pdevst[i]; if (pdev->inuse == 0) break; } if (i == MAX_OPEN_DEVICES) return openfail (ioreq, IOERR_UNITBUSY); put_long (ioreq + 24, pdev - pdevst); pdev->unit = unit; pdev->flags = flags; pdev->inuse = 1; pdev->td = td ? td[unit] : NULL; pdev->promiscuous = (flags & SANA2OPF_PROM) ? 1 : 0; if (pdev->td == NULL || pdev->td->active == 0) return openfail (ioreq, IOERR_OPENFAIL); if (dev->opencnt == 0) { dev->unit = unit; dev->sysdata = xcalloc (uae_u8, ethernet_getdatalenght (pdev->td)); if (!ethernet_open (pdev->td, dev->sysdata, dev, uaenet_gotdata, uaenet_getdata, pdev->promiscuous)) { xfree (dev->sysdata); dev->sysdata = NULL; return openfail (ioreq, IOERR_OPENFAIL); } write_log (_T("%s: initializing unit %d\n"), getdevname (), unit); dev->td = pdev->td; dev->adapter = pdev->td ? pdev->td->active : 0; if (dev->adapter) { dev->online = 1; dev->configured = 1; } start_thread (dev); } if (kickstart_version >= 36) { m68k_areg (regs, 0) = get_long (4) + 350; m68k_areg (regs, 1) = timerdevname; CallLib (context, get_long (4), -0x114); /* FindName('timer.device') */ pdev->timerbase = m68k_dreg (regs, 0); } pdev->copyfrombuff = pdev->copytobuff = pdev->packetfilter = 0; pdev->tempbuf = 0; if (get_word (ioreq + 0x12) >= SANA2_IOREQSIZE) { buffermgmt = get_long (ioreq + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4 + 4 + 4); tagpnext = buffermgmt; while (tagpnext) { uae_u32 tag = get_long (tagpnext); uae_u32 val = get_long (tagpnext + 4); tagp = tagpnext; tagpnext += 8; switch (tag) { case TAG_DONE: tagpnext = 0; break; case TAG_IGNORE: break; case TAG_MORE: tagpnext = val; break; case TAG_SKIP: tagpnext = tagp + val * 8; break; case S2_CopyToBuff: pdev->copytobuff = val; break; case S2_CopyFromBuff: pdev->copyfrombuff = val; break; case S2_PacketFilter: pdev->packetfilter = val; break; } } if (log_net) write_log (_T("%s:%d CTB=%08x CFB=%08x PF=%08x\n"), getdevname(), unit, pdev->copytobuff, pdev->copyfrombuff, pdev->packetfilter); m68k_dreg (regs, 0) = dev->td->mtu + ETH_HEADER_SIZE + 2; m68k_dreg (regs, 1) = 1; pdev->tempbuf = CallLib (context, get_long (4), -0xC6); /* AllocMem */ if (!pdev->tempbuf) { if (dev->opencnt == 0) { ethernet_close (pdev->td, dev->sysdata); xfree (dev->sysdata); dev->sysdata = NULL; } return openfail (ioreq, S2ERR_BAD_ARGUMENT); } /* buffermanagement */ put_long (ioreq + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4 + 4 + 4, pdev->tempbuf); } dev->exclusive = flags & SANA2OPF_MINE; dev->opencnt++; put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) + 1); put_byte (ioreq + 31, 0); put_byte (ioreq + 8, 7); return 0; }