iplleocmdex.c 13.8 KB
/*
 *  F i l e N a m e  :  i p l l e o c m d e x . c
 *
 ****************************************************************************
 *                   (C) Copyright ALPS Electric Co., Ltd. 1995-1996
 ****************************************************************************
 *  Version
 *
 *  ver     Data
 *  ----  --------
 *  1.16  '97-01-10  Add recal at system read retry.
 *  1.15  '96-12-24  Add leoiplReadTimer(),leoiplSetTimer() command.
 *  1.14  '96-11-22  Add _ERRCHK definition.
 *  1.13  '96-10-30  Add Check of CLR_QUEUE request .
 *  1.12  '96-09-20  Add leoiplReadDiskId command.
 *  1.12  '96-09-20  Change old format disk is "UNKNOWN FORMAT ERROR" .
 *  1.11  '96-09-10  Change LeoIPL_sys_data structure .
 *  1.10  '96-08-27  See LeoIPL_country_code to check system sector size to remove KAIHATU definition.
 *  1.09  '96-08-21  Load segment to address LeoIPL_sys_data.param.loadptr.
 *  1.08  '96-07-25  Change initialize for phase1.
 *  1.07  '96-07-08  LeoIPL_country_code change union.
 *  1.06  '96-07-03  Save LeoIPL_country_code for device driver .
 *  1.05  '96-06-24  Modefy Read Command control bit .
 *                   Deleted Timer Command .
 *  1.04  '96-06-17  Modefy LeoIPL_country_code handling and bad_ecc check .
 *  1.03  '96-05-08  Change System area read retrycntr    (40 -> MAX_RETRY)
 *                   Change Bad ECC Sector read retrycntr ( 5 -> MAX_RETRY)
 *  1.02  '96-02-27  Change file name from iplmain.c to iplleocmdex.c
 *                   Debug Bad ECC Sector read.
 *  1.01  '96-02-03  Debug.
 *  1.00  '95-12-20  Initial revision .
 ****************************************************************************
*/
#include "os.h"

#include <ultra64.h>
#include "leodefine.h"
#include "leodrive.h"
#include "iplleomacro.h"
#include "leoappli.h"

/*************************************/
/* PROTOTYPE DEFINITIONS             */
/*************************************/
void leoiplMain(void *arg);
u8   leoiplRead_system_area(void);
u8   leoiplRead_ipl(void);

/*************************************/
/* EXTERNAL FUNCTIONS                */
/*************************************/
extern  void leoiplRead_zone0(void);
extern  u8   leoiplReadDiskId(void);
extern  void leoiplReadTimer(void);
extern  void leoiplSetTimer(void);

extern  void leoIPLClr_queue(void);

/*************************************/
/* RAM DEFINITIONS                   */
/*************************************/
union data_trans_form  LeoIPL_country_code;

/*************************************/
/* EXTERNAL RAMS                     */
/*************************************/
extern union leo_sys_form LeoIPL_sys_data;
extern OSMesg LeoIPLcur_command;
extern OSMesgQueue LeoIPLcommand_que;
extern OSMesgQueue LeoIPLevent_que;
extern OSMesgQueue LeoIPLdma_que;
extern u8  LeoIPLdrive_flag;
extern volatile u8  LeoIPLclr_que_flag;
extern u8  LeoIPLdisk_type;
extern u16 LeoIPLrw_flags;
extern u32 LeoIPLasic_bm_ctl_shadow;
extern u32 LeoIPLasic_seq_ctl_shadow;

/*************************************/
/* LOCAL DEFINITIONS                 */
/*************************************/
/*-----------------------------------*/
/* IPL READ(05H) COMMAND STRUCTURE   */
/*-----------------------------------*/
struct ipl_read_cmd_form {
    LEOCmdHeader   header;
    u64           *buff_ptr;
    union data_trans_form     code;
};

static const u8 ipl_system_lba[4] = {
        SYS_DATA_LBA1,
        SYS_DATA_LBA2,
        SYS_DATA_LBA3,
        SYS_DATA_LBA4 };

/*----------------- NEW OS -------------------*/
OSPiHandle  *LeoIPLPiInfo;
OSIoMesg    LeoIPLPiDmaParam;

#define chk_cmd     ((LEOCmdHeader *)LeoIPLcur_command)

/* ==========================================================================
*  Function : leoiplMain
* --------------------------------------------------------------------------
*  Description : Excute command in command queue
* --------------------------------------------------------------------------
* IN  : commnad in commnad que
* OUT : LeoIPLcur_command
* ARG : Not used
* RET : non
* ==========================================================================
*/
void leoiplMain(void *arg)
{
    u32 sense;
    u32 postoffset;
    u32 cur_status;
    u8  ret;

    /* Initialize shadow ram */
    LeoIPLasic_seq_ctl_shadow = 0;
    LeoIPLasic_bm_ctl_shadow  = 0;

    /* Initialize flags */
    leoiplClr_sys_read();
    leoiplClr_clr_que_flag();

    /* set AD16-bus speed & base address */
    LeoIPLPiInfo = osLeoDiskInit();
    LeoIPLPiDmaParam.hdr.pri  = OS_MESG_PRI_HIGH;
    LeoIPLPiDmaParam.hdr.retQueue = IPLDMA_QUE;

    /* reset drive */
    leoiplDrive_reset();

    while (1)
    {
        /*  Get command from queue  */
        (void)osRecvMesg(IPLCOMMAND_QUE, (OSMesg)&LeoIPLcur_command, OS_MESG_BLOCK);

        /*----------------------------------*/
        /* command check                    */
        /*----------------------------------*/
        switch (chk_cmd->command)
        {
            case 0:
                leoiplDrive_reset();
(void)osRecvMesg(IPLEVENT_QUE, NULL, OS_MESG_NOBLOCK);
                continue;

            case LEO_COMMAND_TEST_UNIT_READY: 
                sense = leoiplChk_asic_ready(ASIC_RD_SEEK); /* Clear reset & disk_chg bits */
#ifdef _ERRCHK
                if (sense == LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION)                 
                    sense = chk_cmd->reserve1;
#endif
pre_cmd_err:
                if (chk_cmd->sense = sense)                 
                    chk_cmd->status = LEO_STATUS_CHECK_CONDITION;
                else
                    chk_cmd->status = LEO_STATUS_GOOD;
                break;

            case LEO_COMMAND_READ:
            case LEO_COMMAND_READ_DISK_ID:
                (void)leoiplChk_asic_ready(ASIC_RD_SEEK); /* Clear reset & disk_chg bits */
                /* check disk */
                leoiplGet_leo_status(&sense);
                if (!(sense & LEO_STAT_DISK))
                {
                    sense = LEO_SENSE_MEDIUM_NOT_PRESENT;
                    goto pre_cmd_err;
                }

                if (chk_cmd->command == LEO_COMMAND_READ)
                {
                    ret = leoiplRead_system_area();   /* read defect list and disk-type  */
                    if (ret == LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION)
                        ret = leoiplRead_ipl();
                }
                else
                {
                    ret = leoiplReadDiskId();
                }

                if (ret)
                {
                    if (!leoiplChk_err_retry(ret) )
                    {
                        if (ret = leoiplSend_asic_cmd_w(ASIC_SLEEP, 0))
                            chk_cmd->sense = ret;
                    }
                    chk_cmd->status = LEO_STATUS_CHECK_CONDITION;
                }
                else
                    chk_cmd->status = LEO_STATUS_GOOD;
                break;

            case LEO_COMMAND_READ_TIMER:
                (void)leoiplChk_asic_ready(ASIC_RD_SEEK); /* Clear reset & disk_chg bits */
                leoiplReadTimer();
                break;

            case LEO_COMMAND_SET_TIMER:
                (void)leoiplChk_asic_ready(ASIC_RD_SEEK); /* Clear reset & disk_chg bits */
                leoiplSetTimer();
                break;

            default:
                chk_cmd->sense  = LEO_SENSE_INVALID_COMMAND_OPERATION_CODE;
                chk_cmd->status = LEO_STATUS_CHECK_CONDITION;
                continue;
        }
        /* Post queue */
        if (chk_cmd->control & LEO_CONTROL_POST)
        {
            /* send sense code to post message */
            osSendMesg(chk_cmd->post, (OSMesg)(chk_cmd->sense), OS_MESG_BLOCK);
        }
        /* Check CLR_QUEUE request */
        if (leoiplChk_clr_que_flag())
            leoIPLClr_queue();
    }
}

/* ==========================================================================
* Function : leoiplRead_system_area
* --------------------------------------------------------------------------
* Description : Read system information 
*             : Hangup if copy protection function detect abnormal format.
* --------------------------------------------------------------------------
* IN    : non
* OUT   : non
* ARG   : non
* RET   : 00     - good
*       : not 00 - not good. error sense code is set.
* ==========================================================================
*/
const static LEOCmdRead system_read_cmd =
      { { LEO_COMMAND_READ,           /* COMMAND        */
          0x00,                       /* RESERVE        */
          0x00,                       /* CONTROL        */
          0x00,                       /* RESERVE        */
          0x00,                       /* STATUS         */
          0x00,                       /* SENSE          */
          0x00,                       /* RESERVE        */
          0x00,                       /* RESERVE        */
          NULL                        /* POST QUEUE     */
        },
          SYS_UNCORR_LBA,             /* LBA            */
          0x01,                       /* BLOCKS         */
          0x00,                       /* BUFFER POINTER */
          0x00                        /* READ BYTES     */
        };

u8 leoiplRead_system_area(void)
{
    LEOCmdRead dummy_cmd;
    struct ipl_read_cmd_form *backup_pointer;
    u32 read_mode;
    u32 retry_cntr;

    /* Backup current command */
    backup_pointer = (struct ipl_read_cmd_form*)LeoIPLcur_command;
    LeoIPL_country_code = backup_pointer->code;
    LeoIPLcur_command = &dummy_cmd;

    read_mode = 0;
    retry_cntr = 0;
    do
    {
        /* Set disk_type,defect number to 0 to use in lba_to_phys() routine */
        LeoIPLdisk_type = 0;
        LeoIPL_sys_data.param.defect_num[0] = 0;
        LeoIPLrw_flags = SECTOR_READ + NO_RETRY;
        dummy_cmd = system_read_cmd;
        dummy_cmd.buff_ptr = &LeoIPL_sys_data.u64_data[0];

        if (read_mode == 0)
        {
            /*************************/
            /* read BAD ECC sector   */
            /*************************/
            leoiplRead_zone0();
            switch (dummy_cmd.header.sense)
            {
                case LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION:
                    do {} while (LeoIPL_country_code.u32_data != 0);
                    break;
                case LEO_SENSE_UNRECOVERED_READ_ERROR:
                    do {} while (LeoIPL_country_code.u32_data == 0);
                    break;
                default:
                    goto system_retry;
            }
            read_mode--;
            retry_cntr = 0;
            continue;        
        }
        else
        {
            /*************************/
            /* read disk system data */
            /*************************/
            dummy_cmd.lba = ipl_system_lba[(retry_cntr & 0x03)];
            if (LeoIPL_country_code.u32_data == 0)
                dummy_cmd.lba += SYS_LBA_DEV_OFFSET;

            /* call read routine */
            leoiplRead_zone0();

            if (dummy_cmd.header.status == LEO_STATUS_GOOD)
            {
                /* compare country_code */
                do {} while (LeoIPL_sys_data.param.country != LeoIPL_country_code.u32_data);

                /* Check format type */
                switch (LeoIPL_sys_data.param.disk_type & (u8)0xf0)
                {
                    case 0x10:
                    case 0x20:
                    case 0x30:
                        break;
                    default:
                        dummy_cmd.header.sense = LEO_SENSE_INCOMPATIBLE_MEDIUM_INSTALLED;
                        goto sys_read_end;
                }

                /* Save country_code */
                *(u8*)OS_PHYSICAL_TO_K1(0x00000010) = LeoIPL_country_code.u8_data[0];
                *(u8*)OS_PHYSICAL_TO_K1(0x00000090) = LeoIPL_country_code.u8_data[1];
                *(u8*)OS_PHYSICAL_TO_K1(0x00000110) = LeoIPL_country_code.u8_data[2];
                *(u8*)OS_PHYSICAL_TO_K1(0x00000190) = LeoIPL_country_code.u8_data[3];
                goto sys_read_end;
            }
        }

system_retry:
        if (leoiplChk_err_retry(dummy_cmd.header.sense))
            break;
        if (retry_cntr++ >= MAX_RETRY)
            break;
        if (leoChk_recal(retry_cntr))
        {
            dummy_cmd.header.sense = leoiplSend_asic_cmd_w(ASIC_RECAL, 0x00);
            if (dummy_cmd.header.sense)
                goto system_retry;
        }
    } while (1);

sys_read_end:
    /* restore current command */
    LeoIPLcur_command = backup_pointer;
    return (chk_cmd->sense = dummy_cmd.header.sense);
}

/* ==========================================================================
* Function : leoiplRead_ipl
* --------------------------------------------------------------------------
* Description : Read first segment of application program.
* --------------------------------------------------------------------------
* IN   : LeoIPLcur_command
* OUT  : *LeoIPLcur_command
* ARG  : non
* RET  : 0:good , not 0: error sense code
* ==========================================================================
*/
u8 leoiplRead_ipl(void)
{
    LEOCmdRead dummy_cmd;
    struct ipl_read_cmd_form  *backup_pointer;

    /* Backup current command */
    backup_pointer = LeoIPLcur_command;
    LeoIPLcur_command = (void*)&dummy_cmd;

    /********************************/
    /* read first file in user area */
    /********************************/
    LeoIPLrw_flags = 0;

    dummy_cmd = system_read_cmd;
#ifdef _ERRCHK
    dummy_cmd.header.reserve1 = backup_pointer->header.reserve1;
    dummy_cmd.header.reserve3 = backup_pointer->header.reserve3;
#endif
    dummy_cmd.lba = SYSTEM_LBAS;
    dummy_cmd.xfer_blks = LeoIPL_sys_data.param.ipl_load_len;
    dummy_cmd.buff_ptr  = backup_pointer->buff_ptr = LeoIPL_sys_data.param.loadptr;

    /* call read routine */
    leoiplRead_zone0();

#ifdef _ERRCHK
    backup_pointer->header.reserve7 = dummy_cmd.header.reserve7;
#endif
    /* Restore current command */
    LeoIPLcur_command = backup_pointer;
    return (chk_cmd->sense  = dummy_cmd.header.sense);
}