/*
 * ASYN Int32 driver for simple FPGA application
 */
#include <epicsStdio.h>
#include <epicsExport.h>
#include <cantProceed.h>

#include <asynDriver.h>
#include <asynInt32.h>
#include <devLib.h>

#include "SOPC.h"   /* Symbolic link to SOPC-generated system header file */

#define AVALON_BASE  0x30000000   /* Base of Avalon space in ColdFire space */
#define OPTR ((epicsUInt8 *)(AVALON_BASE+PIO_0_BASE+1))

/*
 * Driver private storage
 */
typedef struct drvPvt {
    asynInterface common;
    asynInterface int32;
    volatile epicsUInt8 *optr;
} drvPvt;

/*
 * asynCommon methods
 */
static void
report(void *pvt, FILE *fp, int details)
{
}

static asynStatus
connect(void *pvt, asynUser *pasynUser)
{
    pasynManager->exceptionConnect(pasynUser);
    return asynSuccess;
}

static asynStatus
disconnect(void *pvt, asynUser *pasynUser)
{
    pasynManager->exceptionDisconnect(pasynUser);
    return asynSuccess;
}
static asynCommon commonMethods = { report, connect, disconnect };

/*
 * asynInt32 methods
 */
static asynStatus
int32Write(void *pvt, asynUser *pasynUser, epicsInt32 value)
{
    drvPvt *pdrvPvt = (drvPvt *)pvt;

    *pdrvPvt->optr = value;
    return asynSuccess;
}
static asynInt32 int32Methods = { int32Write };

/*
 * Register ourself with ASYN
 */
static void ledDriverDeviceSupportRegistrar(void)
{
    drvPvt *pdrvPvt;
    asynStatus status;
    const char *portName = "ledDriver";
    epicsUInt8 dummy = 0;

    pdrvPvt = callocMustSucceed(sizeof(drvPvt), 1, "ledDriver");

    pdrvPvt->optr = OPTR;
    if (devWriteProbe(sizeof(dummy), pdrvPvt->optr, &dummy) != 0){
        printf("ledDriver: memory probe failed\n");
        return;
    }

    status = pasynManager->registerPort(portName, 0, 1, 0, 0);
    if(status != asynSuccess) {
        printf("registerDriver failed\n");
        return;
    }

    pdrvPvt->common.interfaceType = asynCommonType;
    pdrvPvt->common.pinterface  = &commonMethods;
    pdrvPvt->common.drvPvt = pdrvPvt;
    status = pasynManager->registerInterface(portName, &pdrvPvt->common);
    if (status != asynSuccess) {
        printf("registerInterface failed\n");
        return;
    }

    pdrvPvt->int32.interfaceType = asynInt32Type;
    pdrvPvt->int32.pinterface  = &int32Methods;
    pdrvPvt->int32.drvPvt = pdrvPvt;
    status = pasynInt32Base->initialize(portName, &pdrvPvt->int32);
    if (status != asynSuccess) {
        printf("pasynInt32Base initialize failed\n");
        return;
    }
}
epicsExportRegistrar(ledDriverDeviceSupportRegistrar);
