fresh commit
This commit is contained in:
commit
e68c1ec8c6
20 files changed
+5802
No files matched your search
+651
@@ -0,0 +1,651 @@
|
||||
/*
|
||||
|
||||
File: device.c
|
||||
Author: Neil Cafferkey
|
||||
Copyright (C) 2000-2010 Neil Cafferkey
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <exec/types.h>
|
||||
#include <exec/resident.h>
|
||||
#include <exec/errors.h>
|
||||
#include <utility/utility.h>
|
||||
#include "initializers.h"
|
||||
|
||||
#include <proto/exec.h>
|
||||
#include <proto/alib.h>
|
||||
#include <proto/utility.h>
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include "unit_protos.h"
|
||||
#include "request_protos.h"
|
||||
|
||||
#define VERSION 1
|
||||
#define REVISION 5
|
||||
#define UNIT_COUNT 1
|
||||
#define UTILITY_VERSION 36
|
||||
#define PCCARD_VERSION 1
|
||||
|
||||
|
||||
/* Private prototypes */
|
||||
|
||||
static struct DevBase *DevInit(struct DevBase *dev_base REG("d0"),
|
||||
APTR seg_list REG("a0"),struct DevBase *base REG(BASE_REG));
|
||||
static BYTE DevOpen(ULONG unit_no REG("d0"),
|
||||
struct IOSana2Req *request REG("a1"),ULONG flags REG("d1"),
|
||||
struct DevBase *base REG(BASE_REG));
|
||||
static APTR DevClose(struct IOSana2Req *request REG("a1"),
|
||||
struct DevBase *base REG(BASE_REG));
|
||||
static APTR DevExpunge(struct DevBase *base REG(BASE_REG));
|
||||
static APTR DevReserved();
|
||||
static VOID DevBeginIO(struct IOSana2Req *request REG("a1"),
|
||||
struct DevBase *base REG(BASE_REG));
|
||||
static VOID DevAbortIO(struct IOSana2Req *request REG("a1"),
|
||||
struct DevBase *base REG(BASE_REG));
|
||||
VOID DeleteDevice(struct DevBase *base);
|
||||
|
||||
extern const APTR vectors[];
|
||||
extern const APTR init_table[];
|
||||
|
||||
|
||||
/* Return an error immediately if someone tries to run the device */
|
||||
|
||||
LONG Main()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define DEVICE_NAME "3c589.device"
|
||||
|
||||
const TEXT device_name[]=DEVICE_NAME;
|
||||
static const TEXT version_string[]=DEVICE_NAME " 1.5 (3.2.2010)\n";
|
||||
static const TEXT card_name[]=CARDRESNAME;
|
||||
static const TEXT utility_name[]=UTILITYNAME;
|
||||
static const TEXT pccard_name[]=PCCARDNAME;
|
||||
static const TEXT timer_name[]=TIMERNAME;
|
||||
|
||||
|
||||
const struct Resident device_rom_tag=
|
||||
{
|
||||
RTC_MATCHWORD,
|
||||
(struct Resident *)&device_rom_tag,
|
||||
(APTR)init_table,
|
||||
RTF_AUTOINIT,
|
||||
VERSION,
|
||||
NT_DEVICE,
|
||||
0,
|
||||
(STRPTR)device_name,
|
||||
(STRPTR)version_string,
|
||||
(APTR)init_table
|
||||
};
|
||||
|
||||
|
||||
static const APTR vectors[]=
|
||||
{
|
||||
(APTR)DevOpen,
|
||||
(APTR)DevClose,
|
||||
(APTR)DevExpunge,
|
||||
(APTR)DevReserved,
|
||||
(APTR)DevBeginIO,
|
||||
(APTR)DevAbortIO,
|
||||
(APTR)-1
|
||||
};
|
||||
|
||||
|
||||
static const struct
|
||||
{
|
||||
SMALLINITBYTEDEF(type);
|
||||
SMALLINITPINTDEF(name);
|
||||
SMALLINITBYTEDEF(flags);
|
||||
SMALLINITWORDDEF(version);
|
||||
SMALLINITWORDDEF(revision);
|
||||
SMALLINITPINTDEF(id_string);
|
||||
INITENDDEF;
|
||||
}
|
||||
init_data=
|
||||
{
|
||||
SMALLINITBYTE(OFFSET(Node,ln_Type),NT_DEVICE),
|
||||
SMALLINITPINT(OFFSET(Node,ln_Name),device_name),
|
||||
SMALLINITBYTE(OFFSET(Library,lib_Flags),LIBF_SUMUSED|LIBF_CHANGED),
|
||||
SMALLINITWORD(OFFSET(Library,lib_Version),VERSION),
|
||||
SMALLINITWORD(OFFSET(Library,lib_Revision),REVISION),
|
||||
SMALLINITPINT(OFFSET(Library,lib_IdString),version_string),
|
||||
INITEND
|
||||
};
|
||||
|
||||
|
||||
static const APTR init_table[]=
|
||||
{
|
||||
(APTR)sizeof(struct DevBase),
|
||||
(APTR)vectors,
|
||||
(APTR)&init_data,
|
||||
(APTR)DevInit
|
||||
};
|
||||
|
||||
|
||||
static const ULONG rx_tags[]=
|
||||
{
|
||||
S2_CopyToBuff,
|
||||
S2_CopyToBuff16
|
||||
};
|
||||
|
||||
|
||||
static const ULONG tx_tags[]=
|
||||
{
|
||||
S2_CopyFromBuff,
|
||||
S2_CopyFromBuff16,
|
||||
S2_CopyFromBuff32
|
||||
};
|
||||
|
||||
|
||||
|
||||
/****i* 3c589.device/DevInit ***********************************************
|
||||
*
|
||||
* NAME
|
||||
* DevInit -- .
|
||||
*
|
||||
* SYNOPSIS
|
||||
* dev_base = DevInit(dev_base,seg_list)
|
||||
*
|
||||
* struct DevBase *DevInit(struct DevBase *,APTR);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
* EXAMPLE
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
* SEE ALSO
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
*/
|
||||
|
||||
static struct DevBase *DevInit(struct DevBase *dev_base REG("d0"),
|
||||
APTR seg_list REG("a0"),struct DevBase *base REG(BASE_REG))
|
||||
{
|
||||
BOOL success=TRUE;
|
||||
|
||||
dev_base->sys_base=(APTR)base;
|
||||
base=dev_base;
|
||||
base->seg_list=seg_list;
|
||||
|
||||
base->card_base=OpenResource(card_name);
|
||||
base->utility_base=(APTR)OpenLibrary(utility_name,UTILITY_VERSION);
|
||||
base->pccard_base=OpenLibrary(pccard_name,PCCARD_VERSION);
|
||||
if((base->card_base==NULL)||(base->utility_base==NULL)||
|
||||
(base->pccard_base==NULL))
|
||||
success=FALSE;
|
||||
|
||||
if(OpenDevice(timer_name,UNIT_VBLANK,(APTR)&base->timer_request,0)!=0)
|
||||
success=FALSE;
|
||||
|
||||
NewList((APTR)(&dev_base->units));
|
||||
|
||||
if(!success)
|
||||
{
|
||||
DeleteDevice(base);
|
||||
base=NULL;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****i* 3c589.device/DevOpen ***********************************************
|
||||
*
|
||||
* NAME
|
||||
* DevOpen -- .
|
||||
*
|
||||
* SYNOPSIS
|
||||
* error = DevOpen(unit_num,request,flags)
|
||||
*
|
||||
* BYTE DevOpen(ULONG,struct IOSana2Req *,ULONG);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
* EXAMPLE
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
* SEE ALSO
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
*/
|
||||
|
||||
static BYTE DevOpen(ULONG unit_num REG("d0"),
|
||||
struct IOSana2Req *request REG("a1"),ULONG flags REG("d1"),
|
||||
struct DevBase *base REG(BASE_REG))
|
||||
{
|
||||
struct DevUnit *unit;
|
||||
BYTE error=0;
|
||||
struct Opener *opener;
|
||||
struct TagItem *tag_list;
|
||||
UWORD i;
|
||||
|
||||
base->device.dd_Library.lib_OpenCnt++;
|
||||
base->device.dd_Library.lib_Flags&=~LIBF_DELEXP;
|
||||
|
||||
request->ios2_Req.io_Unit=NULL;
|
||||
tag_list=request->ios2_BufferManagement;
|
||||
request->ios2_BufferManagement=NULL;
|
||||
|
||||
/* Check request size and unit number */
|
||||
|
||||
if((request->ios2_Req.io_Message.mn_Length<sizeof(struct IOSana2Req))
|
||||
||(unit_num>=UNIT_COUNT))
|
||||
error=IOERR_OPENFAIL;
|
||||
|
||||
/* Get the requested unit */
|
||||
|
||||
if(error==0)
|
||||
{
|
||||
request->ios2_Req.io_Unit=(APTR)unit=GetUnit(unit_num,base);
|
||||
if(unit==NULL)
|
||||
error=IOERR_OPENFAIL;
|
||||
}
|
||||
|
||||
/* Handle device sharing */
|
||||
|
||||
if(error==0)
|
||||
{
|
||||
if((unit->open_count!=0)&&(((unit->flags&UNITF_SHARED)==0)||
|
||||
((flags&SANA2OPF_MINE)!=0)))
|
||||
error=IOERR_UNITBUSY;
|
||||
unit->open_count++;
|
||||
}
|
||||
|
||||
if(error==0)
|
||||
{
|
||||
if((flags&SANA2OPF_MINE)==0)
|
||||
unit->flags|=UNITF_SHARED;
|
||||
else if((flags&SANA2OPF_PROM)!=0)
|
||||
unit->flags|=UNITF_PROM;
|
||||
|
||||
/* Set up buffer-management structure and get hooks */
|
||||
|
||||
request->ios2_BufferManagement=opener=
|
||||
AllocVec(sizeof(struct Opener),MEMF_PUBLIC);
|
||||
if(opener==NULL)
|
||||
error=IOERR_OPENFAIL;
|
||||
}
|
||||
|
||||
if(error==0)
|
||||
{
|
||||
NewList(&opener->read_port.mp_MsgList);
|
||||
opener->read_port.mp_Flags=PA_IGNORE;
|
||||
NewList((APTR)&opener->initial_stats);
|
||||
|
||||
for(i=0;i<2;i++)
|
||||
opener->rx_function=(APTR)GetTagData(rx_tags[i],
|
||||
(UPINT)opener->rx_function,tag_list);
|
||||
for(i=0;i<3;i++)
|
||||
opener->tx_function=(APTR)GetTagData(tx_tags[i],
|
||||
(UPINT)opener->tx_function,tag_list);
|
||||
|
||||
opener->filter_hook=(APTR)GetTagData(S2_PacketFilter,NULL,tag_list);
|
||||
opener->dma_tx_function=
|
||||
(APTR)GetTagData(S2_DMACopyFromBuff32,NULL,tag_list);
|
||||
|
||||
Disable();
|
||||
AddTail((APTR)&unit->openers,(APTR)opener);
|
||||
Enable();
|
||||
}
|
||||
|
||||
/* Back out if anything went wrong */
|
||||
|
||||
if(error!=0)
|
||||
DevClose(request,base);
|
||||
|
||||
/* Return */
|
||||
|
||||
request->ios2_Req.io_Error=error;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****i* 3c589.device/DevClose **********************************************
|
||||
*
|
||||
* NAME
|
||||
* DevClose -- .
|
||||
*
|
||||
* SYNOPSIS
|
||||
* seg_list = DevClose(request)
|
||||
*
|
||||
* APTR DevClose(struct IOSana2Req *);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
* EXAMPLE
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
* SEE ALSO
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
*/
|
||||
|
||||
static APTR DevClose(struct IOSana2Req *request REG("a1"),
|
||||
struct DevBase *base REG(BASE_REG))
|
||||
{
|
||||
struct DevUnit *unit;
|
||||
APTR seg_list;
|
||||
struct Opener *opener;
|
||||
|
||||
/* Free buffer-management resources */
|
||||
|
||||
opener=(APTR)request->ios2_BufferManagement;
|
||||
if(opener!=NULL)
|
||||
{
|
||||
Disable();
|
||||
Remove((APTR)opener);
|
||||
Enable();
|
||||
FreeVec(opener);
|
||||
}
|
||||
|
||||
/* Delete the unit if it's no longer in use */
|
||||
|
||||
unit=(APTR)request->ios2_Req.io_Unit;
|
||||
if(unit!=NULL)
|
||||
{
|
||||
if((--unit->open_count)==0)
|
||||
{
|
||||
Remove((APTR)unit);
|
||||
DeleteUnit(unit,base);
|
||||
}
|
||||
}
|
||||
|
||||
/* Expunge the device if a delayed expunge is pending */
|
||||
|
||||
seg_list=NULL;
|
||||
|
||||
if((--base->device.dd_Library.lib_OpenCnt)==0)
|
||||
{
|
||||
if((base->device.dd_Library.lib_Flags&LIBF_DELEXP)!=0)
|
||||
seg_list=DevExpunge(base);
|
||||
}
|
||||
|
||||
return seg_list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****i* 3c589.device/DevExpunge ********************************************
|
||||
*
|
||||
* NAME
|
||||
* DevExpunge -- .
|
||||
*
|
||||
* SYNOPSIS
|
||||
* seg_list = DevExpunge()
|
||||
*
|
||||
* APTR DevExpunge(VOID);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
* EXAMPLE
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
* SEE ALSO
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
*/
|
||||
|
||||
static APTR DevExpunge(struct DevBase *base REG(BASE_REG))
|
||||
{
|
||||
APTR seg_list;
|
||||
|
||||
if(base->device.dd_Library.lib_OpenCnt==0)
|
||||
{
|
||||
seg_list=base->seg_list;
|
||||
Remove((APTR)base);
|
||||
DeleteDevice(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->device.dd_Library.lib_Flags|=LIBF_DELEXP;
|
||||
seg_list=NULL;
|
||||
}
|
||||
|
||||
return seg_list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****i* 3c589.device/DevReserved *******************************************
|
||||
*
|
||||
* NAME
|
||||
* DevReserved -- .
|
||||
*
|
||||
* SYNOPSIS
|
||||
* result = DevReserved()
|
||||
*
|
||||
* APTR DevReserved(VOID);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
* EXAMPLE
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
* SEE ALSO
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
*/
|
||||
|
||||
static APTR DevReserved()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****i* 3c589.device/DevBeginIO ********************************************
|
||||
*
|
||||
* NAME
|
||||
* DevBeginIO -- .
|
||||
*
|
||||
* SYNOPSIS
|
||||
* DevBeginIO(request)
|
||||
*
|
||||
* VOID DevBeginIO(struct IORequest *);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
* EXAMPLE
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
* SEE ALSO
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
*/
|
||||
|
||||
static VOID DevBeginIO(struct IOSana2Req *request REG("a1"),
|
||||
struct DevBase *base REG(BASE_REG))
|
||||
{
|
||||
struct DevUnit *unit;
|
||||
|
||||
request->ios2_Req.io_Error=0;
|
||||
unit=(APTR)request->ios2_Req.io_Unit;
|
||||
|
||||
if(AttemptSemaphore(&unit->access_lock))
|
||||
ServiceRequest(request,base);
|
||||
else
|
||||
{
|
||||
PutRequest(unit->request_ports[GENERAL_QUEUE],(APTR)request,base);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****i* 3c589.device/DevAbortIO ********************************************
|
||||
*
|
||||
* NAME
|
||||
* DevAbortIO -- Try to stop a request.
|
||||
*
|
||||
* SYNOPSIS
|
||||
* DevAbortIO(request)
|
||||
*
|
||||
* VOID DevAbortIO(struct IOSana2Req *);
|
||||
*
|
||||
* FUNCTION
|
||||
* Do our best to halt the progress of a request.
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
* EXAMPLE
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
* SEE ALSO
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* Disable() used instead of a semaphore because device uses interrupts.
|
||||
*
|
||||
*/
|
||||
|
||||
static VOID DevAbortIO(struct IOSana2Req *request REG("a1"),
|
||||
struct DevBase *base REG(BASE_REG))
|
||||
{
|
||||
struct DevUnit *unit;
|
||||
|
||||
unit=(APTR)request->ios2_Req.io_Unit;
|
||||
|
||||
Disable();
|
||||
if((request->ios2_Req.io_Message.mn_Node.ln_Type==NT_MESSAGE)
|
||||
&&((request->ios2_Req.io_Flags&IOF_QUICK)==0))
|
||||
{
|
||||
Remove((APTR)request);
|
||||
request->ios2_Req.io_Error=IOERR_ABORTED;
|
||||
request->ios2_WireError=S2WERR_GENERIC_ERROR;
|
||||
ReplyMsg((APTR)request);
|
||||
}
|
||||
Enable();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****i* 3c589.device/DeleteDevice ******************************************
|
||||
*
|
||||
* NAME
|
||||
* DeleteDevice -- .
|
||||
*
|
||||
* SYNOPSIS
|
||||
* DeleteDevice()
|
||||
*
|
||||
* VOID DeleteDevice(VOID);
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
* EXAMPLE
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
* SEE ALSO
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
*/
|
||||
|
||||
VOID DeleteDevice(struct DevBase *base)
|
||||
{
|
||||
UWORD neg_size,pos_size;
|
||||
|
||||
/* Close devices */
|
||||
|
||||
CloseDevice((APTR)&base->timer_request);
|
||||
|
||||
/* Close libraries */
|
||||
|
||||
if(base->pccard_base!=NULL)
|
||||
CloseLibrary(base->pccard_base);
|
||||
if(base->utility_base!=NULL)
|
||||
CloseLibrary((APTR)base->utility_base);
|
||||
|
||||
/* Free device's memory */
|
||||
|
||||
neg_size=base->device.dd_Library.lib_NegSize;
|
||||
pos_size=base->device.dd_Library.lib_PosSize;
|
||||
FreeMem((UBYTE *)base-neg_size,pos_size+neg_size);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user