Logo Search packages:      
Sourcecode: xbox-cromwell version File versions  Download package

pci.c

#include "boot.h"
// by ozpaulb@hotmail.com 2002-07-14

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

u8 PciReadByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off)
{
      u32 base_addr = 0x80000000;
      base_addr |= ((bus & 0xFF) << 16);  // bus #
      base_addr |= ((dev & 0x1F) << 11);  // device #
      base_addr |= ((func & 0x07) << 8);  // func #

            IoOutputDword(0xcf8, (base_addr + (reg_off & 0xfc)));
            return IoInputByte(0xcfc + (reg_off & 3));
}

void PciWriteByte (unsigned int bus, unsigned int dev, unsigned int func,
            unsigned int reg_off, unsigned char byteval)
{
      u32 base_addr = 0x80000000;
      base_addr |= ((bus & 0xFF) << 16);  // bus #
      base_addr |= ((dev & 0x1F) << 11);  // device #
      base_addr |= ((func & 0x07) << 8);  // func #

      IoOutputDword(0xcf8, (base_addr + (reg_off & 0xfc)));
      IoOutputByte(0xcfc + (reg_off & 3), byteval);
}


u16 PciReadWord(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off)
{
      u32 base_addr = 0x80000000;
      base_addr |= ((bus & 0xFF) << 16);  // bus #
      base_addr |= ((dev & 0x1F) << 11);  // device #
      base_addr |= ((func & 0x07) << 8);  // func #

            IoOutputDword(0xcf8, (base_addr + (reg_off & 0xfe)));
            return IoInputWord(0xcfc + (reg_off & 1));
}


void PciWriteWord(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, u16 w)
{
      u32 base_addr = 0x80000000;
      base_addr |= ((bus & 0xFF) << 16);  // bus #
      base_addr |= ((dev & 0x1F) << 11);  // device #
      base_addr |= ((func & 0x07) << 8);  // func #

      IoOutputDword(0xcf8, (base_addr + (reg_off & 0xfc)));
      IoOutputWord(0xcfc + (reg_off & 1), w);
}


u32 PciReadDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off)
{
      u32 base_addr = 0x80000000;
      base_addr |= ((bus & 0xFF) << 16);  // bus #
      base_addr |= ((dev & 0x1F) << 11);  // device #
      base_addr |= ((func & 0x07) << 8);  // func #
        base_addr |= ((func & 0x07) << 8);
        base_addr |= ((reg_off & 0xff));
        
      IoOutputDword(0xcf8, base_addr);
      return IoInputDword(0xcfc);
}


u32 PciWriteDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int dw) 
{
            
      u32 base_addr = 0x80000000;
      base_addr |= ((bus & 0xFF) << 16);  // bus #
      base_addr |= ((dev & 0x1F) << 11);  // device #
      base_addr |= ((func & 0x07) << 8);  // func #
      base_addr |= ((reg_off & 0xff));

      IoOutputDword(0xcf8, base_addr );   
      IoOutputDword(0xcfc ,dw);

      return 0;    
}
#define RTC_REG_A       10
#define RTC_REG_B       11
#define RTC_REG_C       12
#define RTC_REG_D       13
#define RTC_FREQ_SELECT       RTC_REG_A
#define RTC_CONTROL           RTC_REG_B
#define RTC_INTR_FLAGS        RTC_REG_C

/* On PCs, the checksum is built only over bytes 16..45 */
#define PC_CKS_RANGE_START    16
#define PC_CKS_RANGE_END      45
#define PC_CKS_LOC            46

#define RTC_RATE_1024HZ       0x06
#define RTC_REF_CLCK_32KHZ    0x20
#define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ)
#define RTC_24H         0x02
#define RTC_CONTROL_DEFAULT (RTC_24H)


// access to RTC CMOS memory
u8 CMOS_READ(u8 addr) { 
      IoOutputByte(0x70,addr); 
      return IoInputByte(0x71); 
}

void CMOS_WRITE(u8 val, u8 addr) { 
      IoOutputByte(0x70,addr);
      IoOutputByte(0x71,val); 
}

void BiosCmosWrite(u8 bAds, u8 bData) {
      IoOutputByte(0x70, bAds);
      IoOutputByte(0x71, bData);

      IoOutputByte(0x72, bAds);
      IoOutputByte(0x73, bData);
}

u8 BiosCmosRead(u8 bAds)
{
      IoOutputByte(0x72, bAds);
      return IoInputByte(0x73);
}

int rtc_checksum_valid(int range_start, int range_end, int cks_loc)
{
      int i;
      unsigned sum, old_sum;
      sum = 0;
      for(i = range_start; i <= range_end; i++) {
            sum += CMOS_READ(i);
      }
      sum = (~sum)&0x0ffff;
      old_sum = ((CMOS_READ(cks_loc)<<8) | CMOS_READ(cks_loc+1))&0x0ffff;
      return sum == old_sum;
}

void rtc_set_checksum(int range_start, int range_end, int cks_loc)
{
      int i;
      unsigned sum;
      sum = 0;
      for(i = range_start; i <= range_end; i++) {
            sum += CMOS_READ(i);
      }
      sum = ~(sum & 0x0ffff);
      CMOS_WRITE(((sum >> 8) & 0x0ff), cks_loc);
      CMOS_WRITE(((sum >> 0) & 0x0ff), cks_loc+1);
}

void BootAGPBUSInitialization(void)
{
      u32 temp;
      PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x54,   PciReadDword(BUS_0, DEV_1, FUNC_0, 0x54) | 0x88000000 );
      
      PciWriteDword(BUS_0, DEV_0, FUNC_0, 0x64,   (PciReadDword(BUS_0, DEV_0, FUNC_0, 0x64))| 0x88000000 );
      
      temp =  PciReadDword(BUS_0, DEV_0, FUNC_0, 0x6C);
      IoOutputDword(0xcfc , temp & 0xFFFFFFFE);
      IoOutputDword(0xcfc , temp );
      
      PciWriteDword(BUS_0, DEV_0, FUNC_0, 0x80, 0x00000100);
    
}

void BootDetectMemorySize(void)
{
      int i;
      int result;
      unsigned char *fillstring;
      void *membasetop = (void*)((64*1024*1024));
      void *membaselow = (void*)((0));
      
      (*(unsigned int*)(0xFD000000 + 0x100200)) = 0x03070103 ;
      (*(unsigned int*)(0xFD000000 + 0x100204)) = 0x11448000 ;
        
        PciWriteDword(BUS_0, DEV_0, FUNC_0, 0x84, 0x7FFFFFF);  // 128 MB
        
      xbox_ram = 64;    
      fillstring = malloc(0x200);
      memset(fillstring,0xAA,0x200);
      memset(membasetop,0xAA,0x200);
      asm volatile ("wbinvd\n");
      
      if (!memcmp(membasetop,fillstring,0x200)) {
            // Looks like there is memory .. maybe a 128MB box 
            memset(fillstring,0x55,0x200);
            memset(membasetop,0x55,0x200);
            asm volatile ("wbinvd\n");
            if (!memcmp(membasetop,fillstring,0x200)) {
                  // Looks like there is memory 
                  // now we are sure, we set memory
                        if (memcmp(membaselow,fillstring,0x200) == 0) {
                              // Hell, we find the Test-string at 0x0 too !
                              xbox_ram = 64;
                        } else {
                              xbox_ram = 128;
                        }
            }           
            
      }
      if (xbox_ram == 64) {
            PciWriteDword(BUS_0, DEV_0, FUNC_0, 0x84, 0x3FFFFFF);  // 64 MB
      }
      else if (xbox_ram == 128) {
            PciWriteDword(BUS_0, DEV_0, FUNC_0, 0x84, 0x7FFFFFF);  // 128 MB
      }
        free(fillstring);
}

void BootPciPeripheralInitialization()
{

      __asm__ __volatile__ ( "cli" );

      PciWriteDword(BUS_0, DEV_1, 0, 0x80, 2);  // v1.1 2BL kill ROM area
      if(PciReadByte(BUS_0, DEV_1, 0, 0x8)>=0xd1) { // check revision
            PciWriteDword(BUS_0, DEV_1, 0, 0xc8, 0x8f00);  // v1.1 2BL <-- death
      }

      // Bus 0, Device 0, Function 0 = PCI Bridge Device - Host Bridge
      PciWriteDword(BUS_0, DEV_0, FUNC_0, 0x48, 0x00000114);
      PciWriteDword(BUS_0, DEV_0, FUNC_0, 0x44, 0x80000000); // new 2003-01-23 ag  trying to get single write actions on TSOP
      PciWriteByte(BUS_0, DEV_0, FUNC_0, 0x87, 3); // kern 8001FC21
      PciWriteByte(BUS_0, DEV_0, 8, 0, 0x42);       // Xbeboot-compare
      
      IoOutputByte(0x2e, 0x55);
      IoOutputByte(0x2e, 0x26);
      IoOutputByte(0x61, 0xff);
      IoOutputByte(0x92, 0x01);
      IoOutputByte(0xcf9, 0x0);     // Reset Port
        IoOutputByte(0x43, 0x36);               // Timer 0 (system time): mode 3
        IoOutputByte(0x40, 0xFF);              // 18.2Hz (1.19318MHz/65535)
        IoOutputByte(0x40, 0xFF);
        IoOutputByte(0x43, 0x54);               // Timer 1 (ISA refresh): mode 2
        IoOutputByte(0x41, 18);                // 64KHz (1.19318MHz/18)
        IoOutputByte(0x00, 0);                 // clear base address 0
        IoOutputByte(0x00, 0);
        IoOutputByte(0x01, 0);                 // clear count 0
        IoOutputByte(0x01, 0);
        IoOutputByte(0x02, 0);                 // clear base address 1
        IoOutputByte(0x02, 0 );
        IoOutputByte(0x03, 0);                 // clear count 1
        IoOutputByte(0x03, 0);
        IoOutputByte(0x04, 0);                 // clear base address 2
        IoOutputByte(0x04, 0);
        IoOutputByte(0x05, 0);                 // clear count 2
        IoOutputByte(0x05, 0);
        IoOutputByte(0x06, 0);                 // clear base address 3
        IoOutputByte(0x06, 0);
        IoOutputByte(0x07, 0);                 // clear count 3
        IoOutputByte(0x07, 0);
        IoOutputByte(0x0B, 0x40);               // set channel 0 to single mode, verify transfer
        IoOutputByte(0x0B, 0x41);               // set channel 1 to single mode, verify transfer
        IoOutputByte(0x0B, 0x42);               // set channel 2 to single mode, verify transfer
        IoOutputByte(0x0B, 0x43);               // set channel 3 to single mode, verify transfer
        IoOutputByte(0x08, 0);                 // enable controller
        IoOutputByte(0xC0, 0);                 // clear base address 0
        IoOutputByte(0xC0, 0);
        IoOutputByte(0xC2, 0);                 // clear count 0
        IoOutputByte(0xC2, 0);
        IoOutputByte(0xC4, 0);                // clear base address 1
        IoOutputByte(0xC4, 0);
        IoOutputByte(0xC6, 0);                 // clear count 1
        IoOutputByte(0xC6, 0);
        IoOutputByte(0xC8, 0);                 // clear base address 2
        IoOutputByte(0xC8, 0);
        IoOutputByte(0xCA, 0);                 // clear count 2
        IoOutputByte(0xCA, 0);
        IoOutputByte(0xCC, 0);                 // clear base address 3
        IoOutputByte(0xCC, 0);
        IoOutputByte(0xCE, 0);                 // clear count 3
        IoOutputByte(0xCE, 0);
        IoOutputByte(0xD6, 0xC0);         // set channel 0 to cascade mode
        IoOutputByte(0xD6, 0xC1);         // set channel 1 to single mode, verify transfer
        IoOutputByte(0xD6, 0xC2);         // set channel 2 to single mode, verify transfer
        IoOutputByte(0xD6, 0xC3);         // set channel 3 to single mode, verify transfer
        IoOutputByte(0xD0, 0);                 // enable controller
        IoOutputByte(0x0E, 0);                 // enable DMA0 channels
        IoOutputByte(0xD4, 0);                 // clear chain 4 mask

      /* Setup the real time clock */
      CMOS_WRITE(RTC_CONTROL_DEFAULT, RTC_CONTROL);
      
      /* Setup the frequency it operates at */
      CMOS_WRITE(RTC_FREQ_SELECT_DEFAULT, RTC_FREQ_SELECT);
      
      /* Make certain we have a valid checksum */
      //rtc_set_checksum(PC_CKS_RANGE_START,
      //PC_CKS_RANGE_END,PC_CKS_LOC);
      /* Clear any pending interrupts */
      (void) CMOS_READ(RTC_INTR_FLAGS);

      // configure ACPI hardware to generate interrupt on PIC-chip pin6 action (via EXTSMI#)
      IoOutputByte(0x80ce, 0x08);  // from 2bl RI#
      IoOutputByte(0x80c0, 0x08);  // from 2bl SMBUSC
      IoOutputByte(0x8004, IoInputByte(0x8004)|1);  // KERN: SCI enable == SCI interrupt generated
      IoOutputWord(0x8022, IoInputByte(0x8022)|2);  // KERN: Interrupt enable register, b1 RESERVED in AMD docs
      IoOutputWord(0x8023, IoInputByte(0x8023)|2);  // KERN: Interrupt enable register, b1 RESERVED in AMD docs
      IoOutputByte(0x8002, IoInputByte(0x8002)|1);  // KERN: Enable SCI interrupt when timer status goes high
      IoOutputWord(0x8028, IoInputByte(0x8028)|1);  // KERN: setting readonly trap event???
 
      I2CTransmitWord(0x10, 0x0b00); // Allow audio
      //I2CTransmitWord(0x10, 0x0b01); // GAH!!!  Audio Mute!
      
      // Bus 0, Device 1, Function 0 = nForce HUB Interface - ISA Bridge
      PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x6c, 0x0e065491);
      PciWriteByte(BUS_0, DEV_1, FUNC_0, 0x6a, 0x0003); // kern ??? gets us an int3?  vsync req
      PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x64, 0x00000b0c);
      PciWriteByte(BUS_0, DEV_1, FUNC_0, 0x81, PciReadByte(BUS_0, DEV_1, FUNC_0, 0x81)|8);
      PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x4c, 0x000f0000); // RTC clocks enable?  2Hz INT8?


      // Bus 0, Device 9, Function 0 = nForce ATA Controller
      PciWriteDword(BUS_0, DEV_9, FUNC_0, 0x20, 0x0000ff61);      // (BMIBA) Set Busmaster regs I/O base address 0xff60
      PciWriteDword(BUS_0, DEV_9, FUNC_0, 4, PciReadDword(BUS_0, DEV_9, FUNC_0, 4)|5); // 0x00b00005 );
      PciWriteDword(BUS_0, DEV_9, FUNC_0, 8, PciReadDword(BUS_0, DEV_9, FUNC_0, 8)&0xfffffeff); // 0x01018ab1 ); // was fffffaff
      PciWriteDword(BUS_0, DEV_9, FUNC_0, 0x58, 0x20202020); // kern1.1
      PciWriteDword(BUS_0, DEV_9, FUNC_0, 0x60, 0x00000000); // kern1.1
      PciWriteDword(BUS_0, DEV_9, FUNC_0, 0x50, 0x00000002);  // without this there is no register footprint at IO 1F0
      PciWriteDword(BUS_0, DEV_9, FUNC_0, 0x2c, 0x00000000); // frankenregister from xbe boot
      PciWriteDword(BUS_0, DEV_9, FUNC_0, 0x40, 0x00000000); // frankenregister from xbe boot
      
      // below reinstated by frankenregister compare with xbe boot
      PciWriteDword(BUS_0, DEV_9, FUNC_0, 0x60, 0xC0C0C0C0); // kern1.1 <--- this was in kern1.1 but is FATAL for good HDD access

      // Bus 0, Device 4, Function 0 = nForce MCP Networking Adapter - all verified with kern1.1
      PciWriteDword(BUS_0, DEV_4, FUNC_0, 4, PciReadDword(BUS_0, DEV_4, FUNC_0, 4) | 7 );
      PciWriteDword(BUS_0, DEV_4, FUNC_0, 0x10, 0xfef00000); // memory base address 0xfef00000
      PciWriteDword(BUS_0, DEV_4, FUNC_0, 0x14, 0x0000e001); // I/O base address 0xe000
      PciWriteDword(BUS_0, DEV_4, FUNC_0, 0x118-0xdc, (PciReadDword(BUS_0, DEV_4, FUNC_0, 0x3c) &0xffff0000) | 0x0004 );


      // Bus 0, Device 2, Function 0 = nForce OHCI USB Controller - all verified with kern 1.1
      PciWriteDword(BUS_0, DEV_2, FUNC_0, 4, PciReadDword(BUS_0, DEV_2, FUNC_0, 4) | 7 );
      PciWriteDword(BUS_0, DEV_2, FUNC_0, 0x10, 0xfed00000);      // memory base address 0xfed00000
      PciWriteDword(BUS_0, DEV_2, FUNC_0, 0x3c, (PciReadDword(BUS_0, DEV_2, FUNC_0, 0x3c) &0xffff0000) | 0x0001 );
      PciWriteDword(BUS_0, DEV_2, FUNC_0, 0x50, 0x0000000f);

      // Bus 0, Device 3, Function 0 = nForce OHCI USB Controller - verified with kern1.1
      PciWriteDword(BUS_0, DEV_3, FUNC_0, 4, PciReadDword(BUS_0, DEV_3, FUNC_0, 4) | 7 );
      PciWriteDword(BUS_0, DEV_3, FUNC_0, 0x10, 0xfed08000);      // memory base address 0xfed08000
      PciWriteDword(BUS_0, DEV_3, FUNC_0, 0x3c, (PciReadDword(BUS_0, DEV_3, FUNC_0, 0x3c) &0xffff0000) | 0x0009 );
      PciWriteDword(BUS_0, DEV_3, FUNC_0, 0x50, 0x00000030);  // actually u8?

      // Bus 0, Device 6, Function 0 = nForce Audio Codec Interface - verified with kern1.1
      PciWriteDword(BUS_0, DEV_6, FUNC_0, 4, PciReadDword(BUS_0, DEV_6, FUNC_0, 4) | 7 );
      PciWriteDword(BUS_0, DEV_6, FUNC_0, 0x10, (PciReadDword(BUS_0, DEV_6, FUNC_0, 0x10) &0xffff0000) | 0xd001 );  // MIXER at IO 0xd000
      PciWriteDword(BUS_0, DEV_6, FUNC_0, 0x14, (PciReadDword(BUS_0, DEV_6, FUNC_0, 0x14) &0xffff0000) | 0xd201 );  // BusMaster at IO 0xD200
      PciWriteDword(BUS_0, DEV_6, FUNC_0, 0x18, 0xfec00000);      // memory base address 0xfec00000

      // frankenregister from working Linux driver
      PciWriteDword(BUS_0, DEV_6, FUNC_0, 8, 0x40100b1 );
      PciWriteDword(BUS_0, DEV_6, FUNC_0, 0xc, 0x800000 );
      PciWriteDword(BUS_0, DEV_6, FUNC_0, 0x3c, 0x05020106 );
      PciWriteDword(BUS_0, DEV_6, FUNC_0, 0x44, 0x20001 );
      PciWriteDword(BUS_0, DEV_6, FUNC_0, 0x4c, 0x107 );

      // Bus 0, Device 5, Function 0 = nForce MCP APU
      PciWriteDword(BUS_0, DEV_5, FUNC_0, 4, PciReadDword(BUS_0, DEV_5, FUNC_0, 4) | 7 );
      PciWriteDword(BUS_0, DEV_5, FUNC_0, 0x3c, (PciReadDword(BUS_0, DEV_5, FUNC_0, 0x3c) &0xffff0000) | 0x0005 );
      PciWriteDword(BUS_0, DEV_5, FUNC_0, 0x10, 0xfe800000);      // memory base address 0xfe800000

      // Bus 0, Device 1, Function 0 = nForce HUB Interface - ISA Bridge
      PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x8c, (PciReadDword(BUS_0, DEV_1, FUNC_0, 0x8c) &0xfbffffff) | 0x08000000 );

      // ACPI pin init
      IoOutputDword(0x80b4, 0xffff);  // any interrupt resets ACPI system inactivity timer
      IoOutputByte(0x80cc, 0x08); // Set EXTSMI# pin to be pin function
      IoOutputByte(0x80cd, 0x08); // Set PRDY pin on ACPI to be PRDY function
      IoOutputByte(0x80cf, 0x08); // Set C32KHZ pin to be pin function
      IoOutputWord(0x8020, IoInputWord(0x8020)|0x200); // ack any preceding ACPI int
      
      // Bus 0, Device 1e, Function 0 = nForce AGP Host to PCI Bridge
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 4, PciReadDword(BUS_0, DEV_1e, FUNC_0, 4) | 7 );
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x18, (PciReadDword(BUS_0, DEV_1e, FUNC_0, 0x18) &0xffffff00));
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x3c, 7);  // trying to get video irq

      // frankenregister xbe load correction to match cromwell load
      // controls requests for memory regions
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x0c, 0xff019ee7);
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x10, 0xbcfaf7e7);
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x14, 0x0101fafa);
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x1c, 0x02a000f0);    // Coud this be the BASE Video Address ?
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x20, 0xfdf0fd00);
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x24, 0xf7f0f000);
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x28, 0x8e7ffcff);
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x2c, 0xf8bfef87);
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x30, 0xdf758fa3);
      PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x38, 0xb785fccc);

      // Bus 1, Device 0, Function 0 = NV2A GeForce3 Integrated GPU
      PciWriteDword(BUS_1, DEV_0, FUNC_0, 4, PciReadDword(BUS_1, DEV_0, FUNC_0, 4) | 7 );
      PciWriteDword(BUS_1, DEV_0, FUNC_0, 0x3c, (PciReadDword(BUS_1, DEV_0, FUNC_0, 0x3c) &0xffff0000) | 0x0103 );  // should get vid irq!!
      PciWriteDword(BUS_1, DEV_0, FUNC_0, 0x4c, 0x00000114);

      // frankenregisters so Xromwell matches Cromwell
      PciWriteDword(BUS_1, DEV_0, FUNC_0, 0x0c, 0x0);
      PciWriteDword(BUS_1, DEV_0, FUNC_0, 0x18, 0x08);
}

Generated by  Doxygen 1.6.0   Back to index