leoread.c 6.33 KB
/*
 *  F i l e N a m e  :  l e o r e a d . c
 *
 ****************************************************************************
 *               (C) Copyright ALPS Electric Co., Ltd. 1995-1996
 ****************************************************************************
 *  Version
 *
 *  ver     Date
 *  ----  --------
 *  1.05  '97-01-10  Change sense code name to LEO_SENSE_ILLEGAL_SECTOR_SIZE.
 *  1.04  '96-12-24  Add "#ifdef _LONGCMD" for long command.
 *  1.03a '96-10-07  Enable system area read if SYSTEMWRITE is defined.
 *  1.03  '96-07-25  Change C2_correction complete message send interrupt_thread .
 *                   Delete leoChk_disk_err() .
 *  1.02  '96-07-20  Move track/retry ope to leoint.c
 *  1.01  '96-02-27  Rename file name read.c to leoread.c .
 *  1.00  '95-12-20  Initial revision .
 ****************************************************************************
*/
#include <ultra64.h>
#include "leodefine.h"
#include "leodrive.h"
#include "leomacro.h"
#include "leoappli.h"
#ifdef _LONGCMD
#include "leospappli.h"
#endif

/**************************************/
/* PROTOTYPE DEFINITIONS              */
/**************************************/
void leoRead(void);
void leoRead_common(unsigned int offset);

/**************************************/
/* EXTERNALY DEFINED FUNCTIONS        */
/**************************************/
extern int  leoC2_Correction(void);
#ifdef _LONGCMD
extern u16  leoLba_to_phys(u32 lba);
#endif

/**************************************/
/* RAM LOCATIONS                      */
/**************************************/

/**************************************/
/* EXTERNALY DEFINED RAM LOCATIONS    */
/**************************************/
extern OSThread    LEOinterruptThread;
extern OSMesg      LEOcur_command;
extern OSMesgQueue LEOcontrol_que;
extern OSMesgQueue LEOc2ctrl_que;

extern struct tgt_param_form   LEOtgt_param;
extern volatile u16 LEOrw_flags;

/*************************************/
/*  MACRO DEFINITIONS                */
/*************************************/
#define    read_command         ((LEOCmdRead *)LEOcur_command)
#ifdef _LONGCMD
#define    read_long_command    ((LEOCmdReadLong *)LEOcur_command)
#endif

#ifdef _LONGCMD
/**********************************************************
* Function : leoReadLong
* ---------------------------------------------------------
* Description : excute read long command
* IN  : LEOcur_command
* OUT : *LEOcur_command
**********************************************************/
void leoReadLong(void)
{
    if (read_long_command->header.control & 0x01)
        LEOrw_flags = LONG_RW;
    else
    {
        /* Check parameter */
        LEOrw_flags = FIXSIZE;
        leoLba_to_phys(read_long_command->lba);
        if ( (read_long_command->size & 7)
          || (read_long_command->size == 0)
          || (read_long_command->size > LEOtgt_param.sec_bytes) )
        {
            if (read_long_command->size == (LEOtgt_param.sec_bytes+8))
                LEOrw_flags = LONG_RW;
            else
            {
                read_long_command->header.sense  = LEO_SENSE_ILLEGAL_SECTOR_SIZE;
                read_long_command->header.status = LEO_STATUS_CHECK_CONDITION;
                return;
            }
        }
    }
    leoRead_common(SYSTEM_LBAS);
}
/**********************************************************
* Function : leoReadSector
* ---------------------------------------------------------
* Description : excute read sector command
* IN  : LEOcur_command
* OUT : *LEOcur_command
**********************************************************/
void leoReadSector(void)
{
    LEOrw_flags = SECTOR_READ;
    leoRead_common(SYSTEM_LBAS);
}
#endif

/**********************************************************
* Function : leoRead
* ---------------------------------------------------------
* Description : excute read command
* IN  : LEOcur_command
* OUT : *LEOcur_command
**********************************************************/
void leoRead(void)
{
    LEOrw_flags = 0;
    leoRead_common(SYSTEM_LBAS);
}

/**********************************************************
* Function : leoRead_common
* ---------------------------------------------------------
* Description : read
* IN  : LEOcur_command
* OUT : *LEOcur_command
* ARG : offset .... lba offset. set 0 if read system area
**********************************************************/
void leoRead_common(unsigned int offset)
{
    u32    tg_lba;
    u32    tg_blocks;
    u32    message;
    u16    retry_cnt;

    tg_lba    = read_command->lba;
    tg_blocks = read_command->xfer_blks;

#ifdef _LONGCMD
    tg_lba += offset;
    if ((tg_lba | tg_blocks) & 0xffff0000)
        goto invalid_lba;
#else
    if ((tg_lba | tg_blocks) & 0xffff0000)
        goto invalid_lba;
    tg_lba += offset;
#endif
    if ( (tg_lba+tg_blocks) > (MAX_P_LBA+1) )
    {
invalid_lba:
        read_command->header.sense  = LEO_SENSE_LBA_OUT_OF_RANGE;
        read_command->header.status = LEO_STATUS_CHECK_CONDITION;
        return;
    }
    if (tg_blocks == 0)
    {
        if (tg_lba > MAX_P_LBA)
            goto invalid_lba;
        read_command->header.sense  = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;
        read_command->header.status = LEO_STATUS_GOOD;
        return;
    }

    LEOtgt_param.lba = tg_lba;

    LEOrw_flags &= ~(LOCK_C2_PARAM+WRITE_MODE); /* clear C2 flag */

    osSendMesg(C2_CTRL_QUE, MES_NONE, OS_MESG_NOBLOCK);

    osStartThread(&LEOinterruptThread);

    for (;;)                 /* track read loop */
    {
        /* wait block read done */
        (void)osRecvMesg(CONTROL_QUE, (OSMesg*)&message, OS_MESG_BLOCK);
        switch (message)
        {
            case (u32)MES_RW_COMPLETE:
                    goto read_complete;
            case (u32)MES_REQ_C2_CORR:
                leoC2_Correction();
                LEOrw_flags &= ~LOCK_C2_PARAM;    /* clear flags to indicate new c2_param acceptable */
                osSendMesg(C2_CTRL_QUE, MES_NONE, OS_MESG_NOBLOCK);
                continue;
            default:
                /* error */
                read_command->header.sense  = message;
                read_command->header.status = LEO_STATUS_CHECK_CONDITION;
                return;                             /* stop command */
        }
    }
   /*
    * all block read complete
    */
read_complete:
    read_command->header.sense  = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;
    read_command->header.status = LEO_STATUS_GOOD;
}