void atiSbirqSmi(void) { u32 base, temp; pcitag_t sm_dev = _pci_make_tag(0, 20, 0);; base = _pci_conf_read(sm_dev, 0x74) & 0xffffffe0; base |= 0xa0000000; *(volatile u32 *)base = 0x10; temp = *(volatile u32 *)(base + 0x10); if (temp & 0x100) { // entry0 enable ? *(volatile u32 *)base = 0x14; temp = *(volatile u32 *)(base + 0x14); if (temp & 0x100) { // entryr2 enable ? *(volatile u32 *)base = 0x20; temp = *(volatile u32 *)(base + 0x20); if (temp & 0x100) { // entryr8 enable ? /*flip-flop PIC interrupt maskbits */ u8 reg21; reg21 = linux_inb(0x21); linux_outb(reg21 | 1, 0x21); linux_outb(reg21, 0x21); return ; } } } set_pm_enable_bits(0x03, 1, 0); return ; }
void init_8259A(int auto_eoi) { linux_outb(0xff, 0x21); /* mask all of 8259A-1 */ linux_outb(0xff, 0xA1); /* mask all of 8259A-2 */ /* * linux_outb_p - this has to work on a wide range of PC hardware. */ linux_outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */ linux_outb_p(0x00, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x00-0x07 */ linux_outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */ if (auto_eoi) linux_outb_p(0x03, 0x21); /* master does Auto EOI */ else linux_outb_p(0x01, 0x21); /* master expects normal EOI */ linux_outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */ linux_outb_p(0x08, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x08-0x0f */ linux_outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */ linux_outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode is to be investigated) */ }
void hard_reset(void) { set_bios_reset(); /* Try rebooting through port 0xcf9 */ /* Actually it is not a real hard_reset --- it only resets coherent link table, but * does not reset link freq and width */ linux_outb((0 << 3) | (0 << 2) | (1 << 1), 0xcf9); linux_outb((0 << 3) | (1 << 2) | (1 << 1), 0xcf9); }
/* * sata_drive_detect : * detect the sata drive and put it into proper config */ static void sata_drive_detecting(void) { int ports = 4, count; int timeout; u32 base, reg32, reg04; u32 val; pcitag_t sata_dev = _pci_make_tag(0, 18, 0); PRINTF_DEBUG(); reg04 = _pci_conf_read(sata_dev, 0x04); /* force memory and io enabled */ set_sbcfg_enable_bits(sata_dev, 0x04, 0x03 << 0, 0x03 << 0); /* ahci base addr */ base = (_pci_conf_read(sata_dev, 0x24) & 0xfffffff0) | 0xA0000000; DEBUG_INFO("ahci base addr is %x \n", base); /* 4/PM 3/SM 2/PS 1/SS */ while(ports){ count = 3; while(count){ /* judge is the phy and communication is ok */ delay(1000); // delay 1 ms reg32 = *(volatile u32 *)(base + 0x128); DEBUG_INFO("sata status : reg128 0x%x\n", reg32); if((reg32 & 0x0000000F) == 0x03){ goto drive_is_stable; } /* test if bsy bit is set, it means the drive is connected */ reg32 = *(volatile u32 *)(base + 0x120); if((reg32 & 0x80) == 0){ val = *(volatile u32 *)(base + 0x128); if((val & 0x0f) != 0x1){ goto drive_is_stable; } } count--; } /* now drive is not stable even after waitting for 1 sec,so downgrade to GEN 1 */ reg32 = *(volatile u32 *)(base + 0x12C); if((reg32 & 0x0f) == 0x10){ goto drive_is_stable; // jump if already GEN1 } /* store the sata status */ ati_sb_cfg.sb600_sata_sts |= (0x8 << ports); /* set to GEN1 : reset the status*/ reg32 = *(volatile u32 *)(base + 0x12C); reg32 = (reg32 & 0x0f) | 0x10; *(volatile u32 *)(base + 0x12C) = reg32; reg32 |= 0x01; *(volatile u32 *)(base + 0x12C) = reg32; // force 00B delay(1000); //wait 1 ms reg32 = *(volatile u32 *)(base + 0x12C); reg32 &= 0xfe; *(volatile u32 *)(base + 0x12C) = reg32; /* re detect the device again */ ports--; continue; drive_is_stable: reg32 = *(volatile u32 *)(base + 0x128); if ((reg32 & 0x0f) == 0x3){ u16 sata_bar; sata_bar = _pci_conf_readn(sata_dev, 0x10, 2); if(ports & 0x01){ sata_bar = _pci_conf_readn(sata_dev, 0x18, 2); } sata_bar &= ~(7); sata_bar += 0x06; if(ports <= 2){ val |= 0xA0; }else{ val |= 0xB0; } linux_outb(val, sata_bar); sata_bar++; timeout = 3000; while(timeout--){ val = linux_inb(sata_bar); val &= 0x88000000; if(val == 0x00){ break; } delay(10 * 1000); } /* update the status */ ati_sb_cfg.sb600_sata_sts ^= (1 << (4 - ports)); } base += 0x80; // increase status offset by 80h for next port --ports; } /* while(i) */ /* restore PCI conf cmd */ _pci_conf_write(sata_dev, 0x04, reg04); return; }
int tgt_i2cwrite(int type, unsigned char *addr, int addrlen, unsigned char reg, unsigned char *buf, int count) { int i; int device, offset; char c; device = addr[0]; offset = reg; device &= ~1; switch(type) { case I2C_SINGLE: for(i = 0; i < count; i++) { linux_outb(device, SMBUS_HOST_ADDRESS); linux_outb(offset+i, SMBUS_HOST_COMMAND); linux_outb(0x8, SMBUS_HOST_CONTROL); if( (c = linux_inb(SMBUS_HOST_STATUS) ) & 0x1f) { linux_outb(c, SMBUS_HOST_STATUS); } linux_outb(buf[i], SMBUS_HOST_DATA0); linux_outb(linux_inb(SMBUS_HOST_CONTROL) | 0x40, SMBUS_HOST_CONTROL); while(linux_inb(SMBUS_HOST_STATUS) & SMBUS_HOST_STATUS_BUSY); if( (c = linux_inb(SMBUS_HOST_STATUS) ) & 0x1f) { linux_outb(c,SMBUS_HOST_STATUS); } } break; case I2C_SMB_BLOCK: linux_outb(device, SMBUS_HOST_ADDRESS); //0xd3 linux_outb(offset, SMBUS_HOST_COMMAND); linux_outb(count, SMBUS_HOST_DATA0); linux_outb(0x14, SMBUS_HOST_CONTROL); //0x14 if( (c = linux_inb(SMBUS_HOST_STATUS) ) & 0x1f) { linux_outb(c, SMBUS_HOST_STATUS); } for(i=0;i<count;i++) linux_outb(buf[i], SMBUS_HOST_DATA1+1); c = linux_inb(SMBUS_HOST_CONTROL); linux_outb(c|0x40, SMBUS_HOST_CONTROL); while(linux_inb(SMBUS_HOST_STATUS) & SMBUS_HOST_STATUS_BUSY); if( (c = linux_inb(SMBUS_HOST_STATUS) ) & 0x1f) { linux_outb(c, SMBUS_HOST_STATUS); } break; default: return -1; break; } return count; }
void set_crt_reg(unsigned char index,unsigned char data) { linux_outb(index,crt_index); linux_outb(data,crt_data); }
unsigned char get_crt_reg(unsigned char index) { linux_outb(index,crt_index); return linux_inb(crt_data); }
void soft_reset(void) { set_bios_reset(); /* link reset */ linux_outb(0x06, 0x0cf9); }
void soft_pci_reset_smi(void) { /* reset system through 0xCF9 reset port.*/ linux_outb(6, 0xcf9); }