createleomanager.c 4.47 KB

#include <ultra64.h>
#include "osint.h"
#include "leodrive.h"

#ifndef	_LONGCMD
#include <leo.h>
#else
#include <leosp.h>
#endif

#ifndef INIT_DISK		/* カセット起動 */

#define	__LEO_DRIVE_A		3
#define	__LEO_DRIVE_ADASH	5
#define	__LEO_DRIVE_C		1
#define	__LEO_DRIVE_D		4

#define JAPAN                   0xe848d316
#define USA                     0x2263ee56

#endif /* not INIT_DISK */

#define	IPL_COUNTRY_CODE	0x0009ff00
#define	CODE_JAPAN		0xc3
#define	CODE_USA		0x04

extern s32		__leoActive;
extern LEOVersion 	__leoVersion;

/* export from ISR */
extern char		leoDiskStack[];
extern s32		__osLeoInterrupt(void);

#ifndef INIT_DISK		/* カセット起動 */

/* export from leo device driver */
extern u32    	LEO_country_code;
extern s32 	__leoSetReset(void);

#endif /* not INIT_DISK */

#ifndef INIT_DISK
# ifdef INIT_JAPAN
s32 LeoCJCreateLeoManager(OSPri comPri, OSPri intPri,
			  OSMesg *cmdBuf, s32 cmdMsgCnt)
# else /* INIT_JAPAN */
s32 LeoCACreateLeoManager(OSPri comPri, OSPri intPri,
			  OSMesg *cmdBuf, s32 cmdMsgCnt)
# endif /* INIT_JAPAN */
#else /* INIT_DISK */
s32 LeoCreateLeoManager(OSPri comPri, OSPri intPri,
			OSMesg *cmdBuf, s32 cmdMsgCnt)
#endif /* INIT_DISK */
{
  OSPiHandle 			*driveRomHandle;
  OSPiHandle 			*leoDiskHandle;
  volatile LEOCmdInquiry	cmdBlockInq;
  volatile LEOCmd		cmdBlockID;
  LEODiskID			thisID;
  u32				stat, data;
  

  /* If Leo Manager is already running, simply return */
  if (__leoActive)
    return 0;
  
  /*
   * ハンドラー取得の前に、ドライブの存在を確認
   */
  if (! LeoDriveExist() )
      return LEO_ERROR_DEVICE_COMMUNICATION_FAILURE;

  /*
   * Get the handlers to access drive rom and disk
   */
  leoDiskHandle = osLeoDiskInit();
  driveRomHandle = osDriveRomInit();
  

  __leoActive = 1;
  

  /*
   * ISR の関数登録およびスタック登録(例外ハンドラに対して)
   */
  __osSetHWIntrRoutine((OSHWIntr)1, __osLeoInterrupt,
		       (void *)(leoDiskStack + 4080));


  /*
   * Create command and interrupt threads
   */
  leoInitialize(comPri, intPri, cmdBuf, cmdMsgCnt);

#ifndef INIT_DISK
  if (osResetType == 1)
  {
    /*
     * NMI occurred. Reset the drive.
     */

    __leoSetReset();
    
  }
  
#endif /* not INIT_DISK */

  /*
   * Now, read the version number of the hardware in advance.
   */
  /*
   * Fill up command block
   */
  cmdBlockInq.header.command	= LEO_COMMAND_INQUIRY;
  cmdBlockInq.header.reserve1	= 0;
  cmdBlockInq.header.control	= 0;
  cmdBlockInq.header.reserve3	= 0;

  leoCommand((void *)&cmdBlockInq);
  
  /*
   * dummy code for security
   */
  {
    volatile s32	dummy;
    
#ifdef INIT_JAPAN

    dummy = (s32)( (u32)&cmdBlockInq & 0x00ffffff );
    while(dummy > 0)
      dummy -= (s32)( ((u32)__leoSetReset & 0x00ffffff) | 0x00403df4 );
    
#else

    dummy = (s32)( (u32)__osSetHWIntrRoutine & 0x00a48d3c );
    while(dummy < 0xe00000)
      dummy += (s32)( ( ((u32)leoCommand & 0x000000ff) | 0x8a ) << 16 );
    
#endif
  }
  
  while(cmdBlockInq.header.status == LEO_STATUS_BUSY)
    ;

  if(cmdBlockInq.header.status != LEO_STATUS_GOOD)
    return (cmdBlockInq.header.sense);

  __leoVersion.drive  		= cmdBlockInq.version;
  __leoVersion.driver 		= LEO_SW_VERSION;
  __leoVersion.deviceType	= cmdBlockInq.dev_type;
  __leoVersion.ndevices		= cmdBlockInq.dev_num;
  

#ifndef INIT_DISK		/* カセット起動の場合 */

  if( (__leoVersion.drive & 0x0f) == __LEO_DRIVE_D )
  {
    LEO_country_code = 0;
  }
#ifdef _WRITER
  else if( ((__leoVersion.drive & 0x0f) == __LEO_DRIVE_A) ||
	  ((__leoVersion.drive & 0x0f) == __LEO_DRIVE_ADASH) ||
	  ((__leoVersion.drive & 0x0f) == __LEO_DRIVE_C) )
#else
  else if( ((__leoVersion.drive & 0x0f) == __LEO_DRIVE_A) ||
	  ((__leoVersion.drive & 0x0f) == __LEO_DRIVE_C) )
#endif

  {
    osEPiReadIo(driveRomHandle, (u32)IPL_COUNTRY_CODE, (u32 *)&data); 
    data = (data & 0xff000000) >> 24;
    
#ifdef INIT_JAPAN

    /*
     * dummy code for security
     */
  {
    volatile u32	dummy;
    
    dummy = 0x3ed98f23;
    
    if (data != CODE_JAPAN)
      for(;;);

    dummy *= data;
    dummy -= (u32)&cmdBlockInq;
    
  }

    LEO_country_code = JAPAN;

#else  /* i.e. INIT_USA currently */

    /*
     * dummy code for security
     */
  {
    volatile u32	dummy;
    
    if (data != CODE_USA)
      for(;;);

    dummy = 0x32f8eb20;
    
    /*
     * 意味のあるコード
     */
    LEO_country_code = USA;

    dummy += (u32)&__leoActive;
  }
    

#endif /* INIT_JAPAN */

  } /* else if (drive = A drive) or (drive = C drive) */

  else /* error */
  {
    for(;;);
  }
  
#endif /* not INIT_DISK */

  return 0;

}