Beispiel #1
0
int
consclose(void)
{
	struct Console *mc = ConsoleBase;

	if (mc == NULL)
		return 0;
	if (mc->tmior) {
		CloseDevice((struct AmigaIO *)mc->tmior);
		DeleteIORequest(mc->tmior);
	}

	if (mc->cnior) {
		CloseDevice(mc->cnior);
		DeleteIORequest(mc->cnior);
	}

	if (mc->cnmp)
		DeleteMsgPort(mc->cnmp);

	if (mc->w)
		CloseWindow(mc->w);

	if (mc->s)
		CloseScreen(mc->s);
	if (IntuitionBase)
		CloseLibrary(IntuitionBase);
	ConsoleBase = NULL;
	return 0;
}
Beispiel #2
0
void DIO_Cleanup(struct DiskIO *dio) {
	DEBUGF("DIO_Cleanup(%#p)\n", dio);

	if (dio != NULL) {
		DIO_FlushIOCache(dio);

#ifndef DISABLE_BLOCK_CACHE
		if (dio->block_cache != NULL)
			CleanupBlockCache(dio->block_cache);
#endif

		DeletePool(dio->mempool);

		if (dio->disk_device != NULL)
			CloseDevice((struct IORequest *)dio->diskiotd);

		DeleteIORequest((struct IORequest *)dio->diskiotd);
		DeleteMsgPort(dio->diskmp);

		if (dio->uninhibit)
			Inhibit(dio->devname, FALSE);

		FreeMem(dio, sizeof(*dio));
	}
}
static int Audio_Available(void)
{
	int ok=0;
	struct MsgPort *p;
	struct AHIRequest *req;

	if(p=CreateMsgPort())
	{
		if(req=(struct AHIRequest *)CreateIORequest(p,sizeof(struct AHIRequest)))
		{
			req->ahir_Version=4;

			if(!OpenDevice(AHINAME,0,(struct IORequest *)req,NULL))
			{
				D(bug("AHI available.\n"));
				ok=1;
				CloseDevice((struct IORequest *)req);
			}
			DeleteIORequest((struct IORequest *)req);
		}
		DeleteMsgPort(p);
	}

	D(if(!ok) bug("AHI not available\n"));
	return ok;
}
Beispiel #4
0
void SendEvent(LONG event) {
    struct IOStdReq *InputRequest;
    struct MsgPort *InputPort;
    struct InputEvent *ie;

    if ((InputPort = (struct MsgPort*)CreateMsgPort())) {

        if ((InputRequest = (struct IOStdReq*)CreateIORequest(InputPort, sizeof(struct IOStdReq)))) {

            if (!OpenDevice("input.device", 0, (struct IORequest*)InputRequest, 0)) {

                if ((ie = AllocVec(sizeof(struct InputEvent), MEMF_PUBLIC | MEMF_CLEAR))) {
                    ie->ie_Class = event;
                    InputRequest->io_Command = IND_WRITEEVENT;
                    InputRequest->io_Data = ie;
                    InputRequest->io_Length = sizeof(struct InputEvent);

                    DoIO((struct IORequest*)InputRequest);

                    FreeVec(ie);
                }
                CloseDevice((struct IORequest*)InputRequest);
            }
            DeleteIORequest((struct IORequest *)InputRequest);
        }
        DeleteMsgPort (InputPort);
    }
}
int
main(int argc, char* argv[]) {
  int rc = RETURN_OK;

  if (argc != 2) {
    fprintf(stderr, "Usage: %s <audio mode id>\n", argv[0]);
    rc = RETURN_ERROR;
  }
  else {
    struct MsgPort* mp = CreateMsgPort();

    if (mp != NULL) {
      struct AHIRequest* io = (struct AHIRequest *)
	CreateIORequest(mp, sizeof(struct AHIRequest));

      if (io != NULL) {
	io->ahir_Version = 4;

	if (OpenDevice(AHINAME, AHI_NO_UNIT, (struct IORequest *) io, 0) == 0) {
	  AHIBase = (struct Library *) io->ahir_Std.io_Device;

	  BetterAudioID = atol(argv[1]);

	  Forbid();
	  OldBestAudioIDA = (BestAudioIDA_proto*) 
	    SetFunction(AHIBase, _LVOAHI_BestAudioIDA,
			(ULONG (*)(void)) MyBestAudioIDA );

	  Wait(SIGBREAKF_CTRL_C);

	  SetFunction(AHIBase, _LVOAHI_BestAudioIDA,
		      (ULONG (*)(void)) OldBestAudioIDA );
	  rc = 0;

	  Permit();

	  CloseDevice((struct IORequest *) io);
	}
	else {
	  fprintf(stderr, "Unable to open '" AHINAME "' version 4.\n");
	  rc = RETURN_FAIL;
	}
	
	DeleteIORequest((struct IORequest *) io);
      }
      else {
	fprintf(stderr, "Unable to create IO request.\n");
	rc = RETURN_FAIL;
      }

      DeleteMsgPort(mp);
    }
    else {
      fprintf(stderr, "Unable to create message port.\n");
      rc = RETURN_FAIL;
    }
  }
  
  return rc;
}
Beispiel #6
0
static void entry(void)
{
    struct MsgPort *port1,*port2;
    struct Message *msg;

    Forbid();
    port1=FindPort("message test port");
    Permit();

    port2=CreateMsgPort();
    if(port2!=NULL)
    {
	msg=(struct Message *)CreateIORequest(port2,sizeof(struct Message));
	if(msg!=NULL)
	{
	    int i;
	    for(i=0;i<10;i++)
	    {
		msg->mn_Node.ln_Name=(char *)i;
		PutMsg(port1,msg);
		WaitPort(port2);
		GetMsg(port2);
	    }
	    DeleteIORequest((struct IORequest *)msg);
	}
	DeleteMsgPort(port2);
    }

    Signal(port1->mp_SigTask,1<<port1->mp_SigBit);

    Wait(0);/* Let the parent remove me */
}
Beispiel #7
0
void
ti_Cleanup(Global_T *g)
{
#ifndef DISABLED
    SyncTimer *st = &g->g_SyncTimer;

    if(st->st_Pkt)
    {
	if(st->st_Req)
	{
	    if(st->st_Flags & STF_TIMER_USED)
	    {
    		if(!CheckIO(&st->st_Req->Request))
		      AbortIO(&st->st_Req->Request);

    		WaitIO(&st->st_Req->Request);
	    }

      if(st->st_Flags & STF_DEVICE_OPEN)
		    CloseDevice(&st->st_Req->Request);
	}
    }

    if(st->st_Pkt)
    	FreeVec(st->st_Pkt);

    if(st->st_Req)
	    DeleteIORequest(st->st_Req);
    
    memset(st, 0, sizeof(*st));
#endif
}
Beispiel #8
0
void cleanup(LONG rc)
{
  if(!AHIDevice)
    CloseDevice((struct IORequest *)AHIio);
  DeleteIORequest((struct IORequest *)AHIio);
  DeleteMsgPort(AHImp);
  exit(rc);
}
Beispiel #9
0
void cleanup(LONG rc)
{
  if(!AHIDevice)
    CloseDevice((struct IORequest *)AHIio);
  DeleteIORequest((struct IORequest *)AHIio);
  FreeMem(AHIiocopy,sizeof(struct AHIRequest));
  DeleteMsgPort(AHImp);
  exit(rc);
}
void Sys_Net_Shutdown(struct SysNetData *netdata)
{
	WaitIO((struct IORequest *)netdata->timerrequest);
	CloseDevice((struct IORequest *)netdata->timerrequest);
	DeleteIORequest((struct IORequest *)netdata->timerrequest);
	DeleteMsgPort(netdata->timerport);
	CloseLibrary(SocketBase);
	FreeVec(netdata);
}
Beispiel #11
0
void sdcard_CloseTimer(struct IORequest *tmr)
{
    if (NULL != tmr)
    {
	struct MsgPort *p = tmr->io_Message.mn_ReplyPort;
	CloseDevice(tmr);
	DeleteIORequest(tmr);
	DeleteMsgPort(p);
    }
}
void __cleanupselect(void)
{
  if (_treq) {
    DeleteIORequest(_treq); _treq=NULL;
  }

  if (_tport) {
    DeleteMsgPort(_tport); _tport=NULL;
  }
}
Beispiel #13
0
cdrom_interface::~cdrom_interface(void)
{
  if (cd_error == 0) {
    CloseDevice((struct IORequest *)CDIO);
  }
  if (CDIO != NULL) {
    DeleteIORequest((struct IORequest *)CDIO);
  }
  if (CDMP != NULL) {
    DeleteMsgPort(CDMP);
  }
}
Beispiel #14
0
void CleanupTimer(void)
{
    D(bug("[fat] Cleaning up timer\n"));
    if (glob->timer_active) {
        D(bug("[fat] Terminating active request\n"));
        AbortIO((struct IORequest *)glob->timereq);
        WaitIO((struct IORequest *)glob->timereq);
    }
    CloseDevice((struct IORequest *)glob->timereq);
    DeleteIORequest((struct IORequest *)glob->timereq);
    DeleteMsgPort(glob->timerport);
}
void
cleanup( int rc )
{
  if( AHIDevice == 0 )
  {
    CloseDevice( (struct IORequest *) AHIio );
  }

  DeleteIORequest( (struct IORequest *) AHIio);
  DeleteMsgPort( AHImp );

  exit( rc );
}
Beispiel #16
0
void CleanUp(void) {
  if(!AHIDevice)
    CloseDevice((struct IORequest *)AHIio);
  DeleteIORequest((struct IORequest *)AHIio);
  DeleteMsgPort(AHImp);

  AHIBase = NULL; AHImp = NULL; AHIio = NULL; AHIDevice = -1;

  CloseahiprefsCatalog();

  CloseLibrary(LocaleBase);
  LocaleBase = NULL;
}
void
cleanup( void )
{
  if( AHIDevice == 0 )
  {
    CloseDevice( (struct IORequest *) AHIio );
  }

  DeleteIORequest( (struct IORequest *) AHIio);
  DeleteMsgPort( AHImp );

  CloseLibrary( (struct Library*) IntuitionBase );
  CloseLibrary( (struct Library*) GfxBase );
}
int
main( int argc, char* argv[] ) {
  int rc = RETURN_OK;

  if( argc != 1 ) {
    fprintf( stderr, "Usage: %s\n", argv[ 0 ] );
    rc = RETURN_ERROR;
  }
  else {
    struct MsgPort* mp = CreateMsgPort();
    
    if( mp != NULL ) {
      struct AHIRequest* io = (struct AHIRequest *)
	CreateIORequest( mp, sizeof( struct AHIRequest ) );

      if( io != NULL ) {
	// We use 32 bit samples, so we need version 6.
	io->ahir_Version = 6;

	if( OpenDevice( AHINAME, AHI_NO_UNIT, (struct IORequest *) io, 0 )
	    == 0 ) {
	  AHIBase = (struct Library *) io->ahir_Std.io_Device;

	  rc = PlaySineEverywhere();

	  CloseDevice( (struct IORequest *) io );
	}
	else {
	  fprintf( stderr, "Unable to open '" AHINAME "' version 6.\n" );
	  rc = RETURN_FAIL;
	}
	
	DeleteIORequest( (struct IORequest *) io );
      }
      else {
	fprintf( stderr, "Unable to create IO request.\n" );
	rc = RETURN_FAIL;
      }

      DeleteMsgPort( mp );
    }
    else {
      fprintf( stderr, "Unable to create message port.\n" );
      rc = RETURN_FAIL;
    }
  }
  
  return rc;
}
Beispiel #19
0
static void cleanup(char *msg, ULONG retcode)
{
    if (msg && !args[ARG_QUIET]) 
    {
    	fprintf(stderr, "CopyToPAR: %s\n", msg);
    }
    
    if (fh) Close(fh);
    if (myargs) FreeArgs(myargs);
    
    if (ParOpen) CloseDevice((struct IORequest *)ParIO);
    if (ParIO) DeleteIORequest((struct IORequest *)ParIO);
    if (ParMP) DeleteMsgPort(ParMP);
    
    exit(retcode);
}
int
main(int argc, char* argv[]) {
  int rc = RETURN_OK;

  if (argc != 4) {
    fprintf(stderr, "Usage: %s <audio mode id> <mix_freq> <player_freq>\n", argv[0]);
    rc = RETURN_ERROR;
  }
  else {
    struct MsgPort* mp = CreateMsgPort();
    
    if (mp != NULL) {
      struct AHIRequest* io = (struct AHIRequest *)
	CreateIORequest(mp, sizeof(struct AHIRequest));

      if (io != NULL) {
	io->ahir_Version = 4;

	if (OpenDevice(AHINAME, AHI_NO_UNIT, (struct IORequest *) io, 0) == 0) {
	  AHIBase = (struct Library *) io->ahir_Std.io_Device;

	  rc = MaxPlaySamples(atol(argv[1]), atol(argv[2]), atol(argv[3]));

	  CloseDevice((struct IORequest *) io);
	}
	else {
	  fprintf(stderr, "Unable to open '" AHINAME "' version 4.\n");
	  rc = RETURN_FAIL;
	}
	
	DeleteIORequest((struct IORequest *) io);
      }
      else {
	fprintf(stderr, "Unable to create IO request.\n");
	rc = RETURN_FAIL;
      }

      DeleteMsgPort(mp);
    }
    else {
      fprintf(stderr, "Unable to create message port.\n");
      rc = RETURN_FAIL;
    }
  }
  
  return rc;
}
Beispiel #21
0
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;
  }
}
Beispiel #22
0
struct IORequest *ata_OpenTimer()
{
    struct MsgPort *p = CreateMsgPort();
    if (NULL != p)
    {
	struct IORequest *io = CreateIORequest(p, sizeof(struct timerequest));

	if (NULL != io)
	{
	    /*
	     * ok. ECLOCK does not have too great resolution, either.
	     * we will have to sacrifice our performance a little bit, meaning, the 400ns will turn into (worst case) 2us.
	     * hopefully we won't have to call that TOO often...
	     */
	    if (0 == OpenDevice("timer.device", UNIT_MICROHZ, io, 0))	
	    {
		if (0 == TimerBase)
		{
		    TimerBase = io->io_Device;
		    ata_Calibrate(io);
		}
		return io;
	    }
	    else
	    {
		bug("[ATA  ] Failed to open timer.device, unit MICROHZ\n");
	    }
	    DeleteIORequest(io);
	}
	else
	{
	    bug("[ATA  ] Failed to create timerequest\n");
	}
	DeleteMsgPort(p);
    }
    else
    {
	bug("[ATA  ] Failed to create timer port\n");
    }

    return NULL;
}
Beispiel #23
0
void SCSIExit(void)
{
	// Close all devices
	for (int i=0; i<8; i++)
		for (int j=0; j<8; j++) {
			struct IOStdReq *io = ios[i*8+j];
			if (io) {
				CloseDevice((struct IORequest *)io);
				DeleteIORequest(io);
			}
		}

	// Delete port and buffers
	if (the_port)
		DeleteMsgPort(the_port);
	if (buffer)
		FreeMem(buffer, buffer_size);
	if (sense_buffer)
		FreeMem(sense_buffer, SENSE_LENGTH);
}
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;
}
Beispiel #25
0
static void Sleep(u_long micros)
{
    struct MsgPort *TimerPort;
    struct timerequest *TimerRequest;

    if ((TimerPort = CreateMsgPort())) {
	if ((TimerRequest = CreateIORequest(TimerPort,
					    sizeof(struct timerequest)))) {
	    if (!OpenDevice("timer.device", UNIT_VBLANK,
			    (struct IORequest *)TimerRequest, 0)) {
		TimerRequest->io_Command = TR_ADDREQUEST;
		TimerRequest->io_Flags = IOF_QUICK;
		TimerRequest->tv_secs = micros/1000000;
		TimerRequest->tv_micro = micros%1000000;
		DoIO((struct IORequest *)TimerRequest);
		CloseDevice((struct IORequest *)TimerRequest);
	    }
	    DeleteIORequest(TimerRequest);
	}
	DeleteMsgPort(TimerPort);
    }
}
Beispiel #26
0
// Close a disk
void LIBFUNC L_CloseDisk(REG(a0, DiskHandle *handle))
{
    if (handle)
    {
        // IO request?
        if (handle->dh_io)
        {
            // Device open?
            if (handle->dh_io->iotd_Req.io_Device)
                CloseDevice((struct IORequest *)handle->dh_io);

            // Delete IO request
            DeleteIORequest((struct IORequest *)handle->dh_io);

            // Delete message port
            if (handle->dh_port) DeleteMsgPort(handle->dh_port);
        }

        // Free handle
        FreeVec(handle);
    }
}
Beispiel #27
0
static int load_capslib (void)
{
    if ((CAPS_MsgPort = CreateMsgPort ())) {
	if ((CAPS_IOReq = CreateIORequest (CAPS_MsgPort, sizeof(struct IORequest)))) {
	    if (!OpenDevice(CAPS_NAME, 0, CAPS_IOReq, 0)) {
		CapsImageBase = CAPS_IOReq->io_Device;
		if (CapsImageBase->dd_Library.lib_Version >= 2) {
		    if (CAPSInit () == imgeOk) {
			atexit (unload_capslib);
			return 1;
		    }
		} else
		    write_log ("CAPS: Please install capsimage.device version 2 or newer.\n");

		CloseDevice (CAPS_IOReq);
	    }
	    DeleteIORequest (CAPS_IOReq);
	}
	DeleteMsgPort (CAPS_MsgPort);
    }
    return 0;
}
Beispiel #28
0
LONG InitTimer(void)
{
    LONG err = ERROR_NO_FREE_STORE;

    glob->timerport = CreateMsgPort();
    if (glob->timerport) {
        glob->timereq = (struct timerequest *)CreateIORequest(glob->timerport,
            sizeof(struct timerequest));
        if (glob->timereq) {
            if (OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *)glob->timereq, 0))
            err = ERROR_DEVICE_NOT_MOUNTED;
        else {
            glob->timer_active = 0;
            glob->restart_timer = 1;
            D(bug("[fat] Timer ready\n"));
            return 0;
        }
        DeleteIORequest((struct IORequest *)glob->timereq);
    }
    DeleteMsgPort(glob->timerport);
    }
    return err;
}
Beispiel #29
0
/************************** I/O ******************************************/
struct IOExtTD *openDevice
	(
		struct AFSBase *afsbase,
		struct MsgPort *mp,
		STRPTR device,
		ULONG unit,
		ULONG flags
	)
{
struct IOExtTD *ioreq;

	ioreq = (struct IOExtTD *)CreateIORequest(mp, sizeof(struct IOExtTD));
	if (ioreq != NULL)
	{
		if (OpenDevice(device, unit, (struct IORequest *)ioreq, flags) == 0)
		{
			return ioreq;
		}
		else
			showError(afsbase, ERR_DEVICE, device);
		DeleteIORequest((struct IORequest *)ioreq);
	}
	return NULL;
}
Beispiel #30
0
__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);
}