Version:0.9 StartHTML:0000000105 EndHTML:0000066120 StartFragment:0000000854 EndFragment:0000066086 facpi.txt
//------------------------------------------------------------------------------
//
// BlackFox ACPI-BIOS v2.0
// 
// Copyright (C) 2007-2009 by Black Phoenix
//
//-- Initialization ------------------------------------------------------------

//File version
define ACPI_VERSION,20;

//Create variables withing ACPIRAM
define ACPI_Param_Version,         1901056; //512
define ACPI_Param_ScanDevices,     1901057; //513
define ACPI_Param_Frame,           1901058; //514
define ACPI_Param_ScanControllers, 1901059; //515

setvar localrange,96;

mov GS,851968;  //Cartridge
mov FS,327680;  //GPU
mov ES,1901568; //Sound
mov KS,1900544; //ACPIRAM
mov LS,1902592; //RAWIO

mov ESP,32767;  //Stack fix

call ACPI_PowerDown;
PowerCycle:
  idle;
  cmp LS:#47,1; //Check for power button pressed
  ce ACPI_TurnOn;
jmp PowerCycle;



//-- Main power cycle ----------------------------------------------------------
ACPI_TurnOn:
  call ACPI_PowerUp;
  call ACPI_AssertButtonReleased;

  call ACPI_WIFI_Reset;

  @MainCycle:
    call ACPI_HandleEvents;
  jmp @MainCycle;
ret

ACPI_TurnOff:
  call ACPI_PowerDown;
  call ACPI_AssertButtonReleased;
  mov ESP,32767;  //Restore stack
  jmp PowerCycle;
ret



//-- Events handlers -----------------------------------------------------------
ACPI_HandleEvents_Critical:
  //Check power button
  cmp LS:#47,1;
  ce ACPI_TurnOff;
ret

ACPI_HandleEvents:
  //Check power button
  cmp LS:#47,1;
  ce ACPI_TurnOff;

  //Process WIFI connections
  mov KS:#ACPI_Param_Frame,#ACPI_WIFI_Frame;

//====================================================================================
  //FIXME: better code
  mov EAX,#ACPI_WIFI_Frame; mul EAX,4; add EAX,256; mov LS:#0,KS:#EAX; //RADIO0 Channel
  mov EAX,#ACPI_WIFI_Frame; mul EAX,4; add EAX,272; mov LS:#1,KS:#EAX; //RADIO1 Channel
  mov EAX,#ACPI_WIFI_Frame; mul EAX,4; add EAX,288; mov LS:#2,KS:#EAX; //RADIO2 Channel
  mov EAX,#ACPI_WIFI_Frame; mul EAX,4; add EAX,304; mov LS:#3,KS:#EAX; //RADIO3 Channel
  idle;
  idle;


//== RADIO0 ====================================================================
  mov EBP,8;   //Offset on radio bus
  mov EAX,256; //Offset in ACPIRAM
  call ACPI_WIFI_CopyChannel;

//== RADIO1 ====================================================================
  mov EBP,16;  //Offset on radio bus
  mov EAX,272; //Offset in ACPIRAM
  call ACPI_WIFI_CopyChannel;
  
//== RADIO2 ====================================================================
  mov EBP,24;  //Offset on radio bus
  mov EAX,288; //Offset in ACPIRAM
  call ACPI_WIFI_CopyChannel;
  
//== RADIO3 ====================================================================
  cmp #ACPI_Param_ScanDevices,0;
  je Channel3_Used;
    //cmp #ACPI_WIFI_Frame,2; cge ACPI_WIFI_DeviceScan;
    //cmp #ACPI_WIFI_Frame,2; jge Channel3_NotUsed;
    call ACPI_WIFI_DeviceScan;
    jmp Channel3_NotUsed;
  Channel3_Used:
    mov EBP,32;  //Offset on radio bus
    mov EAX,304; //Offset in ACPIRAM
    call ACPI_WIFI_CopyChannel;
  Channel3_NotUsed:

//== Frame step ================================================================
  inc #ACPI_WIFI_Frame;
  mod #ACPI_WIFI_Frame,4;
//====================================================================================

  //Check for missing controllers
  cmp KS:#256,0;
  jne @Present1;
    sbit #ACPI_Param_ScanControllers,0;
    mov #ACPI_WIFI_Controller1_Range,256;
  @Present1:

  cmp KS:#272,0;
  jne @Present2;
    sbit #ACPI_Param_ScanControllers,1;
    mov #ACPI_WIFI_Controller2_Range,256;
  @Present2:
ret

ACPI_WIFI_Reset:
  mov #ACPI_WIFI_Frame,0;

  mov #ACPI_WIFI_Controller1_Range,256;
  mov #ACPI_WIFI_Controller2_Range,256;

  mov #ACPI_Param_ScanControllers,3; //Scan controllers #1 & #2
  mov #ACPI_Param_ScanDevices,1;     //Keep scanning new devices

  mov KS:#256,0; mov KS:#260,0; mov KS:#264,0; mov KS:#268,0;
  mov KS:#272,0; mov KS:#276,0; mov KS:#280,0; mov KS:#284,0;
  mov KS:#288,0; mov KS:#292,0; mov KS:#294,0; mov KS:#298,0;
  mov KS:#304,0; mov KS:#308,0; mov KS:#312,0; mov KS:#316,0;
ret

alloc ACPI_WIFI_Frame;
alloc ACPI_WIFI_Controller1_Range;
alloc ACPI_WIFI_Controller2_Range;



//-- Device scanning -----------------------------------------------------------
ACPI_WIFI_DeviceScan: //uses RADIO3
  mov EBP,KS:#304;                       //Current tuned in channel
  add EBP,128; min EBP,256; max EBP,128; //Security clamping
  mov KS:#EBP,LS:#32;                    //Recieve device ID
  band KS:#EBP,131056;                   //Mask out the randomizer mask + unused bits

  cmp #ACPI_Param_ScanControllers,0; //Need to scan any controller?
  je DeviceScan_NoControllers;
//==============================================================================
    bit #ACPI_Param_ScanControllers,0; //Need to find controller 1? (nearest controller)
    jz DeviceScan_DontNeed_C1;

      cmp KS:#EBP,16;    //Primary controller
      jne DeviceScan_DontNeed_C1;
        call ACPI_WIFI_ControllerDistance;

        cmp EAX,#ACPI_WIFI_Controller1_Range;
        jg @Out_Of_Range_C1;
          mov #ACPI_WIFI_Controller1_Range,EAX;

          mov EDI,KS:#304; //Get current channel ID
          mov KS:#256,EDI; mov KS:#257,1; mov KS:#258,KS; //Tune RADIO0 to controller channel
          mov KS:#260,EDI; mov KS:#261,1; mov KS:#262,KS;
          mov KS:#264,EDI; mov KS:#265,1; mov KS:#266,KS;
          mov KS:#268,EDI; mov KS:#267,1; mov KS:#269,KS;
        @Out_Of_Range_C1:
    DeviceScan_DontNeed_C1:
//==============================================================================
    bit #ACPI_Param_ScanControllers,1; //Need to find controller 2? (nearest and not 1)
    jz DeviceScan_DontNeed_C2;

      cmp KS:#EBP,65552; //Secondary controller
      jne DeviceScan_DontNeed_C2;
        call ACPI_WIFI_ControllerDistance;

        cmp EAX,#ACPI_WIFI_Controller2_Range;
        jg Out_Of_Range_C2;
          mov #ACPI_WIFI_Controller2_Range,EAX;

          mov EDI,KS:#304; //Get current channel ID
          mov KS:#272,EDI; mov KS:#273,1; mov KS:#274,KS; add KS:#274,8; //Tune RADIO1 to controller channel
          mov KS:#276,EDI; mov KS:#277,1; mov KS:#278,KS; add KS:#278,8;
          mov KS:#280,EDI; mov KS:#281,1; mov KS:#282,KS; add KS:#282,8;
          mov KS:#284,EDI; mov KS:#285,1; mov KS:#286,KS; add KS:#286,8;
        Out_Of_Range_C2:
    DeviceScan_DontNeed_C2:
//==============================================================================
  DeviceScan_NoControllers:

  inc KS:#304;
  //mov KS:#304,65;
  mov KS:#308,KS:#304;
  mov KS:#312,KS:#304;
  mov KS:#316,KS:#304;

  cmp KS:#304,128;
  jl DeviceScan_NoReset;
    mov KS:#304,0;
  DeviceScan_NoReset:
ret



//-- Misc functions ------------------------------------------------------------
ACPI_AssertButtonReleased:
  @ButtonRelease: idle; cmp LS:#47,0; jne @ButtonRelease;
ret

ACPI_WIFI_CopyChannel: //Check for type
  mov ESI,#ACPI_WIFI_Frame; mul ESI,4; add ESI,EAX;
  
           mov EAX,KS:#ESI;  //Device channel
  inc ESI; mov EBX,KS:#ESI;  //Flags
  inc ESI; mov ECX,KS:#ESI;  //Write RAM offset
  inc ESI; mov EDX,KS:#ESI;  //Read RAM offset
  
  cmp EAX,0;      je Channel_DontWrite;  //Check if radio is not used
  cmp LS:#EBP,0; jne Channel_NotMissing; //Check if device is no longer valid
    mov #ECX,0;
    sub ESI,3; mov KS:#ESI,0; ret;
  Channel_NotMissing:

  bit EBX,0; //Check the READ flag
  jz Channel_DontRead;
    mov ESI,LS; add ESI,EBP;
    mov EDI,ECX;
    mcopy 8;
  Channel_DontRead:

  bit EBX,1; //Check the WRITE flag
  jz Channel_DontWrite;
    mov ESI,ECX;
    mov EDI,LS; add EDI,EBP;
    mcopy 8;
  Channel_DontWrite:
ret

ACPI_WIFI_ControllerDistance:
  mov #ACPI_WIFI_Temp1,LS:#37; sub #ACPI_WIFI_Temp1,LS:#56; //X
  mov #ACPI_WIFI_Temp2,LS:#38; sub #ACPI_WIFI_Temp2,LS:#57; //Y
  mov #ACPI_WIFI_Temp3,LS:#39; sub #ACPI_WIFI_Temp3,LS:#58; //Z
  mov EAX,#ACPI_WIFI_Temp1; fpwr EAX,2;
  mov EBX,#ACPI_WIFI_Temp2; fpwr EBX,2;
  add EAX,EBX;
  mov EBX,#ACPI_WIFI_Temp3; fpwr EBX,2;
  add EAX,EBX; fpwr EAX,0.5; //Distance to controller
ret

alloc ACPI_WIFI_Temp1;
alloc ACPI_WIFI_Temp2;
alloc ACPI_WIFI_Temp3;


//-- Power management ----------------------------------------------------------
ACPI_PowerUp:
  //Set default CPU frequency
  mov LS:#40,5000;
  mov LS:#41,5000;

  //Dont reset CPU1
  mov LS:#49,0;

  //Power up GPU
  mov FS:#65535,0;
  mov FS:#0,214;
  mov FS:#1,0;
  mov FS:#2,5;
  mov FS:#3,201;
  mov FS:#4,0;
  mov FS:#5,255;
  mov FS:#6,255;
  mov FS:#7,255;
  mov FS:#8,255;
  mov FS:#0,FS:#0;
  mov FS:#65535,1;
  mov FS:#65534,1;

  //Show power LED
  mov LS:#50,32;
  mov LS:#51,200;
  mov LS:#52,0;
  
  //Show activity LED
  mov LS:#53,0;
  mov LS:#54,0;
  mov LS:#55,0;

  //Reset ACPIRAM and RAM
  mov LS:#61,1; mov LS:#62,1;
  idle;
  mov LS:#61,0; mov LS:#62,0;
  idle;

  //Set some variables in ACPIRAM
  mov #ACPI_Param_Version,ACPI_VERSION;

  //Reset radio channels
  mov LS:#0,0;
  mov LS:#1,0;
  mov LS:#2,0;
  mov LS:#3,0;

  //Give power to CPU
  mov LS:#46,1;
ret

ACPI_PowerDown:
  //Power off the CPU
  mov LS:#46,0; //CPU0
  mov LS:#48,0; //CPU1
  
  //Lights go out
  mov LS:#50,0;
  mov LS:#51,0;
  mov LS:#52,0;
  mov LS:#53,0;
  mov LS:#54,0;
  mov LS:#55,0;
  
  //Reset radio channels
  mov LS:#0,0;
  mov LS:#1,0;
  mov LS:#2,0;
  mov LS:#3,0;

  //Power down GPU
  mov FS:#65535,0;
  mov FS:#0,200;
  mov FS:#1,0;
  mov FS:#10000,FS:#10000;
  mov FS:#65534,1;
  mov FS:#65535,0;

  //Turn off the sound
  mov ES:#0 ,0;
  mov ES:#8 ,0;
  mov ES:#16,0;
  mov ES:#24,0;
  mov ES:#32,0;
  mov ES:#40,0;
  mov ES:#48,0;
  mov ES:#56,0;
ret