void WriteSeqReg(uint8 index, uint8 value) { if (gInfo.sharedInfo->chipType == S3_TRIO64) { WritePIO_8(0x3c4, index); WritePIO_8(0x3c5, value); } else { OUTREG8(0x83c4, index); OUTREG8(0x83c5, value); } }
void WriteSeqReg(uint8 index, uint8 value, uint8 mask) { // Write a value to a Sequencer reg using a mask. The mask selects the // bits to be modified. if (gInfo.sharedInfo->chipType == S3_TRIO64) { WritePIO_8(0x3c4, index); WritePIO_8(0x3c5, (ReadPIO_8(0x3c5) & ~mask) | (value & mask)); } else { OUTREG8(0x83c4, index); OUTREG8(0x83c5, (INREG8(0x83c5) & ~mask) | (value & mask)); } }
status_t Mach64_SetDisplayMode(const DisplayModeEx& mode) { // The code to actually configure the display. // All the error checking must be done in ProposeDisplayMode(), // and assume that the mode values we get here are acceptable. SharedInfo& si = *gInfo.sharedInfo; if (si.displayType == MT_VGA) { // Chip is connected to a monitor via a VGA connector. SetCrtcRegisters(mode); SetClockRegisters(mode); if (si.chipType >= MACH64_264VTB) SetDSPRegisters(mode); } else { // Chip is connected to a laptop LCD monitor; or via a DVI interface. uint16 vesaMode = GetVesaModeNumber(display_mode(mode), mode.bitsPerPixel); if (vesaMode == 0) return B_BAD_VALUE; status_t status = ioctl(gInfo.deviceFileDesc, ATI_SET_VESA_DISPLAY_MODE, &vesaMode, sizeof(vesaMode)); if (status != B_OK) return status; } Mach64_AdjustFrame(mode); // Initialize the palette so that the various color depths will display // the correct colors. OUTREGM(DAC_CNTL, DAC_8BIT_EN, DAC_8BIT_EN); OUTREG8(DAC_MASK, 0xff); OUTREG8(DAC_W_INDEX, 0); // initial color index for (int i = 0; i < 256; i++) { OUTREG8(DAC_DATA, i); OUTREG8(DAC_DATA, i); OUTREG8(DAC_DATA, i); } Mach64_EngineInit(mode); return B_OK; }
//------------------------------------------------------------------------------ // VOID OALTimerSetCount(UINT32 count) { UINT32 retVal = 0; UINT32 setDelay = 0; SH4_TMU_REGS *pTMURegs = OALPAtoUA(SH4_REG_PA_TMU); // Stop Timer OUTREG8(&pTMURegs->TSTR, INREG8(&pTMURegs->TSTR) & ~TMU_TSTR_STR0); // Update the count OUTREG32(&pTMURegs->TCNT0, count + setDelay - 1); // Start Timer OUTREG8(&pTMURegs->TSTR, INREG8(&pTMURegs->TSTR) | TMU_TSTR_STR0); }
//------------------------------------------------------------------------------ // // Function: BSPIntrActiveIrq // // This function is called from interrupt handler to give BSP chance to // translate IRQ in case of secondary interrupt controller. // UINT32 BSPIntrActiveIrq(UINT32 irq) { UINT8 data; UINT32 doneIrq; OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+BSPIntrActiveIrq(%d)\r\n", irq)); switch(irq) { case IRQ_GPIO: // Check whether alarm happen if(OALRTCAlarmIntrHandler() == FALSE) { irq = OAL_INTR_IRQ_UNDEFINED; } // Acknowledge GPIO interrupt OUTREG32(&g_pVRC5477Regs->GIUINSTAT, 0xffffffff); // Re-enable IRQ_GPIO interrupt on VRC5477 doneIrq = IRQ_GPIO; OALIntrDoneIrqs(1, &doneIrq); break; case IRQ_INTC: // Read PIC1 interrupt OUTREG8(&g_pPIC1Regs->ctrl, 0x0E); data = INREG8(&g_pPIC1Regs->data) & 0x07; if (data != 2) { irq = IRQ_PIC_0 + data; SETREG8(&g_pPIC1Regs->mask, 1 << data); } else { // Read PIC2 interrupt OUTREG8(&g_pPIC2Regs->ctrl, 0x0E); data = INREG8(&g_pPIC2Regs->data) & 0x07; irq = IRQ_PIC_8 + data; SETREG8(&g_pPIC2Regs->mask, 1 << data); // End interrupt on PIC2 OUTREG8(&g_pPIC2Regs->ctrl, 0x20); } // End interrupt on PIC1 OUTREG8(&g_pPIC1Regs->ctrl, 0x20); // Re-enable IRQ_INTC interrupt on VRC5477 doneIrq = IRQ_INTC; OALIntrDoneIrqs(1, &doneIrq); break; } OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-BSPIntrActiveIrq(%d)\r\n", irq)); return irq; }
//------------------------------------------------------------------------------ // // Function: OALIntrEnableIrq/BSPIntrEnableIrq // // This function enable interrupt identified by IRQ. If implementation uses // platform callbacks it will call BSPIntrEnableIrq before IRQ is enabled in // hardware. The BSPIntrEnableIrq returns IRQ used for interrupt controller // chaining. // BOOL OALIntrEnableIrqs(UINT32 count, const UINT32 *pIrqs) { UINT32 irq, i; BOOL retVal = TRUE; SH4_RTC_REGS *pRTCRegs = OALPAtoUA(SH4_REG_PA_RTC); OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OALIntrEnableIrqs(%d, 0x%08x)\r\n", count, pIrqs)); for(i = 0; i < count; i++) { #ifndef OAL_BSP_CALLBACKS irq = pIrqs[i]; #else // Give the BSP a chance to enable the irq irq = BSPIntrEnableIrq(pIrqs[i]); #endif if(irq == OAL_INTR_IRQ_UNDEFINED) continue; switch(irq) { case IRQ_RTC_ATI: OUTREG8(&pRTCRegs->RCR1, INREG8(&pRTCRegs->RCR1) | RTC_RCR1_AIE); OALMSG(OAL_INTR&&OAL_VERBOSE, (L"INFO: IRQ_RTC_ATI Enabled\r\n")); break; default: OALMSG(OAL_ERROR, (L"ERROR: Unable to enable IRQ %d\r\n", irq)); retVal = FALSE; } } OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OALIntrEnableIrqs(rc = %d)\r\n", retVal)); return retVal; }
void WriteReg8(uint32 addr, uint8 value) { if (gInfo.sharedInfo->chipType == S3_TRIO64) WritePIO(addr, 1, value); else OUTREG8(addr, value); }
//------------------------------------------------------------------------------ // // Function: OALIntrDisableIrq/BSPIntrDisableIrq // // This function disable interrupt identified by IRQ. If implementation uses // platform callbacks it will call BSPIntrDisableIrq before IRQ is disabled in // hardware. The BSPIntrEnableIrq returns IRQ used for interrupt controller // chaining if it is suitable to disable it. // VOID OALIntrDisableIrqs(UINT32 count, const UINT32 *pIrqs) { UINT32 irq, i; SH4_RTC_REGS *pRTCRegs = OALPAtoUA(SH4_REG_PA_RTC); OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OALIntrDisableIrqs(%d, 0x%08x)\r\n", count, pIrqs)); for(i = 0; i < count; i++) { #ifndef OAL_BSP_CALLBACKS irq = pIrqs[i]; #else irq = BSPIntrDisableIrq(pIrqs[i]); #endif if(irq == OAL_INTR_IRQ_UNDEFINED) continue; switch(irq) { case IRQ_RTC_ATI: OUTREG8(&pRTCRegs->RCR1, INREG8(&pRTCRegs->RCR1) & ~RTC_RCR1_AIE); OALMSG(OAL_INTR&&OAL_VERBOSE, (L"INFO: IRQ_RTC_ATI Disabled\r\n")); break; default: OALMSG(OAL_ERROR, (L"ERROR: Unable to disable IRQ %d\r\n", irq)); } } OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OALIntrDisableIrqs()\r\n")); }
void WriteMiscOutReg(uint8 value) { if (gInfo.sharedInfo->chipType == S3_TRIO64) WritePIO_8(0x3c2, value); else OUTREG8(0x83c2, value); }
//------------------------------------------------------------------------------ // // Function: OALIntrDoneIrq/BSPIntrDoneIrq // // This function finish interrupt identified by IRQ. If implementation uses // platform callbacks it will call BSPIntrDoneIrq before IRQ is enabled in // hardware. The BSPIntrDoneIrq returns IRQ used for interrupt controller // chaining if it is suitable to finish it. In most cases implementation will // for both function will be similar to OALIntrEnableIrq/BSPIntrEnableIrq. // VOID OALIntrDoneIrqs(UINT32 count, const UINT32 *pIrqs) { UINT32 irq, i; SH4_RTC_REGS *pRTCRegs = OALPAtoUA(SH4_REG_PA_RTC); OALMSG(OAL_VERBOSE&&OAL_FUNC, (L"+OALIntrDoneIrqs(%d, 0x%08x)\r\n", count, pIrqs)); for(i = 0; i < count; i++) { #ifndef OAL_BSP_CALLBACKS irq = pIrqs[i]; #else irq = BSPIntrDoneIrq(pIrqs[i]); #endif if(irq == OAL_INTR_IRQ_UNDEFINED) continue; switch(irq) { case IRQ_RTC_ATI: // Clear alarm flag but do not reenable interrupt for the RTC Alarm // since that will happen the next time OEMSetAlarmTime is called OUTREG8(&pRTCRegs->RCR1, (INREG8(&pRTCRegs->RCR1) & ~(RTC_RCR1_AF))); break; default: OALMSG(OAL_ERROR, (L"ERROR: Unable to disable IRQ %d\r\n", irq)); } } OALMSG(OAL_VERBOSE&&OAL_FUNC, (L"-OALIntrDoneIrqs()\r\n")); }
void serial_setbrg (void) { unsigned short UART_DIVISOR_LATCH = DEVICE_CLOCK / 16 / DEBUG_UART_BAUDRATE; SETREG8( (DEBUG_UART_BASE + UART_ULCR_OFFSET), ULCR_DLAB ); OUTREG8( (DEBUG_UART_BASE + UART_UDLLR_OFFSET), UART_DIVISOR_LATCH & 0xFF ); OUTREG8( (DEBUG_UART_BASE + UART_UDLHR_OFFSET), (UART_DIVISOR_LATCH >> 8) & 0xFF ); CLRREG8( (DEBUG_UART_BASE + UART_ULCR_OFFSET), ULCR_DLAB ); }
void serial_putc (const char c) { #if 1 if (c == '\n') serial_putc ('\r'); /* Wait for fifo to shift out some bytes */ while ( !(INREG8((DEBUG_UART_BASE + UART_ULSR_OFFSET))&ULSR_TDRQ ) ); OUTREG8((DEBUG_UART_BASE + UART_UTHR_OFFSET), c); #endif }
//------------------------------------------------------------------------------ // // Function: OEMWriteDebugByte // // Write byte to debug serial port. // VOID OEMWriteDebugByte(UINT8 ch) { VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); // wait FIFO empty while (!(INREG8(&pVRC5477Regs->UARTLSR0) & UART_LSR_THRE)); // send OUTREG8(&pVRC5477Regs->UARTTHR0, ch); }
/* * This routine could be implemented by taking the addresses * written to the GATT, and flushing them individually. However * currently it just flushes the whole table. Which is probably * more efficent, since agp_memory blocks can be a large number of * entries. */ static void serverworks_tlbflush(struct agp_memory *temp) { OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 1); while(INREG8(serverworks_private.registers, SVWRKS_POSTFLUSH) == 1) cpu_relax(); OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 1); while(INREG32(serverworks_private.registers, SVWRKS_DIRFLUSH) == 1) cpu_relax(); }
uint8 ReadSeqReg(uint8 index) { if (gInfo.sharedInfo->chipType == S3_TRIO64) { WritePIO_8(0x3c4, index); return ReadPIO_8(0x3c5); } OUTREG8(0x83c4, index); return INREG8(0x83c5); }
//------------------------------------------------------------------------------ // Start timer 2 (parameter - interrupt interval in micro-seconds) //------------------------------------------------------------------------------ void SHxStartTimer2 (DWORD dwUSec) { DWORD dwCount; volatile SH4_TMU_REGS *pTMURegs = OALPAtoUA(SH4_REG_PA_TMU); if (!dwUSec) { // // Use default rate (1 MS) // dwUSec = 1000; } else if (dwUSec < 20) { // // Rate specified: at least 20us // dwUSec = 20; } dwCount = (dwUSec * g_oalTimer.countsPerMSec) / 1000; // // Init timer2 and enable timer2 interrupt // // make sure timer2 is topped OUTREG8(&pTMURegs->TSTR, INREG8(&pTMURegs->TSTR) & ~TMU_TSTR_STR2); // initialize timer constant and count register OUTREG32(&pTMURegs->TCOR2, dwCount); OUTREG32(&pTMURegs->TCNT2, dwCount); // enable timer2 interrupts // Enable underflow interrupts OUTREG16(&pTMURegs->TCR2, INREG16(&pTMURegs->TCR2) | TMU_TCR_UNIE); // Clear any pending interrupts OUTREG16(&pTMURegs->TCR2, INREG16(&pTMURegs->TCR2) & ~TMU_TCR_UNF); // start timer2 OUTREG8(&pTMURegs->TSTR, INREG8(&pTMURegs->TSTR) | TMU_TSTR_STR2); }
void Mach64_SetIndexedColors(uint count, uint8 first, uint8* colorData, uint32 flags) { // Set the indexed color palette for 8-bit color depth mode. (void)flags; // avoid compiler warning for unused arg if (gInfo.sharedInfo->displayMode.space != B_CMAP8) return ; OUTREG8(DAC_MASK, 0xff); OUTREG8(DAC_W_INDEX, first); // initial color index while (count--) { OUTREG8(DAC_DATA, colorData[0]); // red OUTREG8(DAC_DATA, colorData[1]); // green OUTREG8(DAC_DATA, colorData[2]); // blue colorData += 3; } }
status_t Rage128_SetDisplayMode(const DisplayModeEx& mode) { // The code to actually configure the display. // All the error checking must be done in ProposeDisplayMode(), // and assume that the mode values we get here are acceptable. DisplayParams params; // where computed parameters are saved if (gInfo.sharedInfo->displayType == MT_VGA) { // Chip is connected to a monitor via a VGA connector. if ( ! CalculateCrtcRegisters(mode, params)) return B_BAD_VALUE; if ( ! CalculatePLLRegisters(mode, params)) return B_BAD_VALUE; if ( ! CalculateDDARegisters(mode, params)) return B_BAD_VALUE; SetRegisters(params); } else { // Chip is connected to a laptop LCD monitor; or via a DVI interface. uint16 vesaMode = GetVesaModeNumber(display_mode(mode), mode.bitsPerPixel); if (vesaMode == 0) return B_BAD_VALUE; if (ioctl(gInfo.deviceFileDesc, ATI_SET_VESA_DISPLAY_MODE, &vesaMode, sizeof(vesaMode)) != B_OK) return B_ERROR; } Rage128_AdjustFrame(mode); // Initialize the palette so that color depths > 8 bits/pixel will display // the correct colors. // Select primary monitor and enable 8-bit color. OUTREGM(R128_DAC_CNTL, R128_DAC_8BIT_EN, R128_DAC_PALETTE_ACC_CTL | R128_DAC_8BIT_EN); OUTREG8(R128_PALETTE_INDEX, 0); // set first color index for (int i = 0; i < 256; i++) OUTREG(R128_PALETTE_DATA, (i << 16) | (i << 8) | i ); Rage128_EngineInit(mode); return B_OK; }
void WriteIndexedColor(uint8 index, uint8 red, uint8 green, uint8 blue) { // Write an indexed color. Argument index is the index (0-255) of the // color, and arguments red, green, & blue are the components of the color. // Note that although the Trio64V+ chip supports MMIO in nearly all areas, // it does not support MMIO for setting indexed colors; thus, use PIO to // set the indexed color. if (gInfo.sharedInfo->chipType == S3_TRIO64 || gInfo.sharedInfo->chipType == S3_TRIO64_VP) { WritePIO_8(0x3c8, index); // color index WritePIO_8(0x3c9, red); WritePIO_8(0x3c9, green); WritePIO_8(0x3c9, blue); } else { OUTREG8(0x83c8, index); // color index OUTREG8(0x83c9, red); OUTREG8(0x83c9, green); OUTREG8(0x83c9, blue); } }
//------------------------------------------------------------------------------ // // Function: VRC5477Uart1Send // UINT16 VRC5477Uart1Send(UINT8 *pData, UINT16 size) { VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); // This should not happen, but to be sure if (size == 0) return 0; // Wait FIFO empty while (!(INREG8(&pVRC5477Regs->UARTLSR1) & UART_LSR_THRE)); // Send OUTREG8(&pVRC5477Regs->UARTTHR1, *pData); // We send only one char per call return 1; }
int serial_init (void) { serial_setgpio(); OUTREG8( (DEBUG_UART_BASE + UART_UIER_OFFSET), 0 ); CLRREG8( (DEBUG_UART_BASE + UART_UFCR_OFFSET), UFCR_UME ); CLRREG8( (DEBUG_UART_BASE + UART_UISR_OFFSET), (UISR_RCVEIR|UISR_XMITIR) ); SETREG8( (DEBUG_UART_BASE + UART_ULCR_OFFSET), (ULCR_WLS_8BITS|ULCR_SBLS_1BIT) ); serial_setbrg(); SETREG8( (DEBUG_UART_BASE + UART_UFCR_OFFSET), (UFCR_FME | UFCR_RFRT | UFCR_TFRT | UFCR_UME | UFCR_RDTR_15) ); return 0; }
static int serverworks_configure(void) { struct aper_size_info_lvl2 *current_size; u32 temp; u8 enable_reg; u16 cap_reg; current_size = A_SIZE_LVL2(agp_bridge->current_size); /* Get the memory mapped registers */ pci_read_config_dword(agp_bridge->dev, serverworks_private.mm_addr_ofs, &temp); temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); serverworks_private.registers = (volatile u8 *) ioremap(temp, 4096); if (!serverworks_private.registers) { printk (KERN_ERR PFX "Unable to ioremap() memory.\n"); return -ENOMEM; } OUTREG8(serverworks_private.registers, SVWRKS_GART_CACHE, 0x0a); OUTREG32(serverworks_private.registers, SVWRKS_GATTBASE, agp_bridge->gatt_bus_addr); cap_reg = INREG16(serverworks_private.registers, SVWRKS_COMMAND); cap_reg &= ~0x0007; cap_reg |= 0x4; OUTREG16(serverworks_private.registers, SVWRKS_COMMAND, cap_reg); pci_read_config_byte(serverworks_private.svrwrks_dev, SVWRKS_AGP_ENABLE, &enable_reg); enable_reg |= 0x1; /* Agp Enable bit */ pci_write_config_byte(serverworks_private.svrwrks_dev, SVWRKS_AGP_ENABLE, enable_reg); serverworks_tlbflush(NULL); agp_bridge->capndx = pci_find_capability(serverworks_private.svrwrks_dev, PCI_CAP_ID_AGP); /* Fill in the mode register */ pci_read_config_dword(serverworks_private.svrwrks_dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); pci_read_config_byte(agp_bridge->dev, SVWRKS_CACHING, &enable_reg); enable_reg &= ~0x3; pci_write_config_byte(agp_bridge->dev, SVWRKS_CACHING, enable_reg); pci_read_config_byte(agp_bridge->dev, SVWRKS_FEATURE, &enable_reg); enable_reg |= (1<<6); pci_write_config_byte(agp_bridge->dev,SVWRKS_FEATURE, enable_reg); return 0; }
//------------------------------------------------------------------------------ // // Function: VRC5477Uart1Init // // Initialize debug serial port // BOOL VRC5477Uart1Init(KITL_SERIAL_INFO *pInfo) { BOOL rc = FALSE; VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); UINT16 divider; UINT8 lcr; // Check if config paramters are supportable if ( pInfo->baudRate < 9600 || pInfo->baudRate > 115200 || pInfo->dataBits != 8 || pInfo->stopBits == 0 || pInfo->parity > 2 ) goto cleanUp; // Input frequency is 1.8462MHz divider = (1846200/pInfo->baudRate + 7)/16; // Get LCR lcr = UART_LCR_8BIT; if (pInfo->stopBits > 1) lcr |= UART_LCR_2STP; if (pInfo->parity > 0) { lcr |= UART_LCR_PE; if (pInfo->parity > 1) lcr |= UART_LCR_EP; } // Disable interrupts OUTREG8(&pVRC5477Regs->UARTIER1, 0); // Set baud rate OUTREG8(&pVRC5477Regs->UARTLCR1, UART_LCR_DLAB); OUTREG8(&pVRC5477Regs->UARTDLL1, (UINT8)divider); OUTREG8(&pVRC5477Regs->UARTDLM1, (UINT8)(divider >> 8)); // 8 bit, 1 stop bit, no parity OUTREG8(&pVRC5477Regs->UARTLCR1, lcr); // Enable&reset FIFOs OUTREG8(&pVRC5477Regs->UARTFCR1, UART_FCR_EN|UART_FCR_RRST|UART_FCR_TRST); // Set DTR&RTS signals OUTREG8(&pVRC5477Regs->UARTMCR1, UART_MCR_DTR|UART_MCR_RTS); // Clear comm errors INREG8(&pVRC5477Regs->UARTLSR1); // Best size is full KITL_MTU... pInfo->bestSize = KITL_MTU; // Done rc = TRUE; cleanUp: return rc; }
void Rage128_SetIndexedColors(uint count, uint8 first, uint8* colorData, uint32 flags) { // Set the indexed color palette for 8-bit color depth mode. (void)flags; // avoid compiler warning for unused arg if (gInfo.sharedInfo->displayMode.space != B_CMAP8) return ; // Select primary monitor and enable 8-bit color. OUTREGM(R128_DAC_CNTL, R128_DAC_8BIT_EN, R128_DAC_PALETTE_ACC_CTL | R128_DAC_8BIT_EN); OUTREG8(R128_PALETTE_INDEX, first); // set first color index while (count--) { OUTREG(R128_PALETTE_DATA, ((colorData[0] << 16) // red | (colorData[1] << 8) // green | colorData[2])); // blue colorData += 3; } }
/* * This routine could be implemented by taking the addresses * written to the GATT, and flushing them individually. However * currently it just flushes the whole table. Which is probably * more efficent, since agp_memory blocks can be a large number of * entries. */ static void serverworks_tlbflush(struct agp_memory *temp) { unsigned long end; OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01); end = jiffies + 3*HZ; while(INREG8(serverworks_private.registers, SVWRKS_POSTFLUSH) == 0x01) { if((signed)(end - jiffies) <= 0) { printk(KERN_ERR PFX "Posted write buffer flush took more" "then 3 seconds\n"); } } OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001); end = jiffies + 3*HZ; while(INREG32(serverworks_private.registers, SVWRKS_DIRFLUSH) == 0x00000001) { if((signed)(end - jiffies) <= 0) { printk(KERN_ERR PFX "TLB flush took more" "then 3 seconds\n"); } } }
//------------------------------------------------------------------------------ // // Function: VRC5477Uart1Recv // UINT16 VRC5477Uart1Recv(UINT8 *pData, UINT16 size) { VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); UINT8 status; UINT16 count; count = 0; while (count < size) { // Get line status status = INREG8(&pVRC5477Regs->UARTLSR1); // If there ara no data, break loop if ((status & UART_LSR_DR) == 0) break; // On error clear FIFOs and break loop if ((status & 0x0E) != 0) { OUTREG8(&pVRC5477Regs->UARTFCR1, 0x07); count = 0; break; } // Get data *pData++ = INREG8(&pVRC5477Regs->UARTRBR1); count++; } return count; }
//------------------------------------------------------------------------------ // // Function: OEMInitDebugSerial // // Initialize debug serial port // BOOL OEMDebugInit() { VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); // Set baud rate OUTREG8(&pVRC5477Regs->UARTLCR0, UART_LCR_DLAB); OUTREG8(&pVRC5477Regs->UARTDLL0, BSP_UART_DSIUDLL); OUTREG8(&pVRC5477Regs->UARTDLM0, BSP_UART_DSIUDLM); // 8 bit, 1 stop bit, no parity OUTREG8(&pVRC5477Regs->UARTLCR0, UART_LCR_8BIT); // Enable FIFO OUTREG8(&pVRC5477Regs->UARTFCR0, UART_FCR_EN); // Pool OUTREG8(&pVRC5477Regs->UARTIER0, 0); // Set DTR/RTS signals OUTREG8(&pVRC5477Regs->UARTMCR0, UART_MCR_DTR|UART_MCR_RTS); return TRUE; }
static void SetClockRegisters(const DisplayModeEx& mode) { SharedInfo& si = *gInfo.sharedInfo; M64_Params& params = si.m64Params; int p; int postDiv; bool extendedDiv = false; uint32 pixelClock = mode.timing.pixel_clock; if (pixelClock > params.maxPixelClock) pixelClock = params.maxPixelClock; double q = ((pixelClock / 10.0) * params.refDivider) / (2.0 * params.refFreq); if (si.chipType >= MACH64_264VTB) { if (q > 255) { TRACE("SetClockRegisters(): Warning: q > 255\n"); q = 255; p = 0; postDiv = 1; } else if (q > 127.5) { p = 0; postDiv = 1; } else if (q > 85) { p = 1; postDiv = 2; } else if (q > 63.75) { p = 0; postDiv = 3; extendedDiv = true; } else if (q > 42.5) { p = 2; postDiv = 4; } else if (q > 31.875) { p = 2; postDiv = 6; extendedDiv = true; } else if (q > 21.25) { p = 3; postDiv = 8; } else if (q >= 10.6666666667) { p = 3; postDiv = 12; extendedDiv = true; } else { TRACE("SetClockRegisters(): Warning: q < 10.66666667\n"); p = 3; postDiv = 12; extendedDiv = true; } } else { if (q > 255) { TRACE("SetClockRegisters(): Warning: q > 255\n"); q = 255; p = 0; } else if (q > 127.5) p = 0; else if (q > 63.75) p = 1; else if (q > 31.875) p = 2; else if (q >= 16) p = 3; else { TRACE("SetClockRegisters(): Warning: q < 16\n"); p = 3; } postDiv = 1 << p; } uint8 fbDiv = uint8(q * postDiv); // With some chips such as those with ID's 4750 & 475A, the display has // ripples when using resolution 1440x900 at 60 Hz refresh rate. // Decrementing fbDiv by 1 seems to fix this problem. if (mode.timing.h_display == 1440 && pixelClock < 108000) fbDiv--; int clkNum = params.clockNumberToProgram; OUTREG8(CLOCK_CNTL, clkNum | CLOCK_STROBE); // Temporarily switch to accelerator mode. uint32 crtc_gen_cntl = INREG(CRTC_GEN_CNTL); if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN)) OUTREG(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN); // Reset VCLK generator. uint8 vclkCntl = Mach64_GetPLLReg(PLL_VCLK_CNTL); Mach64_SetPLLReg(PLL_VCLK_CNTL, vclkCntl | PLL_VCLK_RESET); // Set post-divider. uint8 tmp = Mach64_GetPLLReg(PLL_VCLK_POST_DIV); Mach64_SetPLLReg(PLL_VCLK_POST_DIV, (tmp & ~(0x03 << (2 * clkNum))) | (p << (2 * clkNum))); // Set feedback divider. Mach64_SetPLLReg(PLL_VCLK0_FB_DIV + clkNum, fbDiv); // Set extended post-divider. if (si.chipType >= MACH64_264VTB) { tmp = Mach64_GetPLLReg(PLL_XCLK_CNTL); if (extendedDiv) Mach64_SetPLLReg(PLL_XCLK_CNTL, tmp | (0x10 << clkNum)); else Mach64_SetPLLReg(PLL_XCLK_CNTL, tmp & ~(0x10 << clkNum)); } // End VCLK generator reset. Mach64_SetPLLReg(PLL_VCLK_CNTL, vclkCntl & ~PLL_VCLK_RESET); snooze(5000); INREG8(DAC_W_INDEX); // Clear DAC counter if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN)) OUTREG(CRTC_GEN_CNTL, crtc_gen_cntl); // Restore register // Save parameters that will be used for computing the DSP parameters. params.vClkPostDivider = postDiv; params.vClkFeedbackDivider = fbDiv; return; }
//------------------------------------------------------------------------------ // // Function: OALPCIInit // BOOL OALPCIInit() { VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); M1535_CFG_REGS *pM1535Regs = OALPAtoUA(BSP_REG_PA_M1535_CFG); OAL_PCI_LOCATION pciLoc; UINT32 u32; //---------------------------------------------------------------------- // External PCI //---------------------------------------------------------------------- // Cold reset OUTREG32(&pVRC5477Regs->PCICTL0H, PCI_CTRL_CRST); OALStall(100000); OUTREG32(&pVRC5477Regs->PCICTL0H, 0); OALStall(100000); // Setup windows OUTREG32(&pVRC5477Regs->PCIINIT00, BSP_PCI_INIT00); OUTREG32(&pVRC5477Regs->PCIW0, BSP_PCI_W0); OUTREG32(&pVRC5477Regs->PCIINIT10, BSP_PCI_INIT10); OUTREG32(&pVRC5477Regs->PCIW1, BSP_PCI_W1); // Setup control & arbiter registers OUTREG32(&pVRC5477Regs->PCICTL0L, BSP_PCI_CTL0L); OUTREG32(&pVRC5477Regs->PCICTL0H, BSP_PCI_CTL0H); OUTREG32(&pVRC5477Regs->PCIARB0L, BSP_PCI_ARB0L); OUTREG32(&pVRC5477Regs->PCIARB0H, BSP_PCI_ARB0H); // Setup configuration space OUTREG16(&pVRC5477Regs->PCICMD0, BSP_PCI_CMD0); OUTREG8(&pVRC5477Regs->MLTIM0, BSP_PCI_MLTIM0); OUTREG32(&pVRC5477Regs->BARC0, BSP_PCI_BARC0); OUTREG32(&pVRC5477Regs->BARM010, BSP_PCI_BARM010); OUTREG32(&pVRC5477Regs->BARM230, BSP_PCI_BARM230); OUTREG32(&pVRC5477Regs->BAR00, BSP_PCI_BAR00); OUTREG32(&pVRC5477Regs->BAR10, BSP_PCI_BAR10); OUTREG32(&pVRC5477Regs->BAR20, BSP_PCI_BAR20); OUTREG32(&pVRC5477Regs->BARB0, BSP_PCI_BARB0); OUTREG32(&pVRC5477Regs->BARP00, BSP_PCI_BARP00); OUTREG32(&pVRC5477Regs->BARP10, BSP_PCI_BARP10); //---------------------------------------------------------------------- // Internal PCI //---------------------------------------------------------------------- OUTREG32(&pVRC5477Regs->PCICTL1H, PCI_CTRL_CRST); OALStall(100000); OUTREG32(&pVRC5477Regs->PCICTL1H, 0); OALStall(100000); // Setup internal PCI windows OUTREG32(&pVRC5477Regs->PCIINIT01, BSP_PCI_INIT01); OUTREG32(&pVRC5477Regs->IOPCIW0, BSP_IOPCI_W0); OUTREG32(&pVRC5477Regs->PCIINIT11, BSP_PCI_INIT11); OUTREG32(&pVRC5477Regs->IOPCIW1, BSP_IOPCI_W1); // Setup control & arbiter registers OUTREG32(&pVRC5477Regs->PCICTL1L, BSP_PCI_CTL1L); OUTREG32(&pVRC5477Regs->PCICTL1H, BSP_PCI_CTL1H); OUTREG32(&pVRC5477Regs->PCIARB1L, BSP_PCI_ARB1L); OUTREG32(&pVRC5477Regs->PCIARB1H, BSP_PCI_ARB1H); // Setup configuration space OUTREG16(&pVRC5477Regs->PCICMD1, BSP_PCI_CMD1); OUTREG8(&pVRC5477Regs->MLTIM1, BSP_PCI_MLTIM1); OUTREG32(&pVRC5477Regs->BARC1, BSP_PCI_BARC1); OUTREG32(&pVRC5477Regs->BARM011, BSP_PCI_BARM011); OUTREG32(&pVRC5477Regs->BARM231, BSP_PCI_BARM231); OUTREG32(&pVRC5477Regs->BAR01, BSP_PCI_BAR01); OUTREG32(&pVRC5477Regs->BAR11, BSP_PCI_BAR11); OUTREG32(&pVRC5477Regs->BAR21, BSP_PCI_BAR21); OUTREG32(&pVRC5477Regs->BARB1, BSP_PCI_BARB1); OUTREG32(&pVRC5477Regs->BARP01, BSP_PCI_BARP01); OUTREG32(&pVRC5477Regs->BARP11, BSP_PCI_BARP11); OALStall(10000); //---------------------------------------------------------------------- // ALI M1535+ South Bridge //---------------------------------------------------------------------- // Is there ALI M1535+ bridge = CPU board is inserted to SG2 mother board, // in such case we must do some initialization --- default config address // lines for some ALI M1535+ internal devices colide with PCI slot config // address lines. pciLoc.bus = 0; pciLoc.dev = 8; pciLoc.fnc = 0; OALPCICfgRead(0, pciLoc, 0, sizeof(u32), &u32); if (u32 != 0x153310B9) goto cleanUp; //---------------------------------------------------------------------- // PCI-ISA bridge initialize //---------------------------------------------------------------------- OALLog(L"INFO: OALPCIInit: ALI M1535+ Bridge detected\r\n"); u32 = 0x0000C119; // I/O control, select PS2 keyboad/mouse OALPCICfgWrite(0, pciLoc, 0x40, sizeof(u32), &u32); u32 = 0x0000025D; // Primary IDE IRQ14 OALPCICfgWrite(0, pciLoc, 0x44, sizeof(u32), &u32); u32 = 0x70000009; // Audio->IRQ6, PCI INTC->IRQ11 OALPCICfgWrite(0, pciLoc, 0x48, sizeof(u32), &u32); u32 = 0x00000000; // USB1 enable OALPCICfgWrite(0, pciLoc, 0x50, sizeof(u32), &u32); u32 = 0x00000000; // PCSJ OALPCICfgWrite(0, pciLoc, 0x54, sizeof(u32), &u32); u32 = 0x0000007C; // IDE IDSEL(AD15), INTR OALPCICfgWrite(0, pciLoc, 0x58, sizeof(u32), &u32); u32 = 0x00004000; // Document recommend??? OALPCICfgWrite(0, pciLoc, 0x6C, sizeof(u32), &u32); u32 = 0x002600D2; // PMU IDSEL(AD14), USB IDSEL(AD13) OALPCICfgWrite(0, pciLoc, 0x70, sizeof(u32), &u32); u32 = 0x40801F01; // No modem, USB INTR(IRQ09), 2nd IDE IRQ15, AC97 IDSEL(AD17) OALPCICfgWrite(0, pciLoc, 0x74, sizeof(u32), &u32); u32 = 0x00000000; // USB2 disable OALPCICfgWrite(0, pciLoc, 0x7C, sizeof(u32), &u32); //--------------------------- // Configure super I/O chip //--------------------------- OUTPORT8(&pM1535Regs->config, 0x51); // Enter config mode OUTPORT8(&pM1535Regs->config, 0x23); // Enable parallel port OUTPORT8(&pM1535Regs->index, 0x07); OUTPORT8(&pM1535Regs->data, 0x03); // Select logical device 3 OUTPORT8(&pM1535Regs->index, 0x30); OUTPORT8(&pM1535Regs->data, 0x01); // Enable device OUTPORT8(&pM1535Regs->index, 0x60); OUTPORT8(&pM1535Regs->data, 0x03); // I/O address: 378h OUTPORT8(&pM1535Regs->index, 0x61); OUTPORT8(&pM1535Regs->data, 0x78); // I/O address: 378h OUTPORT8(&pM1535Regs->index, 0x70); OUTPORT8(&pM1535Regs->data, 0x07); // Irq: 7 // Enable UART1 OUTPORT8(&pM1535Regs->index, 0x07); OUTPORT8(&pM1535Regs->data, 0x04); // Select logical device 4 OUTPORT8(&pM1535Regs->index, 0x30); OUTPORT8(&pM1535Regs->data, 0x01); // Enable device OUTPORT8(&pM1535Regs->index, 0x60); OUTPORT8(&pM1535Regs->data, 0x03); // I/O address: 3F8h OUTPORT8(&pM1535Regs->index, 0x61); OUTPORT8(&pM1535Regs->data, 0xF8); // I/O address: 3F8h OUTPORT8(&pM1535Regs->index, 0x70); OUTPORT8(&pM1535Regs->data, 0x04); // Irq: 4 // Enable UART2/INFRA OUTPORT8(&pM1535Regs->index, 0x07); OUTPORT8(&pM1535Regs->data, 0x05); // Select logical device 5 OUTPORT8(&pM1535Regs->index, 0x30); OUTPORT8(&pM1535Regs->data, 0x01); // Enable device OUTPORT8(&pM1535Regs->index, 0x60); OUTPORT8(&pM1535Regs->data, 0x03); // I/O address: 3E8h OUTPORT8(&pM1535Regs->index, 0x61); OUTPORT8(&pM1535Regs->data, 0xE8); // I/O address: 3E8h OUTPORT8(&pM1535Regs->index, 0x70); OUTPORT8(&pM1535Regs->data, 0x05); // Irq: 5 // Enable PS/2 controller OUTPORT8(&pM1535Regs->index, 0x07); OUTPORT8(&pM1535Regs->data, 0x07); // Select logical device 7. OUTPORT8(&pM1535Regs->index, 0x30); OUTPORT8(&pM1535Regs->data, 0x01); // Enable device OUTPORT8(&pM1535Regs->index, 0x70); OUTPORT8(&pM1535Regs->data, 0x01); // Irq: 1 - keyboard OUTPORT8(&pM1535Regs->index, 0x72); OUTPORT8(&pM1535Regs->data, 0x0C); // Irq: 12 - mouse // Enable UART3 OUTPORT8(&pM1535Regs->index, 0x07); OUTPORT8(&pM1535Regs->data, 0x0B); // Select logical device 11 OUTPORT8(&pM1535Regs->index, 0x30); OUTPORT8(&pM1535Regs->data, 0x01); // Enable device OUTPORT8(&pM1535Regs->index, 0x60); OUTPORT8(&pM1535Regs->data, 0x02); // I/O address: 2F8h OUTPORT8(&pM1535Regs->index, 0x61); OUTPORT8(&pM1535Regs->data, 0xF8); // I/O address: 2F8h OUTPORT8(&pM1535Regs->index, 0x70); OUTPORT8(&pM1535Regs->data, 0x03); // Irq: 3 // Exit config mode OUTPORT8(&pM1535Regs->config, 0xBB); cleanUp: return TRUE; }
//------------------------------------------------------------------------------ // // Function: BSPIntrInit // // This function is called from OALIntrInit to initialize secondary interrupt // controller. // BOOL BSPIntrInit() { UINT8 *pPIC1Edge, *pPIC2Edge; UINT32 irq; OALMSG(OAL_INTR&&OAL_FUNC, (L"+BSPIntrInit\r\n")); // Add static mapping for on chip devices... OALIntrStaticTranslate(SYSINTR_FIRMWARE + 0, IRQ_UART1); // UART1 // Add GPIO static mapping for RTC alarm OALIntrStaticTranslate(SYSINTR_RTC_ALARM, IRQ_GPIO); // And enable it (it will not occur until it is set in OEMSetAlarmTime) irq = IRQ_GPIO; OALIntrEnableIrqs(1, &irq); // Get and save uncached virtual addresses for VRC5477 and PIC1/PIC2 g_pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); g_pPIC1Regs = OALPAtoUA(BSP_REG_PA_M1535_PIC1); g_pPIC2Regs = OALPAtoUA(BSP_REG_PA_M1535_PIC2); // M1535+ INTR uses positive logic (active on high), set VRC5477 CLRPORT32(&g_pVRC5477Regs->INTPPES0, 1 << 4); // We have to enable PCI interrupts irq = IRQ_INTA; OALIntrEnableIrqs(1, &irq); irq = IRQ_INTB; OALIntrEnableIrqs(1, &irq); irq = IRQ_INTC; OALIntrEnableIrqs(1, &irq); irq = IRQ_INTD; OALIntrEnableIrqs(1, &irq); // PIC1/PIC2 edge registers are needed only for initialization pPIC1Edge = OALPAtoUA(BSP_REG_PA_M1535_EDGE1); pPIC2Edge = OALPAtoUA(BSP_REG_PA_M1535_EDGE2); // Initialize the 8259 PIC1 OUTREG8(&g_pPIC1Regs->ctrl, 0x11); // ICW1, cascade & ICW4 OUTREG8(&g_pPIC1Regs->mask, IRQ_PIC_0); // ICW2, vector to 32 OUTREG8(&g_pPIC1Regs->mask, 0x04); // ICW3, slave on IRQ 2 OUTREG8(&g_pPIC1Regs->mask, 0x01); // ICW4, normal EOI OUTREG8(&g_pPIC1Regs->ctrl, 0x0B); // OCW2, read IS register OUTREG8(&g_pPIC1Regs->mask, 0xFF); // OCW1, all disabled // Now initialize the 8259 PIC2 OUTREG8(&g_pPIC2Regs->ctrl, 0x11); // ICW1, cascade & ICW4 OUTREG8(&g_pPIC2Regs->mask, IRQ_PIC_8); // ICW2, vector to 40 OUTREG8(&g_pPIC2Regs->mask, 0x02); // ICW3, we are IRQ 2 OUTREG8(&g_pPIC2Regs->mask, 0x01); // ICW4, normal EOI OUTREG8(&g_pPIC2Regs->ctrl, 0x0B); // OCW2, read IS register OUTREG8(&g_pPIC2Regs->mask, 0xFF); // OCW1, all disabled // IRQ0-IRQ7 Edge sensitive(IRQ2 cannot be set to level sensitive) OUTREG8(pPIC1Edge, 0x00); // IRQ9&IRQ11 level (USB host, PCI INTC), other edge sensitive OUTREG8(pPIC2Edge, 0x0A); // Enable interrupt from PIC2 on PIC1 CLRREG8(&g_pPIC1Regs->mask, 1 << 2); // Set static interrupt mappings for legacy devices OALIntrStaticTranslate(SYSINTR_FIRMWARE + 8, IRQ_PIC_1); // keyboard OALIntrStaticTranslate(SYSINTR_FIRMWARE + 9, IRQ_PIC_12); // mouse // We are done OALMSG(OAL_INTR&&OAL_FUNC, (L"-BSPIntrInit(rc = 1)\r\n")); return TRUE; }