leoutil.c 5.65 KB
/*
 *  F i l e N a m e  : l e o u t i l . c
 *
 ****************************************************************************
 *                   (C) Copyright ALPS Electric Co., Ltd. 1995-1996
 ****************************************************************************
 *  Version:
 *
 *  ver     date
 *  ----  --------
 *  1.06  '96-09-20   Change device-driver support is new format only .
 *                    Change defect cylinder calculate .
 *  1.05  '96-09-10   Support new format DISK ( max 12 defect per zone ) .
 *                    Change defect cylinder calculate .
 *                    Change LEOZONE_SCYL_TBL[] -> LEOZONE_SCYL_TBL[][] .
 *  1.04  '96-08-27   See LEO_country_code to check system sector size to remove KAIHATU definition.
 *  1.03  '96-06-11   Add LEOtgt_param.sec_bytes,.blk_byte calc in leoLba_to_phys().
 *  1.02  '96-04-05   Change LEO_TBL .
 *  1.01  '96-02-27   Rename file name util.c to leoutil.c .
 *  1.00  '95-12-20   Initial Revision.
 ****************************************************************************
 */
#include <ultra64.h>
#include "leodefine.h"
#include "leodrive.h"
#include "leomacro.h"

/*************************************/
/* PROTOTYPE                         */
/*************************************/
u16 leoLba_to_phys(u32 lba);
u16 leoLba_to_vzone(u32 lba);

/*************************************/
/* EXTERNAL FUNCTIONS                */
/*************************************/

/*************************************/
/* EXTERNAL RAMS                     */
/*************************************/
extern u16    LEOVZONE_TBL[DISK_TYPES][VZONES_PER_DRV];
extern u8     LEOVZONE_PZONEHD_TBL[DISK_TYPES][VZONES_PER_DRV];
extern u16    LEOZONE_SCYL_TBL[VZONES_PER_DRV];
extern u16    LEOZONE_OUTERCYL_TBL[(ZONES_PER_DRV-1)];
extern struct tgt_param_form LEOtgt_param;
extern union  leo_sys_form   LEO_sys_data;
extern u8     LEOdisk_type;
extern u8  LEOBYTE_TBL1[ZONES_PER_DRV];
extern u16 LEOBYTE_TBL2[ZONES_PER_DRV];
extern union data_trans_form LEO_country_code;

/* ==========================================================================
* Function : leoLba_to_phys
* --------------------------------------------------------------------------
* Description : TRANSLATE LBA TO PHYSICAL PARMETER
* --------------------------------------------------------------------------
* IN    : LEOdisk_type
* OUT   : tgt_param
* ARG   : lba
* RET   : 0     .. GOOD
*       : NOT 0 .. NOT GOOD
* ==========================================================================
*/
u16   leoLba_to_phys(u32 lba)
{
    u16 vzone_num;
    u16 zone_slba;
    u16 zone_scyl;
    u16 zone_tk;
    u16 bad_tk_num;
    u32 counter;
    u16 def_offset;
    u16 defect;
    u8  def_zone_no;

    /*
     *  Calc accessable block in track
     */
    LEOtgt_param.rdwr_blocks = (u32)0x02 - (lba & (u32)0x01);

    /*
     *  Calc start block
     */
    switch (lba & (u32)0x03)
    {
        case 0:                          /* start block = 0 */
        case 3: 
            LEOtgt_param.start_block = (u16)0x00;
            break;
        default:                         /* start block = 1 */
            LEOtgt_param.start_block = (u16)0x01;
            break;
    }

    /*
     *  Calc cylinder/head.(no defect)
     */
    /* calc zone */
    vzone_num = leoLba_to_vzone(lba);
    LEOtgt_param.zone = def_zone_no = LEOVZONE_PZONEHD_TBL[LEOdisk_type][vzone_num];

    LEOtgt_param.head = 0;
    if (LEOtgt_param.zone > (u8)7)
    {
        LEOtgt_param.zone -= (u8)7;
        LEOtgt_param.head  = 1;
    }

    /* zone start cylinder */
    zone_scyl = LEOZONE_SCYL_TBL[def_zone_no];

    /* calc cylinder address in zone */
    if (vzone_num)
    {
        zone_slba = LEOVZONE_TBL[LEOdisk_type][vzone_num - 1];
    }
    else
    {
        zone_slba = 0;
    }
    zone_tk  = (lba - zone_slba) / 2;
    if (LEOtgt_param.head)
    {
        /* seek innter to outer in side 1 */
        LEOtgt_param.cylinder = zone_scyl - zone_tk;
        zone_scyl = LEOZONE_OUTERCYL_TBL[LEOtgt_param.zone-1];
    }
    else
    {
        /* seek outer to inner in side 0 */
        LEOtgt_param.cylinder  = zone_scyl + zone_tk;
    }

    /*
     *  defect
     */
    /* Calc defect num */
    if (def_zone_no)
    {
        def_offset = LEO_sys_data.param.defect_num[def_zone_no - 1];
    }
    else
    {
        def_offset = 0;
    }
    bad_tk_num = LEO_sys_data.param.defect_num[def_zone_no] - def_offset;

    while (bad_tk_num)
    {
        defect = (u16)LEO_sys_data.param.defect_data[def_offset] + zone_scyl;
        if (LEOtgt_param.cylinder < defect)
            break;

        LEOtgt_param.cylinder++;
        def_offset++;
        bad_tk_num--;
    }

    LEOtgt_param.sec_bytes = LEOBYTE_TBL1[LEOtgt_param.zone];
    LEOtgt_param.blk_bytes = LEOBYTE_TBL2[LEOtgt_param.zone];

    if ((LEO_country_code.u32_data == 0) && (lba < SYS_UNCORR_LBA))
    {
        LEOtgt_param.sec_bytes = SEC_SIZE_SYSTEM;
        LEOtgt_param.blk_bytes = SEC_SIZE_SYSTEM*USR_SECS_PER_BLK;
    }

    return(FUNC_OK);
}


/* ==========================================================================
* FUNCTION  : leoLba_to_vzone
* --------------------------------------------------------------------------
* DESCRIPTION  : calc logical zone from LBA
* --------------------------------------------------------------------------
* IN   : LEOdisk_type
* OUT  : ̵
* ARG  : lba 
* RET  : logical zone  (015)
*      : if error then return 0xff
* ==========================================================================
*/
u16   leoLba_to_vzone(u32 lba)
{
    u16 i;
    u16 *ptr;

    ptr = &LEOVZONE_TBL[LEOdisk_type][0];
    for (i=0; i<16 ; i++)
    {
        if (lba < *ptr)
            return(i);
        ptr++;
    }
    return(FUNC_NG);
}