leofunc.c 9.74 KB
/*
 *  F i l e N a m e : l e o f u n c . c
 *
 ****************************************************************************
 *                   (C) Copyright ALPS Electric Co., Ltd. 1995-1996
 ****************************************************************************
 * Version:
 *
 *   ver     Date
 *   ----  --------
 *   1.10  '97-02-20   Rename leoReset() to LeoReset().
 *                     Add __leoSetReset(), LeoResetClear().
 *   1.09  '96-12-24   Add "#ifdef _LONGCMD" for long command.
 *   1.08  '96-11-05   Add new leoReset() function.
 *   1.07  '96-11-05   Change leoInitialize() argment command que size & address .
 *   1.06  '96-10-01   Change LEOdma_que_buf size (1->2) .
 *   1.05  '96-09-17   Delete leoReset() function .
 *   1.04  '96-08-01   Move ram initialize to leocmdex.c.
 *   1.03  '96-07-03   Debug country_code in leoInitialize() .
 *   1.02  '96-06-17   Debug leoInitialize() .
 *                     Add country_code argment in leoInitialize() .
 *   1.01  '96-02-27   Rename leocom.c to leofunc.c
 *   1.00  '95-12-17   Initial Revision.
 ****************************************************************************
 */

#include <ultra64.h>
#include "osint.h"
#include "leodefine.h"
#include "leodrive.h"
#include "leomacro.h"
#include "leoappli.h"
#ifdef _LONGCMD
#include "leospappli.h"
#endif

/**************************************
*  PROTOTYPE DEFINITION
**************************************/
void leoInitialize(OSPri compri, OSPri intpri, OSMesg *command_que_buf, u32 cmd_buff_size);
void leoCommand(void *cmd_blk_addr);
void leoReset(void);

/**************************************
*  EXTERNALY DEFINITION FUNCTIONS
**************************************/
extern  void leomain(void *arg);
extern  void leointerrupt(void *arg);
extern  void leoClr_queue(void);
extern  void leoDrive_reset(void);
extern  u32  leoRetUnit_atten(void);
extern  void leoClrUA_RESET(void);

/**************************************
*  EXTERNALY DEFINITION RAM LOCATIONS
**************************************/
extern  OSThread LEOcommandThread;
extern  OSThread LEOinterruptThread;
extern  u64      LEOcommandThreadStack[LEO_STACKSIZE/8];
extern  u64      LEOinterruptThreadStack[LEO_STACKSIZE/8];

extern OSMesgQueue LEOcommand_que;
extern OSMesgQueue LEOevent_que;
extern OSMesgQueue LEOcontrol_que;
extern OSMesgQueue LEOblock_que;
extern OSMesgQueue LEOdma_que;
static OSMesgQueue LEOpost_que;

extern OSMesg LEOevent_que_buf;
extern OSMesg LEOcontrol_que_buf;
extern OSMesg LEOblock_que_buf;
extern OSMesg LEOdma_que_buf[DMA_Q_SIZE];
static OSMesg LEOpost_que_buf;

extern volatile u8  LEOclr_que_flag;

/**************************************
*  Macro
**************************************/
#define command_block   ((LEOCmdHeader *)cmd_blk_addr)

u32	__leoResetCalled = 0;
u32	__leoQueuesCreated = 0;

#ifndef MAX
#define MAX(a, b)	((a) > (b) ? (a) : (b))
#endif

/* ==========================================================================
* Function : leoInitialize
* --------------------------------------------------------------------------
* Description : Initialize leo driver software
* --------------------------------------------------------------------------
* IN        : non
* OUT       : non
* ARG       : compri, intpri                 : thread priority
*           : command_que_buf, cmd_buff_size : for command que
* RET       : non
* ==========================================================================
*/
void leoInitialize(OSPri compri, OSPri intpri, OSMesg *command_que_buf, u32 cmd_buff_size)
{
    u32         savedMask;
    OSPri       oldPri, myPri, pri;

    pri = MAX(compri, intpri);
        
    oldPri = -1;
    myPri = osGetThreadPri((OSThread *)NULL);
    if (myPri < pri) {
        oldPri = myPri;
        osSetThreadPri(NULL, pri);
    }

    savedMask = __osDisableInt();
    
    __leoQueuesCreated = 1;
    
    /* MAKE QUEUE */
    osCreateMesgQueue(COMMAND_QUE, &command_que_buf[0], cmd_buff_size);
    osCreateMesgQueue(CONTROL_QUE, &LEOcontrol_que_buf, CONTROL_Q_SIZE);
    osCreateMesgQueue(EVENT_QUE,   &LEOevent_que_buf,   EVENT_Q_SIZE);
    osCreateMesgQueue(DMA_QUE,     &LEOdma_que_buf[0],  DMA_Q_SIZE);
    osCreateMesgQueue(BLOCK_QUE,   &LEOblock_que_buf,   BLOCK_Q_SIZE);
    osCreateMesgQueue(&LEOpost_que,&LEOpost_que_buf,    1);

    /* MAKE COMMAND THREAD AND START  */
    osCreateThread(&LEOcommandThread, 1, leomain, (void *)0,
		   (void *)(LEOcommandThreadStack + LEO_STACKSIZE/8), compri);
    osStartThread(&LEOcommandThread);
    /* MAKE INTERRUPT HANDLING THREAD AND START      */
    osCreateThread(&LEOinterruptThread, 1, leointerrupt, (void *)0,
		   (void *)(LEOinterruptThreadStack + LEO_STACKSIZE/8), intpri);
    osStartThread(&LEOinterruptThread);

    /* SET EVENT INTERRUPT  */
    osSetEventMesg(OS_EVENT_CART, EVENT_QUE, MES_INTERRUPT);

    /*  SETUP BLOCK QUE  */
    osSendMesg(BLOCK_QUE, MES_NONE, OS_MESG_NOBLOCK);

    __osRestoreInt(savedMask);


    /* Restore original thread priority */
    if (oldPri != -1)
        osSetThreadPri(NULL, oldPri);

}

/*===========================================================================
* FUNCTION  :  leoCommand(cmd_blk_addr)
* ---------------------------------------------------------------------------
* DESCRIPTION :  RECIEVE COMMAND FROM APPLICATION.
* IN   :  NON
* OUT  :  NON
* ARG  :  cmd_blk_addr .. command block top address
* RET  :  NON
* =========================================================================*/
void leoCommand(void *cmd_blk_addr)
{
    if (__leoResetCalled)
    {
	command_block->status = LEO_STATUS_CHECK_CONDITION;
	command_block->sense = LEO_SENSE_WAITING_NMI;
	if (command_block->control & LEO_CONTROL_POST)
	{
	    /* send post message */
	    osSendMesg(command_block->post, (OSMesg)LEO_SENSE_WAITING_NMI,
		       OS_MESG_BLOCK);
	}

	return;
	
    }
    
    (void)osRecvMesg(BLOCK_QUE, NULL, OS_MESG_BLOCK);

    /*  Indicate BUSY  */
    command_block->status = LEO_STATUS_BUSY;
    command_block->sense  = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;

    switch (command_block->command)
    {
        case LEO_COMMAND_CLEAR_QUE:
            leoSet_clr_que_flag();
            leoClr_queue();
            leoClr_clr_que_flag();
            command_block->status = LEO_STATUS_GOOD;
            if (command_block->control & LEO_CONTROL_POST)
            {
                /* send post message */
                osSendMesg(command_block->post, (OSMesg)LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION, OS_MESG_BLOCK);
            }
            break;
        case LEO_COMMAND_READ:
        case LEO_COMMAND_WRITE:
#ifdef _LONGCMD
        case LEO_COMMAND_READ_LONG:
        case LEO_COMMAND_WRITE_LONG:
        case LEO_COMMAND_READ_SECTOR:
#endif
            /* Clear read/write bytes */
            ((LEOCmdRead *)(cmd_blk_addr))->rw_bytes = 0x00000000L;
            goto cmd_queing;
        default:
            if ((u32)(command_block->command-1) >= (u32)(LEO_CMD_NUM-1))
            {
                command_block->sense  = LEO_SENSE_INVALID_COMMAND_OPERATION_CODE;
                command_block->status = LEO_STATUS_CHECK_CONDITION;
                break;
            }
cmd_queing:
            if (osSendMesg(COMMAND_QUE, cmd_blk_addr, OS_MESG_NOBLOCK))
            {
                /* Que full */
                command_block->sense  = LEO_SENSE_QUEUE_FULL;
                command_block->status = LEO_STATUS_CHECK_CONDITION;
            }
    }

    osSendMesg(BLOCK_QUE, MES_NONE, OS_MESG_BLOCK);
}


/* ==========================================================================
* Function : LeoReset
* --------------------------------------------------------------------------
* Description : Stop device driver and Reset drive.
* --------------------------------------------------------------------------
* IN    : NON
* OUT   : NON
* ARG   : NON
* OUT   : NON
* ==========================================================================
*/
static const u8 zero[1]={0};
void LeoReset(void)
{
    __leoResetCalled = 1;

    if(__leoQueuesCreated)
    {
	/*
	 * BLOCK_QUE からメッセージをとるようなことはしない。
	 * かわりに、__leoResetCalled を見て、エラー37を返してくれる。
	 */

	/* Clear queued command */
	leoSet_clr_que_flag();
	leoClr_queue();
	leoClr_clr_que_flag();

	(void)osRecvMesg(EVENT_QUE, NULL, OS_MESG_NOBLOCK);
	(void)osSendMesg(EVENT_QUE, (OSMesg)MES_NMI_RESET, OS_MESG_BLOCK);
	(void)osSendMesg(COMMAND_QUE, (OSMesg)zero , OS_MESG_BLOCK);
    }
    
}

/* ==========================================================================
* Function : __leoSetReset
* --------------------------------------------------------------------------
* Description : Reset drive.
* --------------------------------------------------------------------------
* IN    : NON
* OUT   : NON
* ARG   : NON
* OUT   : NON
* ==========================================================================
*/
s32 __leoSetReset(void)
{
    leoDrive_reset();
    return 0;
}
/* ==========================================================================
* Function : LeoResetClear
* --------------------------------------------------------------------------
* Description : Clear UA reset condition.
* --------------------------------------------------------------------------
* IN    : NON
* OUT   : NON
* ARG   : NON
* OUT   : NON
* ==========================================================================
*/
s32 LeoResetClear(void)
{
    LEOCmdHeader resetclear;
    resetclear.command = LEO_COMMAND_RESETCLEAR;
    resetclear.control = LEO_CONTROL_POST;
    resetclear.status  = LEO_STATUS_GOOD;
    resetclear.post    = &LEOpost_que;
    if (osSendMesg(COMMAND_QUE, (OSMesg)&resetclear, OS_MESG_NOBLOCK))
    {
        /* Que full */
        return LEO_SENSE_QUEUE_FULL;
    }
    (void)osRecvMesg(&LEOpost_que, NULL, OS_MESG_BLOCK);
    if (resetclear.status == LEO_STATUS_GOOD)
        return LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;
    return resetclear.sense;
}