int getchar(void) { struct AmigaIO *ior; char c = '\n'; struct Console *mc = ConsoleBase; unsigned long ticks; #ifdef SERCONSOLE int32_t r; #endif mc->cnior->length = 1; mc->cnior->buf = &c; mc->cnior->cmd = Cmd_Rd; SendIO(mc->cnior); ticks = 10 * timelimit; do { if (timelimit == 0) ticks = 2; mc->tmior->cmd = Cmd_Addtimereq; mc->tmior->secs = 0; mc->tmior->usec = 100000; SendIO((struct AmigaIO *)mc->tmior); ior = WaitPort(mc->cnmp); if (ior == mc->cnior) { AbortIO((struct AmigaIO *)mc->tmior); ticks = 1; } else /* if (ior == mc->tmior) */ { #ifdef SERCONSOLE if (use_serconsole) { r = RawMayGetChar(); if (r != -1) { c = r; ticks = 1; } } #endif if (ticks == 1) AbortIO((struct AmigaIO *)mc->cnior); } WaitIO((struct AmigaIO *)mc->tmior); --ticks; } while (ticks != 0); timelimit = 0; (void)WaitIO(mc->cnior); return c; }
void schedule(int t, void (*callback)(void *p), void *p) { struct nscallback *nscb; struct TimeVal tv; ULONG time_us = 0; if(schedule_list == NULL) return; nscb = AllocVec(sizeof(struct nscallback), MEMF_PRIVATE | MEMF_CLEAR); if(!nscb) return; time_us = t*10000; /* t converted to µs */ nscb->tv.Seconds = time_us / 1000000; nscb->tv.Microseconds = time_us % 1000000; GetSysTime(&tv); AddTime(&nscb->tv,&tv); // now contains time when event occurs if(nscb->treq = AllocVec(sizeof(struct TimeRequest),MEMF_PRIVATE | MEMF_CLEAR)) { *nscb->treq = *tioreq; nscb->treq->Request.io_Command=TR_ADDREQUEST; nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro SendIO((struct IORequest *)nscb->treq); } nscb->callback = callback; nscb->p = p; pblHeapInsert(schedule_list, nscb); }
void conreqtkn(void) { conreadreq->io_Command= CMD_READ; conreadreq->io_Data = (APTR)&coninput; conreadreq->io_Length = 1; SendIO((struct IORequest *)conreadreq); }
void Sys_Net_Wait(struct SysNetData *netdata, struct SysSocket *socket, unsigned int timeout_us) { fd_set rfds; ULONG sigmask; WaitIO((struct IORequest *)netdata->timerrequest); if (SetSignal(0, 0) & (1<<netdata->timerport->mp_SigBit)) Wait(1<<netdata->timerport->mp_SigBit); FD_ZERO(&rfds); FD_SET(socket->s, &rfds); netdata->timerrequest->tr_node.io_Command = TR_ADDREQUEST; netdata->timerrequest->tr_time.tv_secs = timeout_us / 1000000; netdata->timerrequest->tr_time.tv_micro = timeout_us % 1000000; SendIO((struct IORequest *)netdata->timerrequest); sigmask = 1<<netdata->timerport->mp_SigBit; WaitSelect(socket->s + 1, &rfds, 0, 0, 0, &sigmask); AbortIO((struct IORequest *)netdata->timerrequest); }
/* Waits for a signal or a timeout */ ULONG ata_WaitTO(struct IORequest* tmr, ULONG secs, ULONG micro, ULONG sigs) { ULONG sig = 1 << tmr->io_Message.mn_ReplyPort->mp_SigBit; D(struct Node *t = (struct Node *)FindTask(NULL)); D(bug("[ATA ] Timed wait %lds %ldu (task='%s')\n", secs, micro, t->ln_Name)); tmr->io_Command = TR_ADDREQUEST; ((struct timerequest*)tmr)->tr_time.tv_secs = secs; ((struct timerequest*)tmr)->tr_time.tv_micro = micro; SendIO(tmr); D(bug("[ATA ] Preset signals: %lx ('%s')\n", SetSignal(0, 0), t->ln_Name)); D(bug("[ATA ] Signals requested: %lx ('%s')\n", sigs, t->ln_Name)); D(bug("[ATA ] Timer signal: %lx ('%s')\n", sig, t->ln_Name)); sigs = Wait(sigs | sig); D(bug("[ATA ] Signals received: %lx ('%s')\n", sigs, t->ln_Name)); if (0 == (sigs & sig)) { if (!CheckIO(tmr)) AbortIO(tmr); } WaitIO(tmr); SetSignal(0, sig); return sigs & ~sig; }
void CSleep(int milliseconds) { #if defined(PSP) sceKernelDelayThread(milliseconds * 1000); #elif defined(__BEOS__) snooze(milliseconds * 1000); #elif defined(__AMIGA__) { ULONG signals; ULONG TimerSigBit = 1 << TimerPort->mp_SigBit; /* send IORequest */ TimerRequest->tr_node.io_Command = TR_ADDREQUEST; TimerRequest->tr_time.tv_secs = (milliseconds * 1000) / 1000000; TimerRequest->tr_time.tv_micro = (milliseconds * 1000) % 1000000; SendIO((struct IORequest *)TimerRequest); if (!((signals = Wait(TimerSigBit | SIGBREAKF_CTRL_C)) & TimerSigBit) ) { AbortIO((struct IORequest *)TimerRequest); } WaitIO((struct IORequest *)TimerRequest); } #else usleep(milliseconds * 1000); #endif }
int sendtocon(char *pekare, int size) { struct IntuiMessage *mymess; struct NiKMess *nikmess; int aborted = FALSE, paused=FALSE; ULONG signals,conwritesig = 1L << conwriteport->mp_SigBit, conreadsig = 1L << conreadport->mp_SigBit,windsig = 1L << NiKwind->UserPort->mp_SigBit, nikomnodesig = 1L << nikomnodeport->mp_SigBit; char console = 1, tecken; conwritereq->io_Command=CMD_WRITE; conwritereq->io_Data=(APTR)pekare; conwritereq->io_Length=size; SendIO((struct IORequest *)conwritereq); while(console) { signals = Wait(conwritesig | conreadsig | windsig | nikomnodesig); if(signals & conwritesig) { console=0; if(WaitIO((struct IORequest *)conwritereq)) printf("Error console\n"); } if(signals & conreadsig) { if((tecken=congettkn()) == 3) { if(console) { AbortIO((struct IORequest *)conwritereq); WaitIO((struct IORequest *)conwritereq); } aborted=TRUE; console=0; putstring("^C\n\r",-1,0); } else if((tecken==' ' && (Servermem->inne[nodnr].flaggor & MELLANSLAG)) || tecken==19) paused=TRUE; else if(tecken && typeaheadbuftkn<50) { typeaheadbuf[typeaheadbuftkn++]=tecken; typeaheadbuf[typeaheadbuftkn]=0; } } if(signals & windsig) { mymess=(struct IntuiMessage *)GetMsg(NiKwind->UserPort); ReplyMsg((struct Message *)mymess); cleanup(OK,""); } if(signals & nikomnodesig) { while(nikmess = (struct NiKMess *) GetMsg(nikomnodeport)) { handleservermess(nikmess); ReplyMsg((struct Message *)nikmess); } if(carrierdropped()) aborted = TRUE; } } if(paused && gettekn()==3) { putstring("^C\n\r",-1,0); return(TRUE); } return(aborted); }
long __saveds __regargs nik_sread(char *databuffer,long size,long timeout) { ULONG signals,sersig=1L << serreadport->mp_SigBit, timersig=1L << timerport->mp_SigBit; if(timeout) { serreadreq->IOSer.io_Command=CMD_READ; serreadreq->IOSer.io_Length=size; serreadreq->IOSer.io_Data=(APTR)databuffer; SendIO((struct IORequest *)serreadreq); timerreq->tr_node.io_Command=TR_ADDREQUEST; timerreq->tr_time.tv_secs=timeout/1000000; timerreq->tr_time.tv_micro=timeout%1000000; timerreq->tr_node.io_Message.mn_ReplyPort=timerport; SendIO((struct IORequest *)timerreq); for(;;) { signals=Wait(sersig | timersig); if((signals & sersig) && CheckIO((struct IORequest *)serreadreq)) { WaitIO((struct IORequest *)serreadreq); AbortIO((struct IORequest *)timerreq); WaitIO((struct IORequest *)timerreq); if(serreadreq->IOSer.io_Error || carrierdropped()) return(-1L); return((long)serreadreq->IOSer.io_Actual); } if((signals & timersig) && CheckIO((struct IORequest *)timerreq)) { WaitIO((struct IORequest *)timerreq); AbortIO((struct IORequest *)serreadreq); WaitIO((struct IORequest *)serreadreq); /* printf("Timeout! Size=%d Timeout=%d Actual=%d",size,timeout,serreadreq->IOSer.io_Actual); */ return((long)serreadreq->IOSer.io_Actual); } } } else { serreadreq->IOSer.io_Command=SDCMD_QUERY; DoIO((struct IORequest *)serreadreq); serreadreq->IOSer.io_Command=CMD_READ; if(serreadreq->IOSer.io_Actual > size) serreadreq->IOSer.io_Length=size; else serreadreq->IOSer.io_Length=serreadreq->IOSer.io_Actual; serreadreq->IOSer.io_Data=(APTR)databuffer; DoIO((struct IORequest *)serreadreq); return((long)serreadreq->IOSer.io_Actual); } }
LONG addChangeInt(struct AFSBase *afsbase, struct IOHandle *ioh) { ioh->mc_int.is_Code = (VOID_FUNC)changeIntCode; ioh->mc_int.is_Data = ioh; ioh->iochangeint->iotd_Req.io_Command = TD_ADDCHANGEINT; ioh->iochangeint->iotd_Req.io_Flags = 0; ioh->iochangeint->iotd_Req.io_Length = sizeof(struct Interrupt); ioh->iochangeint->iotd_Req.io_Data = &ioh->mc_int; ioh->iochangeint->iotd_Req.io_Error = 0; SendIO((struct IORequest *)&ioh->iochangeint->iotd_Req); return ioh->iochangeint->iotd_Req.io_Error; }
static int GM_UNIQUENAME(Init)(LIBBASETYPEPTR LIBBASE) { /* Setup the timer.device data */ LIBBASE->tb_CurrentTime.tv_secs = 0; LIBBASE->tb_CurrentTime.tv_micro = 0; LIBBASE->tb_VBlankTime.tv_secs = 0; LIBBASE->tb_VBlankTime.tv_micro = 1000000 / (SysBase->VBlankFrequency * SysBase->PowerSupplyFrequency); LIBBASE->tb_Elapsed.tv_secs = 0; LIBBASE->tb_Elapsed.tv_micro = 0; D(kprintf("Timer period: %ld secs, %ld micros\n", LIBBASE->tb_VBlankTime.tv_secs, LIBBASE->tb_VBlankTime.tv_micro)); LIBBASE->tb_MiscFlags = TF_GO; /* Initialise the lists */ NEWLIST( &LIBBASE->tb_Lists[0] ); NEWLIST( &LIBBASE->tb_Lists[1] ); NEWLIST( &LIBBASE->tb_Lists[2] ); NEWLIST( &LIBBASE->tb_Lists[3] ); NEWLIST( &LIBBASE->tb_Lists[4] ); /* Start the timer2 */ outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */ outb(0xb6, 0x43); /* Binary mode on Timer2, count mode 3? */ outb(0x00, 0x42); /* We're counting whole range */ outb(0x00, 0x42); LIBBASE->tb_prev_tick = 0xffff; /* Start up the interrupt server. This is shared between us and the HIDD that deals with the vblank */ LIBBASE->tb_VBlankInt.is_Node.ln_Pri = 0; LIBBASE->tb_VBlankInt.is_Node.ln_Type = NT_INTERRUPT; LIBBASE->tb_VBlankInt.is_Node.ln_Name = (STRPTR)MOD_NAME_STRING; LIBBASE->tb_VBlankInt.is_Code = (APTR)&VBlankInt; LIBBASE->tb_VBlankInt.is_Data = LIBBASE; AddIntServer(INTB_TIMERTICK, &LIBBASE->tb_VBlankInt); /* VBlank EMU */ LIBBASE->tb_vblank_timerequest.tr_node.io_Command = TR_ADDREQUEST; LIBBASE->tb_vblank_timerequest.tr_node.io_Device = (struct Device *)TimerBase; LIBBASE->tb_vblank_timerequest.tr_node.io_Unit = (struct Unit *)UNIT_MICROHZ; LIBBASE->tb_vblank_timerequest.tr_time.tv_secs = 0; LIBBASE->tb_vblank_timerequest.tr_time.tv_micro = 1000000 / SysBase->VBlankFrequency; SendIO(&LIBBASE->tb_vblank_timerequest.tr_node); return TRUE; }
static void ti_StartTimer(SyncTimer *st) { st->st_Pkt->dp_Type = ACTION_TIMER; st->st_Req->Request.io_Command = TR_ADDREQUEST; st->st_Req->Time.Seconds = SYNC_TIME; st->st_Req->Time.Microseconds = 0; SendIO(&st->st_Req->Request); st->st_Flags |= STF_TIMER_USED; }
void RestartTimer(void) { if (glob->timer_active) { D(bug("Queuing timer restart\n")); glob->restart_timer = 1; } else { D(bug("Immediate timer restart\n")); glob->timereq->tr_node.io_Command = TR_ADDREQUEST; glob->timereq->tr_time.tv_secs = 2; glob->timereq->tr_time.tv_micro = 0; SendIO((struct IORequest *)glob->timereq); glob->timer_active = 1; } }
__stkargs int start_timer(struct timeval * tv, struct timerequest * tr) { if (!tr) { printf("no request structure\n"); return 0; } if (tv->tv_secs == 0L && tv->tv_micro < 2L) tv->tv_micro = 2L; /* minimal delay */ tr->tr_time = *tv; tr->tr_node.io_Command = TR_ADDREQUEST; SendIO((struct IORequest *) tr); return 1; }
static void rem_resethandler(void) { if (rhdata->ioreq) { if (rhdata->handleradded) { if (rhdata->rebooting) { rhdata->timereq.tr_node.io_Message.mn_Node.ln_Type = NT_REPLYMSG; rhdata->timereq.tr_node.io_Message.mn_Node.ln_Pri = 0; rhdata->timereq.tr_node.io_Message.mn_ReplyPort = rhdata->msgport; rhdata->timereq.tr_node.io_Message.mn_Length = sizeof(rhdata->timereq); if (OpenDevice(TIMERNAME, UNIT_VBLANK, &rhdata->timereq.tr_node, 0) == 0) { rhdata->timereq.tr_node.io_Command = TR_ADDREQUEST; rhdata->timereq.tr_time.tv_secs = 3; rhdata->timereq.tr_time.tv_micro = 0; SendIO(&rhdata->timereq.tr_node); rhdata->timing = TRUE; } return; } rhdata->handleradded = FALSE; rhdata->ioreq->io_Command = KBD_REMRESETHANDLER; rhdata->ioreq->io_Data = (APTR) &rhdata->is; DoIO((struct IORequest *) rhdata->ioreq); CloseDevice((struct IORequest *) rhdata->ioreq); } DeleteIORequest((struct IORequest *) rhdata->ioreq); rhdata->ioreq = NULL; } if (rhdata->msgport) { DeleteMsgPort(rhdata->msgport); rhdata->msgport = NULL; } }
struct SysNetData *Sys_Net_Init() { struct SysNetData *netdata; netdata = AllocVec(sizeof(*netdata), MEMF_ANY); if (netdata) { SocketBase = OpenLibrary("bsdsocket.library", 0); if (SocketBase) { netdata->timerport = CreateMsgPort(); if (netdata->timerport) { netdata->timerrequest = (struct timerequest *)CreateIORequest(netdata->timerport, sizeof(*netdata->timerrequest)); if (netdata->timerrequest) { if (OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *)netdata->timerrequest, 0) == 0) { netdata->timerrequest->tr_node.io_Command = TR_ADDREQUEST; netdata->timerrequest->tr_time.tv_secs = 1; netdata->timerrequest->tr_time.tv_micro = 0; SendIO((struct IORequest *)netdata->timerrequest); AbortIO((struct IORequest *)netdata->timerrequest); return netdata; } DeleteIORequest((struct IORequest *)netdata->timerrequest); } DeleteMsgPort(netdata->timerport); } CloseLibrary(SocketBase); } FreeVec(netdata); } return 0; }
ULONG sdcard_WaitTO(struct IORequest* tmr, ULONG secs, ULONG micro, ULONG sigs) { ULONG sig = 1 << tmr->io_Message.mn_ReplyPort->mp_SigBit; tmr->io_Command = TR_ADDREQUEST; ((struct timerequest*)tmr)->tr_time.tv_secs = secs; ((struct timerequest*)tmr)->tr_time.tv_micro = micro; SendIO(tmr); sigs = Wait(sigs | sig); if (0 == (sigs & sig)) { if (!CheckIO(tmr)) AbortIO(tmr); } WaitIO(tmr); SetSignal(0, sig); return sigs &~ sig; }
static void AHI_PlayAudio(_THIS) { if(playing>1) WaitIO((struct IORequest *)audio_req[current_buffer]); /* Write the audio data out */ audio_req[current_buffer] -> ahir_Std. io_Message.mn_Node.ln_Pri = 60; audio_req[current_buffer] -> ahir_Std. io_Data = mixbuf[current_buffer]; audio_req[current_buffer] -> ahir_Std. io_Length = this->hidden->size; audio_req[current_buffer] -> ahir_Std. io_Offset = 0; audio_req[current_buffer] -> ahir_Std . io_Command = CMD_WRITE; audio_req[current_buffer] -> ahir_Frequency = this->hidden->freq; audio_req[current_buffer] -> ahir_Volume = 0x10000; audio_req[current_buffer] -> ahir_Type = this->hidden->type; audio_req[current_buffer] -> ahir_Position = 0x8000; audio_req[current_buffer] -> ahir_Link = (playing>0 ? audio_req[current_buffer^1] : NULL); SendIO((struct IORequest *)audio_req[current_buffer]); current_buffer^=1; playing++; }
__saveds void ASERDPort::serial_func(void) { struct ASERDPort *obj = (ASERDPort *)proc_arg; struct MsgPort *proc_port = NULL, *io_port = NULL, *control_port = NULL; struct IOExtSer *read_io = NULL, *write_io = NULL, *control_io = NULL; uint8 orig_params[sizeof(struct IOExtSer)]; bool opened = false; ULONG io_mask = 0, proc_port_mask = 0; // Default: error occured obj->proc_error = true; // Create message port for communication with main task proc_port = CreateMsgPort(); if (proc_port == NULL) goto quit; proc_port_mask = 1 << proc_port->mp_SigBit; // Create message ports for serial.device I/O io_port = CreateMsgPort(); if (io_port == NULL) goto quit; io_mask = 1 << io_port->mp_SigBit; control_port = CreateMsgPort(); if (control_port == NULL) goto quit; // Create IORequests read_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer)); write_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer)); control_io = (struct IOExtSer *)CreateIORequest(control_port, sizeof(struct IOExtSer)); if (read_io == NULL || write_io == NULL || control_io == NULL) goto quit; read_io->IOSer.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug write_io->IOSer.io_Message.mn_Node.ln_Type = 0; control_io->IOSer.io_Message.mn_Node.ln_Type = 0; // Parse device name char dev_name[256]; ULONG dev_unit; if (sscanf(obj->device_name, "%[^/]/%ld", dev_name, &dev_unit) < 2) goto quit; // Open device if (obj->is_parallel) ((IOExtPar *)read_io)->io_ParFlags = PARF_SHARED; else read_io->io_SerFlags = SERF_SHARED | SERF_7WIRE; if (OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)read_io, 0) || read_io->IOSer.io_Device == NULL) goto quit; opened = true; // Copy IORequests memcpy(write_io, read_io, sizeof(struct IOExtSer)); memcpy(control_io, read_io, sizeof(struct IOExtSer)); // Attach control_io to control_port and set default values control_io->IOSer.io_Message.mn_ReplyPort = control_port; if (!obj->is_parallel) { control_io->io_CtlChar = SER_DEFAULT_CTLCHAR; control_io->io_RBufLen = 64; control_io->io_ExtFlags = 0; control_io->io_Baud = 9600; control_io->io_BrkTime = 250000; control_io->io_ReadLen = control_io->io_WriteLen = 8; control_io->io_StopBits = 1; control_io->io_SerFlags = SERF_SHARED; control_io->IOSer.io_Command = SDCMD_SETPARAMS; DoIO((struct IORequest *)control_io); memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); } // Initialization went well, inform main task obj->proc_port = proc_port; obj->control_io = control_io; obj->proc_error = false; Signal(MainTask, SIGF_SINGLE); // Main loop for (;;) { // Wait for I/O and messages (CTRL_C is used for quitting the task) ULONG sig = Wait(proc_port_mask | io_mask | SIGBREAKF_CTRL_C); // Main task wants to quit us if (sig & SIGBREAKF_CTRL_C) break; // Main task sent a command to us if (sig & proc_port_mask) { struct SerMessage *msg; while (msg = (SerMessage *)GetMsg(proc_port)) { D(bug("serial_proc received %08lx\n", msg->what)); switch (msg->what) { case MSG_QUERY: control_io->IOSer.io_Command = SDCMD_QUERY; DoIO((struct IORequest *)control_io); D(bug(" query returned %08lx, actual %08lx\n", control_io->IOSer.io_Error, control_io->IOSer.io_Actual)); break; case MSG_SET_PARAMS: // Only send SDCMD_SETPARAMS when configuration has changed if (memcmp(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar))) { memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); memcpy(&(read_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); memcpy(&(write_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); control_io->IOSer.io_Command = SDCMD_SETPARAMS; D(bug(" params %08lx %08lx %08lx %08lx %08lx %08lx\n", control_io->io_CtlChar, control_io->io_RBufLen, control_io->io_ExtFlags, control_io->io_Baud, control_io->io_BrkTime, *(uint32 *)((uint8 *)control_io + 76))); DoIO((struct IORequest *)control_io); D(bug(" set_parms returned %08lx\n", control_io->IOSer.io_Error)); } break; case MSG_SET_PAR_PARAMS: control_io->IOSer.io_Command = PDCMD_SETPARAMS; DoIO((struct IORequest *)control_io); D(bug(" set_par_parms returned %08lx\n", control_io->IOSer.io_Error)); break; case MSG_BREAK: control_io->IOSer.io_Command = SDCMD_BREAK; DoIO((struct IORequest *)control_io); D(bug(" break returned %08lx\n", control_io->IOSer.io_Error)); break; case MSG_RESET: control_io->IOSer.io_Command = CMD_RESET; DoIO((struct IORequest *)control_io); D(bug(" reset returned %08lx\n", control_io->IOSer.io_Error)); break; case MSG_KILL_IO: AbortIO((struct IORequest *)read_io); AbortIO((struct IORequest *)write_io); WaitIO((struct IORequest *)read_io); WaitIO((struct IORequest *)write_io); obj->read_pending = obj->write_pending = false; obj->read_done = obj->write_done = false; break; case MSG_PRIME_IN: read_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb; read_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); read_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount); read_io->IOSer.io_Actual = 0; read_io->IOSer.io_Command = CMD_READ; D(bug("serial_proc receiving %ld bytes from %08lx\n", read_io->IOSer.io_Length, read_io->IOSer.io_Data)); SendIO((struct IORequest *)read_io); break; case MSG_PRIME_OUT: { write_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb; write_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); write_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount); write_io->IOSer.io_Actual = 0; write_io->IOSer.io_Command = CMD_WRITE; D(bug("serial_proc transmitting %ld bytes from %08lx\n", write_io->IOSer.io_Length, write_io->IOSer.io_Data)); #if MONITOR bug("Sending serial data:\n"); uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); for (int i=0; i<len; i++) { bug("%02lx ", adr[i]); } bug("\n"); #endif SendIO((struct IORequest *)write_io); break; } } D(bug(" serial_proc replying\n")); ReplyMsg(msg); } } // I/O operation completed if (sig & io_mask) { struct IOExtSer *io; while (io = (struct IOExtSer *)GetMsg(io_port)) { if (io == read_io) { D(bug("read_io complete, %ld bytes received, error %ld\n", read_io->IOSer.io_Actual, read_io->IOSer.io_Error)); uint32 pb = (uint32)read_io->IOSer.io_Message.mn_Node.ln_Name; #if MONITOR bug("Receiving serial data:\n"); uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); for (int i=0; i<read_io->IOSer.io_Actual; i++) { bug("%02lx ", adr[i]); } bug("\n"); #endif WriteMacInt32(pb + ioActCount, read_io->IOSer.io_Actual); obj->conv_error(read_io, obj->input_dt); obj->read_done = true; SetInterruptFlag(INTFLAG_SERIAL); TriggerInterrupt(); } else if (io == write_io) { D(bug("write_io complete, %ld bytes sent, error %ld\n", write_io->IOSer.io_Actual, write_io->IOSer.io_Error)); uint32 pb = (uint32)write_io->IOSer.io_Message.mn_Node.ln_Name; WriteMacInt32(pb + ioActCount, write_io->IOSer.io_Actual); obj->conv_error(write_io, obj->output_dt); obj->write_done = true; SetInterruptFlag(INTFLAG_SERIAL); TriggerInterrupt(); } } } } quit: // Close everything if (opened) { if (CheckIO((struct IORequest *)write_io) == 0) { AbortIO((struct IORequest *)write_io); WaitIO((struct IORequest *)write_io); } if (CheckIO((struct IORequest *)read_io) == 0) { AbortIO((struct IORequest *)read_io); WaitIO((struct IORequest *)read_io); } CloseDevice((struct IORequest *)read_io); } if (control_io) DeleteIORequest(control_io); if (write_io) DeleteIORequest(write_io); if (read_io) DeleteIORequest(read_io); if (control_port) DeleteMsgPort(control_port); if (io_port) DeleteMsgPort(io_port); // Send signal to main task to confirm termination Forbid(); Signal(MainTask, SIGF_SINGLE); }
void IOFS_SendPkt(struct DosPacket *dp, struct MsgPort *replyport, struct DosLibrary *DOSBase) { /* * Trying to emulate the packet system by rewriting the * packets to IO Requests. Sometimes there are too many * parameters in the packet but thats fine. If there are * not enough parameters or the wrong type etc. then * it is more difficult to translate the packet. * */ struct IOFileSys *iofs = AllocMem(sizeof(struct IOFileSys), MEMF_CLEAR); struct FileHandle *fh; BPTR oldCurDir; LONG result; if (iofs != NULL) { /* * Also attach the packet to the io request. * Will remain untouched by the driver. */ iofs->io_PacketEmulation = dp; /* * In case the packet is to be aborted * I know which IORequest to use. The user will * use the packet itself to abort the operation. */ dp->dp_Arg7 = (IPTR)iofs; iofs->IOFS.io_Message.mn_Node.ln_Type = NT_REPLYMSG; iofs->IOFS.io_Message.mn_ReplyPort = replyport; iofs->IOFS.io_Message.mn_Length = sizeof(struct IOFileSys); iofs->IOFS.io_Flags = 0; /* * Have to rewrite this packet... */ switch (dp->dp_Type) { case ACTION_NIL: case ACTION_READ_RETURN: case ACTION_WRITE_RETURN: case ACTION_TIMER: kprintf("This packet is a reserved one and should not be sent" " by you!\n"); // Alert(); return; // case ACTION_GET_BLOCK: case ACTION_DISK_CHANGE: case ACTION_DISK_TYPE: case ACTION_EVENT: case ACTION_SET_MAP: kprintf("This packet is obsolete. (ACTION type %d)\n", dp->dp_Type); return; case ACTION_FINDINPUT: // Open() MODE_OLDFILE [*] fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Command = FSA_OPEN_FILE; iofs->io_Union.io_OPEN_FILE.io_FileMode = FMF_WRITE | FMF_READ; oldCurDir = CurrentDir((BPTR)dp->dp_Arg2); result = DoNameAsynch(iofs, BStrtoCStr((BSTR)dp->dp_Arg3), DOSBase); CurrentDir(oldCurDir); if (result != 0) { kprintf("Error: Didn't find file\n"); return; } kprintf("Returned from DoNameAsynch()\n"); break; case ACTION_FINDOUTPUT: // Open() MODE_NEWFILE [*] fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Command = FSA_OPEN_FILE; iofs->io_Union.io_OPEN_FILE.io_FileMode = FMF_LOCK | FMF_CREATE | FMF_CLEAR | FMF_WRITE | FMF_READ; oldCurDir = CurrentDir((BPTR)dp->dp_Arg2); result = DoNameAsynch(iofs, BStrtoCStr((BSTR)dp->dp_Arg3), DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } break; case ACTION_FINDUPDATE: // Open() MODE_READWRITE [*] fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Command = FSA_OPEN_FILE; iofs->io_Union.io_OPEN_FILE.io_FileMode = FMF_CREATE | FMF_WRITE | FMF_READ; oldCurDir = CurrentDir((BPTR)dp->dp_Arg2); result = DoNameAsynch(iofs, BStrtoCStr((BSTR)dp->dp_Arg3), DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } break; case ACTION_READ: // Read() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_READ; iofs->io_Union.io_READ_WRITE.io_Buffer = (APTR)dp->dp_Arg2; iofs->io_Union.io_READ_WRITE.io_Length = (LONG)dp->dp_Arg3; break; case ACTION_WRITE: // Write() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_WRITE; iofs->io_Union.io_READ_WRITE.io_Buffer = (APTR)dp->dp_Arg2; iofs->io_Union.io_READ_WRITE.io_Length = (LONG)dp->dp_Arg3; break; case ACTION_SEEK: // Seek() [*] CH fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; /* If the file is in write mode flush it. This is done synchronously as otherwise the seek may be served before the flush. (TODO: What are a reasonable semantics here?) */ if (fh->fh_Flags & FHF_WRITE) { Flush(MKBADDR(fh)); } else { /* Read mode. Just reinit the buffers. We can't call Flush() in this case as that would end up in recursion. */ fh->fh_Pos = fh->fh_End = fh->fh_Buf; } iofs->IOFS.io_Command = FSA_SEEK; iofs->io_Union.io_SEEK.io_Offset = (QUAD)dp->dp_Arg2; iofs->io_Union.io_SEEK.io_SeekMode = dp->dp_Arg3; break; case ACTION_SET_FILE_SIZE: // SetFileSize() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_SET_FILE_SIZE; iofs->io_Union.io_SET_FILE_SIZE.io_Offset = (QUAD)dp->dp_Arg2; iofs->io_Union.io_SET_FILE_SIZE.io_SeekMode = dp->dp_Arg3; break; case ACTION_EXAMINE_FH: // ExamineFH() case ACTION_EXAMINE_OBJECT: // Examine() [*] -- the same thing // in AROS { UBYTE *buffer = AllocVec(sizeof(struct ExAllData), MEMF_PUBLIC | MEMF_CLEAR); if (buffer == NULL) { dp->dp_Res1 = DOSFALSE; dp->dp_Res2 = ERROR_NO_FREE_STORE; return; } fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_EXAMINE; iofs->io_Union.io_EXAMINE.io_ead = (struct ExAllData *)buffer; iofs->io_Union.io_EXAMINE.io_Size = sizeof(struct ExAllData); iofs->io_Union.io_EXAMINE.io_Mode = ED_OWNER; /* A supplied FileInfoBlock (is a BPTR) is in dp_Arg2 */ break; } case ACTION_EXAMINE_NEXT: // ExNext() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_EXAMINE_NEXT; iofs->io_Union.io_EXAMINE_NEXT.io_fib = (BPTR)dp->dp_Arg2; break; case ACTION_CREATE_DIR: // CreateDir() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_CREATE_DIR; iofs->io_Union.io_CREATE_DIR.io_Filename = BStrtoCStr((BSTR)dp->dp_Arg2); iofs->io_Union.io_CREATE_DIR.io_Protection = 0; break; case ACTION_DELETE_OBJECT: // DeleteFile() [*] // ARG1: LOCK Lock to which ARG2 is relative // ARG2: BSTR Name of object to delete (relative to ARG1) fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; /* IFS_DELETE_OBJECT just consists of a STRPTR so we have to use NameFromLock() here -- TODO */ // iofs->io_Union.io_DELETE_OBJECT.io_Filename = BStrtoCStr((BSTR)dp->dp_Arg2); iofs->IOFS.io_Command = FSA_DELETE_OBJECT; break; case ACTION_RENAME_OBJECT: // Rename() /* TODO */ break; case ACTION_LOCK_RECORD: // LockRecord() fh = (struct FileHandle *)BADDR(dp->dp_Arg1); iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->io_Union.io_RECORD.io_Offset = (QUAD)dp->dp_Arg2; iofs->io_Union.io_RECORD.io_Size = (LONG)dp->dp_Arg3; iofs->io_Union.io_RECORD.io_RecordMode = (LONG)dp->dp_Arg4; iofs->io_Union.io_RECORD.io_Timeout = (LONG)dp->dp_Arg5; break; case ACTION_FREE_RECORD: // UnlockRecord() fh = (struct FileHandle *)BADDR(dp->dp_Arg1); iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->io_Union.io_RECORD.io_Offset = (QUAD)dp->dp_Arg2; iofs->io_Union.io_RECORD.io_Size = (LONG)dp->dp_Arg3; iofs->io_Union.io_RECORD.io_RecordMode = (LONG)dp->dp_Arg4; break; case ACTION_PARENT: // ParentDir() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_OPEN; iofs->io_Union.io_OPEN.io_FileMode = FMF_READ; // Shared lock oldCurDir = CurrentDir((BPTR)dp->dp_Arg1); result = DoNameAsynch(iofs, "/", DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } return; case ACTION_SET_PROTECT: // SetProtection() [*] // STRPTR io_Filename; /* The file to change. */ // ULONG io_Protection; /* The new protection bits. */ fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_SET_PROTECT; iofs->io_Union.io_SET_PROTECT.io_Protection = dp->dp_Arg4; iofs->io_Union.io_SET_PROTECT.io_Filename = BStrtoCStr(dp->dp_Arg3); break; case ACTION_SET_COMMENT: // SetComment() [*] fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_SET_COMMENT; iofs->io_Union.io_SET_COMMENT.io_Filename = BStrtoCStr((BSTR)dp->dp_Arg3); iofs->io_Union.io_SET_COMMENT.io_Comment = BStrtoCStr(dp->dp_Arg4); break; case ACTION_LOCATE_OBJECT: // Lock() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_OPEN; switch (dp->dp_Arg3) { case EXCLUSIVE_LOCK: iofs->io_Union.io_OPEN.io_FileMode = FMF_LOCK | FMF_READ; break; case SHARED_LOCK: iofs->io_Union.io_OPEN.io_FileMode = FMF_READ; break; default: iofs->io_Union.io_OPEN.io_FileMode = dp->dp_Arg3; break; } oldCurDir = CurrentDir((BPTR)dp->dp_Arg1); result = DoNameAsynch(iofs, BStrtoCStr((BSTR)dp->dp_Arg2), DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } dp->dp_Arg6 = (IPTR)AllocDosObject(DOS_FILEHANDLE, NULL); if (dp->dp_Arg6 == (IPTR)NULL) { return; } break; case ACTION_COPY_DIR: // DupLock() case ACTION_COPY_DIR_FH: // DupLockFromFH() -- the same thing // in AROS fh = (struct FileHandle *)BADDR(dp->dp_Arg1); iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_OPEN; /* Create a shared lock */ iofs->io_Union.io_OPEN.io_FileMode = FMF_READ; oldCurDir = CurrentDir((BPTR)dp->dp_Arg1); result = DoNameAsynch(iofs, "", DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } dp->dp_Arg6 = (IPTR)AllocDosObject(DOS_FILEHANDLE, NULL); if (dp->dp_Arg6 == (IPTR)NULL) { return; } break; case ACTION_END: // Close() [*] case ACTION_FREE_LOCK: // UnLock() -- the same thing in AROS fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; /* If the filehandle has a pending write on it Flush() the buffer. This is made synchronously... */ if (fh->fh_Flags & FHF_WRITE) { Flush(MKBADDR(fh)); } iofs->IOFS.io_Command = FSA_CLOSE; break; case ACTION_SET_DATE: // SetFileDate() [*] fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_SET_DATE; memcpy(&iofs->io_Union.io_SET_DATE.io_Date, (APTR)dp->dp_Arg4, sizeof(struct DateStamp)); oldCurDir = CurrentDir((BPTR)dp->dp_Arg2); result = DoNameAsynch(iofs, BStrtoCStr((BSTR)dp->dp_Arg3), DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } break; case ACTION_SAME_LOCK: // SameLock() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_SAME_LOCK; iofs->io_Union.io_SAME_LOCK.io_Lock[0] = BADDR((BPTR)dp->dp_Arg1); iofs->io_Union.io_SAME_LOCK.io_Lock[1] = BADDR((BPTR)dp->dp_Arg2); break; case ACTION_MAKE_LINK: // MakeLink() { STRPTR name = BStrtoCStr(dp->dp_Arg2); if (dp->dp_Arg4 == LINK_SOFT) { /* We want a soft-link. */ iofs->IOFS.io_Command = FSA_CREATE_SOFTLINK; iofs->io_Union.io_CREATE_SOFTLINK.io_Reference = (STRPTR)dp->dp_Arg3; } else { /* We want a hard-link. */ struct FileHandle *fh = (struct FileHandle *)BADDR((BPTR)dp->dp_Arg3); struct DevProc *dvp; /* We check, if name and dest are on the same device. */ if ((dvp = GetDeviceProc(name, NULL)) == NULL) { /* TODO: Simulate packet return */ return; } if (dvp->dvp_Port != (struct MsgPort *)fh->fh_Device) { FreeDeviceProc(dvp); SetIoErr(ERROR_RENAME_ACROSS_DEVICES); /* TODO: Simulate packet return */ return; } FreeDeviceProc(dvp); iofs->IOFS.io_Command = FSA_CREATE_HARDLINK; iofs->io_Union.io_CREATE_HARDLINK.io_OldFile = fh->fh_Unit; } oldCurDir = CurrentDir((BPTR)dp->dp_Arg1); DoNameAsynch(iofs, name, DOSBase); CurrentDir(oldCurDir); } break; case ACTION_READ_LINK: // ReadLink() /* TODO */ break; case ACTION_EXAMINE_ALL: // ExAll() /* TODO */ break; case ACTION_ADD_NOTIFY: // StartNotify() { struct NotifyRequest *notify = (struct NotifyRequest *)BADDR(dp->dp_Arg1); struct FileHandle *dir; iofs->IOFS.io_Command = FSA_ADD_NOTIFY; iofs->io_Union.io_NOTIFY.io_NotificationRequest = notify; notify->nr_MsgCount = 0; if (strchr(notify->nr_Name, ':') != NULL) { DoNameAsynch(iofs, notify->nr_Name, DOSBase); } else { dir = BADDR(CurrentDir(NULL)); CurrentDir(MKBADDR(dir)); /* Set back the current dir */ if (dir == NULL) { return; } iofs->IOFS.io_Device = dir->fh_Device; iofs->IOFS.io_Unit = dir->fh_Unit; /* Save device for EndNotify() purposes */ notify->nr_Handler = (struct MsgPort *) dir->fh_Device; if (iofs->IOFS.io_Device == NULL) { return; } } } break; case ACTION_REMOVE_NOTIFY: // EndNotify() { struct NotifyRequest *notify = (struct NotifyRequest *)BADDR(dp->dp_Arg1); iofs->IOFS.io_Command = FSA_REMOVE_NOTIFY; iofs->io_Union.io_NOTIFY.io_NotificationRequest = notify; if (strchr(notify->nr_Name, ':')) { DoNameAsynch(iofs, notify->nr_Name, DOSBase); } else { iofs->IOFS.io_Device = (struct Device *)notify->nr_Handler; if (iofs->IOFS.io_Device == NULL) { return; } } } break; /* The following five packets are only relative to the message port of the file system to send to. Therefore, we fill in only partial information in the IOFileSys and hope for the best... Specifically, the device cannot use iofs->io_Device. TODO */ case ACTION_RENAME_DISK: // Relabel() /* TODO */ break; case ACTION_FORMAT: // Format() /* TODO */ break; case ACTION_MORE_CACHE: // AddBuffers() /* TODO */ break; case ACTION_INHIBIT: // Inhibit() /* TODO */ break; case ACTION_IS_FILESYSTEM: // IsFileSystem() /* TODO */ break; case ACTION_DISK_INFO: // Info() /* TODO */ break; case ACTION_INFO: // No associated function /* TODO */ break; case ACTION_CURRENT_VOLUME: // No associated function /* TODO */ break; case ACTION_PARENT_FH: // ParentOfFH() /* TODO -- Should be the same as ACTION_PARENT? For some reason ParentDir() and ParentOfFH() is implemented differently in AROS. Have to investigate this further. */ break; case ACTION_FH_FROM_LOCK: // OpenFromLock() /* TODO: Have so simulate ReplyMsg() here */ return; case ACTION_SET_OWNER: // SetOwner() // Unfortunately, I have no info regardning this packet. // iofs->IOFS.io_Command = FSA_SET_OWNER; // iofs->io_Union.io_SET_OWNER.io_UID = owner_info >> 16; // iofs->io_Union.io_SET_OWNER.io_GID = owner_info & 0xffff; break; case ACTION_CHANGE_MODE: // ChangeMode() /* TODO */ break; /* I haven't looked into the following packets in detail */ case ACTION_DIE: // No associated function break; case ACTION_WRITE_PROTECT: // No associated function break; case ACTION_FLUSH: // No associated function break; case ACTION_SERIALIZE_DISK: // No associated function break; // --- Console only packets ------------------------------ /* I think these should not be implemented as packets except for ACTION_WAIT_CHAR which is not really a console only packet. Instead functions should be added to console.device */ case ACTION_SCREEN_MODE: // SetMode() /* TODO*/ break; case ACTION_CHANGE_SIGNAL: // No associated function { struct MsgPort *msgport; struct Task *task; fh = (struct FileHandle *)dp->dp_Arg1; msgport = (struct MsgPort *)dp->dp_Arg2; task = msgport ? msgport->mp_SigTask : NULL; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_CHANGE_SIGNAL; iofs->io_Union.io_CHANGE_SIGNAL.io_Task = task; } break; case ACTION_WAIT_CHAR: // WaitForChar() /* TODO */ break; default: D(kprintf("Unknown packet type %d found in SendPkt()\n", dp->dp_Type)); dp->dp_Res1 = DOSFALSE; dp->dp_Res2 = ERROR_ACTION_NOT_KNOWN; PutMsg(replyport, dp->dp_Link); return; } D(kprintf("Calling SendIO() with command %u\n", iofs->IOFS.io_Command)); SendIO((struct IORequest *)iofs); } }
int main(int argc, char *argv[]) { BYTE *p1=buffer1,*p2=buffer2; void *tmp; ULONG signals,length; struct AHIRequest *link = NULL; LONG priority = 0; BYTE pri; if(argc == 2) { StrToLong(argv[1], &priority); } pri = priority; Printf("Sound priority: %ld\n", pri); if((AHImp=CreateMsgPort()) != NULL) { if((AHIio=(struct AHIRequest *)CreateIORequest(AHImp,sizeof(struct AHIRequest))) != NULL) { AHIio->ahir_Version = 4; AHIDevice=OpenDevice(AHINAME,0,(struct IORequest *)AHIio,0); } } if(AHIDevice) { Printf("Unable to open %s/0 version 4\n",AHINAME); cleanup(RETURN_FAIL); } // Make a copy of the request (for double buffering) AHIiocopy = AllocMem(sizeof(struct AHIRequest), MEMF_ANY); if(! AHIiocopy) { cleanup(RETURN_FAIL); } CopyMem(AHIio, AHIiocopy, sizeof(struct AHIRequest)); AHIios[0]=AHIio; AHIios[1]=AHIiocopy; SetIoErr(0); for(;;) { // Fill buffer length = Read(Input(),p1,BUFFERSIZE); // Play buffer AHIios[0]->ahir_Std.io_Message.mn_Node.ln_Pri = pri; AHIios[0]->ahir_Std.io_Command = CMD_WRITE; AHIios[0]->ahir_Std.io_Data = p1; AHIios[0]->ahir_Std.io_Length = length; AHIios[0]->ahir_Std.io_Offset = 0; AHIios[0]->ahir_Frequency = FREQUENCY; AHIios[0]->ahir_Type = TYPE; AHIios[0]->ahir_Volume = 0x10000; // Full volume AHIios[0]->ahir_Position = 0x8000; // Centered AHIios[0]->ahir_Link = link; SendIO((struct IORequest *) AHIios[0]); if(link) { // Wait until the last buffer is finished (== the new buffer is started) signals=Wait(SIGBREAKF_CTRL_C | (1L << AHImp->mp_SigBit)); // Check for Ctrl-C and abort if pressed if(signals & SIGBREAKF_CTRL_C) { SetIoErr(ERROR_BREAK); break; } // Remove the reply and abort on error if(WaitIO((struct IORequest *) link)) { SetIoErr(ERROR_WRITE_PROTECTED); break; } } // Check for end-of-sound, and wait until it is finished before aborting if(length != BUFFERSIZE) { WaitIO((struct IORequest *) AHIios[0]); break; } link = AHIios[0]; // Swap buffer and request pointers, and restart tmp = p1; p1 = p2; p2 = tmp; tmp = AHIios[0]; AHIios[0] = AHIios[1]; AHIios[1] = tmp; } // Abort any pending iorequests AbortIO((struct IORequest *) AHIios[0]); WaitIO((struct IORequest *) AHIios[0]); if(link) { // Only if the second request was started AbortIO((struct IORequest *) AHIios[1]); WaitIO((struct IORequest *) AHIios[1]); } if(IoErr()) { PrintFault(IoErr(), argv[0] ); cleanup(RETURN_ERROR); } cleanup(RETURN_OK); return RETURN_OK; // Make compiler happy }
void main(int argc, char *argv[]) { BYTE *p1=buffer1,*p2=buffer2,*tmp; ULONG signals; if(AHImp=CreateMsgPort()) { if(AHIio=(struct AHIRequest *)CreateIORequest(AHImp,sizeof(struct AHIRequest))) { AHIio->ahir_Version = 4; AHIDevice=OpenDevice(AHINAME,0,(struct IORequest *)AHIio,NULL); } } if(AHIDevice) { Printf("Unable to open %s/0 version 4\n",AHINAME); cleanup(RETURN_FAIL); } // Initialize the first read AHIio->ahir_Std.io_Command=CMD_READ; AHIio->ahir_Std.io_Data=&buffer1; AHIio->ahir_Std.io_Length=BUFFERSIZE; AHIio->ahir_Std.io_Offset=0; AHIio->ahir_Frequency=FREQUENCY; AHIio->ahir_Type=TYPE; if(!DoIO((struct IORequest *) AHIio)) { // The first buffer is now filled SetIoErr(NULL); for(;;) { ULONG length; length=AHIio->ahir_Std.io_Actual; // Initialize the second read (note that io_Offset is not cleared!) AHIio->ahir_Std.io_Data=p2; AHIio->ahir_Std.io_Length=BUFFERSIZE; AHIio->ahir_Frequency=FREQUENCY; AHIio->ahir_Type=TYPE; SendIO((struct IORequest *) AHIio); // While the second read is in progress, save the first buffer to stdout if(Write(Output(),p1,length) != length) { break; } signals=Wait(SIGBREAKF_CTRL_C | (1L << AHImp->mp_SigBit)); if(signals & SIGBREAKF_CTRL_C) { SetIoErr(ERROR_BREAK); break; } // Remove the reply if(WaitIO((struct IORequest *) AHIio)) { SetIoErr(ERROR_READ_PROTECTED); break; } // Swap buffer pointers and repeat tmp=p1; p1=p2; p2=tmp; } // Abort any pending iorequests AbortIO((struct IORequest *) AHIio); WaitIO((struct IORequest *) AHIio); } if(IoErr()) { PrintFault(IoErr(), argv[0] ); // Oh, common! It's not MY fault that this // routine prints to stdout instead of stderr! cleanup(RETURN_ERROR); } cleanup(RETURN_OK); }
static void Slave( struct ExecBase* SysBase ) { struct AHIAudioCtrlDrv* AudioCtrl; struct DriverBase* AHIsubBase; struct DeviceBase* DeviceBase; BOOL running; ULONG signals; AudioCtrl = (struct AHIAudioCtrlDrv*) FindTask( NULL )->tc_UserData; AHIsubBase = (struct DriverBase*) dd->ahisubbase; DeviceBase = (struct DeviceBase*) AHIsubBase; dd->slavesignal = AllocSignal( -1 ); if( dd->slavesignal != -1 ) { struct MsgPort* ahi_mp = NULL; struct AHIRequest* ahi_iorequest = NULL; APTR ahi_iocopy = NULL; BYTE ahi_device = -1; struct AHIRequest* ahi_io[ 2 ] = { NULL, NULL }; BOOL ahi_io_used[ 2 ] = { FALSE, FALSE }; ULONG frame_length = 0; ahi_mp = CreateMsgPort(); if( ahi_mp != NULL ) { ahi_iorequest = CreateIORequest( ahi_mp, sizeof( struct AHIRequest ) ); if( ahi_iorequest != NULL ) { ahi_iorequest->ahir_Version = 4; ahi_device = OpenDevice( AHINAME, dd->unit, (struct IORequest*) ahi_iorequest, 0 ); if( ahi_device == 0 ) { struct Library* AHIBase = (struct Library*) ahi_iorequest->ahir_Std.io_Device; ahi_iocopy = AllocVec( sizeof( *ahi_iorequest ), MEMF_ANY ); if( ahi_iocopy != NULL ) { bcopy( ahi_iorequest, ahi_iocopy, sizeof( *ahi_iorequest ) ); ahi_io[ 0 ] = ahi_iorequest; ahi_io[ 1 ] = ahi_iocopy; // Everything set up. Tell Master we're alive and healthy. Signal( (struct Task*) dd->mastertask, 1L << dd->mastersignal ); running = TRUE; // The main playback loop follow while( running ) { int skip_mix; APTR tmp_buff; struct AHIRequest* tmp_io; if( ahi_io_used[ 0 ] ) { LONG err; ULONG mask = ( SIGBREAKF_CTRL_C | (1L << dd->slavesignal) | (1L << ahi_mp->mp_SigBit) ); signals = Wait( mask ); if( signals & ( SIGBREAKF_CTRL_C | (1L << dd->slavesignal) ) ) { running = FALSE; break; } err = WaitIO( (struct IORequest*) ahi_io[ 0 ] ); if( err != 0 ) { KPrintF( DRIVER ": AHI device error %ld\n", err ); // running = FALSE; break; } } skip_mix = CallHookPkt( AudioCtrl->ahiac_PreTimerFunc, (Object*) AudioCtrl, 0 ); CallHookPkt( AudioCtrl->ahiac_PlayerFunc, AudioCtrl, NULL ); if( ! skip_mix ) { CallHookPkt( AudioCtrl->ahiac_MixerFunc, AudioCtrl, dd->mixbuffers[ 0 ] ); } CallHookPkt( AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0 ); if( frame_length == 0 ) { frame_length = AHI_SampleFrameSize( AudioCtrl->ahiac_BuffType ); } ahi_io[ 0 ]->ahir_Std.io_Command = CMD_WRITE; ahi_io[ 0 ]->ahir_Std.io_Data = dd->mixbuffers[ 0 ]; ahi_io[ 0 ]->ahir_Std.io_Length = ( AudioCtrl->ahiac_BuffSamples * frame_length ); ahi_io[ 0 ]->ahir_Std.io_Offset = 0; ahi_io[ 0 ]->ahir_Frequency = AudioCtrl->ahiac_MixFreq; ahi_io[ 0 ]->ahir_Type = AudioCtrl->ahiac_BuffType; ahi_io[ 0 ]->ahir_Volume = 0x10000; ahi_io[ 0 ]->ahir_Position = 0x08000; ahi_io[ 0 ]->ahir_Link = ( ahi_io_used[ 1 ] ? ahi_io[ 1 ] : NULL ); SendIO( (struct IORequest*) ahi_io[ 0 ] ); tmp_io = ahi_io[ 0 ]; ahi_io[ 0 ] = ahi_io[ 1 ]; ahi_io[ 1 ] = tmp_io; tmp_buff = dd->mixbuffers[ 0 ]; dd->mixbuffers[ 0 ] = dd->mixbuffers[ 1 ]; dd->mixbuffers[ 1 ] = tmp_buff; ahi_io_used[ 0 ] = ahi_io_used[ 1 ]; ahi_io_used[ 1 ] = TRUE; } if( ahi_io_used[ 0 ] ) { AbortIO( (struct IORequest*) ahi_io[ 0 ] ); WaitIO( (struct IORequest*) ahi_io[ 0 ] ); } if( ahi_io_used[ 1 ] ) { AbortIO( (struct IORequest*) ahi_io[ 1 ] ); WaitIO( (struct IORequest*) ahi_io[ 1 ] ); } FreeVec( ahi_iocopy ); } CloseDevice( (struct IORequest*) ahi_iorequest ); } DeleteIORequest( (struct IORequest*) ahi_iorequest ); } DeleteMsgPort( ahi_mp ); } } FreeSignal( dd->slavesignal ); dd->slavesignal = -1; Forbid(); // Tell the Master we're dying Signal( (struct Task*) dd->mastertask, 1L << dd->mastersignal ); dd->slavetask = NULL; // Multitaking will resume when we are dead. }