leowrite.c 6.12 KB
/*
 *  F i l e N a m e :  l e o w r i t e . c
 *
 ****************************************************************************
 *                   (C) Copyright ALPS Electric Co., Ltd. 1995-1996
 ****************************************************************************
 *  Version:
 *
 *  ver     date
 *  ----   --------
 *  1.07   '98-04-22   Change writable lba for each disk type .
 *  1.06   '98-02-17   Enable ROM area write for B114 .
 *  1.05   '97-01-10   Change sense code name to LEO_SENSE_ILLEGAL_SECTOR_SIZE.
 *  1.04   '96-12-24   Delete "SYSTEMWRITE" and add "#ifdef _LONGCMD" for long command.
 *  1.03a  '96-10-07   Enable system area write if SYSTEMWRITE is defined.
 *  1.03   '96-07-20   Move track/retry operation to leoint.c  .
 *  1.02   '96-04-11   Move retry judgment location .
 *                     Delete TRACK_COMPLETE message .
 *  1.01   '96-02-27   Rename file name write.c to leowrite.c .
 *  1.00   '95-12-20   Initial Revision.
 ****************************************************************************
*/
#define _WRITER

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

/**************************************
*  PROTOTYPE DEFINITION
**************************************/
void leoWrite(void);
#ifdef _LONGCMD
static void leoWriteCommon(void);
#endif

/**************************************
*  EXTERNALY DEFINITION FUNCTIONS
**************************************/
extern u16  leoLba_to_phys(u32 lba);

/**************************************
*  EXTERNALY DEFINITION RAM LOCATIONS
**************************************/
extern OSThread    LEOinterruptThread;
extern OSMesgQueue LEOcontrol_que;
extern OSMesg      LEOcur_command;
extern u8  LEOdisk_type;
extern struct tgt_param_form LEOtgt_param;
extern u16 LEOrw_flags;

extern u16 LEOBYTE_TBL2[ZONES_PER_DRV];
extern u16 LEORAM_START_LBA[DISK_TYPES];

#ifdef _WRITER
extern u16 LEOWRITER_END_LBA[DISK_TYPES];
#endif
/**************************************
*  MACROS
**************************************/
#define   write_command   ((LEOCmdWrite *)LEOcur_command)
#ifdef _LONGCMD
#define   write_long_command    ((LEOCmdWriteLong *)LEOcur_command)
#define   ALLTK_WRT
#endif

#ifdef _LONGCMD
/**********************************************************
* Function : leoWriteLong
* ---------------------------------------------------------
* Description : excute write long command
* IN  : LEOcur_command
* OUT : *LEOcur_command
**********************************************************/
void leoWriteLong(void)
{
    if (write_long_command->header.control & 0x01)
        LEOrw_flags = WRITE_MODE+LONG_RW;
    else
    {
        LEOrw_flags = WRITE_MODE+FIXSIZE;
        leoLba_to_phys(write_long_command->lba);
        if (  (write_long_command->size & 7)
           || (write_long_command->size == 0)
           || (write_long_command->size > LEOtgt_param.sec_bytes) )
        {
            if (write_long_command->size == (LEOtgt_param.sec_bytes+8))
                LEOrw_flags = LONG_RW;
            else
            {
                write_long_command->header.sense  = LEO_SENSE_ILLEGAL_SECTOR_SIZE;
                write_long_command->header.status = LEO_STATUS_CHECK_CONDITION;
                return;
            }
        }
    }
    leoWriteCommon();
}
/*===========================================================================
* Function : void leoWrite(void)
* ---------------------------------------------------------------------------
* Function : Execute write commnad
* IN    : LEOcur_command, LEOdisk_type
* OUT   : *LEOcur_command
* ARG   : non
* RET   : non
* =========================================================================*/
void leoWrite(void)
{
    LEOrw_flags = WRITE_MODE;  /* clear C2,sectormode flag */
    leoWriteCommon();
}
void leoWriteCommon(void)
#else
void leoWrite(void)
#endif
{
    u32 message;
    u32 start_lba;
    u32 xfer_blk;
    u32 write_bytes = 0;
    u8  retry_count = 0;

    /* set start lba and blocks  */
    start_lba = write_command->lba;
    xfer_blk  = write_command->xfer_blks;

#ifdef _LONGCMD
    start_lba += SYSTEM_LBAS;
    if ((start_lba | xfer_blk) & 0xffff0000)
        goto invalid_lba;
#else
    if ((start_lba | xfer_blk) & 0xffff0000)
        goto invalid_lba;
    start_lba += SYSTEM_LBAS;
#endif

    /* CHECK LBA AND BLOCKS VALUE  */
    if ( (start_lba > MAX_P_LBA) || ((start_lba+xfer_blk)>(MAX_P_LBA+1)) )
    {
invalid_lba:
        /* OUT OF RANGE ERROR  */
        write_command->header.sense  = LEO_SENSE_LBA_OUT_OF_RANGE;
        write_command->header.status = LEO_STATUS_CHECK_CONDITION;
        return;
    }

#ifndef ALLTK_WRT
    /* RAM AREA ? */
    if (start_lba < LEORAM_START_LBA[LEOdisk_type])
    {
#ifdef _WRITER
        if ((start_lba < LEOWRITER_START_LBA) || (start_lba > LEOWRITER_END_LBA[LEOdisk_type]))
        {
            write_command->header.sense  = LEO_SENSE_WRITE_PROTECT_ERROR;
            write_command->header.status = LEO_STATUS_CHECK_CONDITION;
            return;                                         /* 範囲外の場合は、エラー終了  */
        }
#else
        write_command->header.sense  = LEO_SENSE_WRITE_PROTECT_ERROR;
        write_command->header.status = LEO_STATUS_CHECK_CONDITION;
        return;                                         /* 範囲外の場合は、エラー終了  */
#endif
    }
#endif

    if (xfer_blk == 0)
    {
        write_command->header.sense  = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;
        write_command->header.status = LEO_STATUS_GOOD;
        return;
    }

#ifdef _LONGCMD
    LEOrw_flags |= WRITE_MODE;
#else
    LEOrw_flags = WRITE_MODE;
#endif
    LEOtgt_param.lba = start_lba;

    osStartThread(&LEOinterruptThread);

    (void)osRecvMesg(CONTROL_QUE, (OSMesg*)&message, OS_MESG_BLOCK);
    if (message != (u32)MES_RW_COMPLETE)
    {
        /* error */
        write_command->header.sense  = message;
        write_command->header.status = LEO_STATUS_CHECK_CONDITION;
        return;
    }
    /* SET DONE STATUS  */
    write_command->header.sense  = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;
    write_command->header.status = LEO_STATUS_GOOD;
}