コード例 #1
0
ファイル: debug.c プロジェクト: laoyouji/wince6.0-1b
//------------------------------------------------------------------------------
//
//  Function:  OEMReadDebugByte
//
//  Input character/byte from debug serial port
//
INT OEMReadDebugByte()
{
     VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA);
     UINT8 ch, status;
    
     status = INREG8(&pVRC5477Regs->UARTLSR0);
     if ((status & UART_LSR_DR) != 0) {
       ch = INREG8(&pVRC5477Regs->UARTRBR0);
       if ((status & UART_LSR_RFERR) != 0) ch = OEM_DEBUG_COM_ERROR;
    } else {
       ch = OEM_DEBUG_READ_NODATA;
    }
    return ch;
}
コード例 #2
0
//------------------------------------------------------------------------------
//
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);
}
コード例 #3
0
ファイル: intr.c プロジェクト: laoyouji/wince6.0-1b
//------------------------------------------------------------------------------
//
//  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;
}
コード例 #4
0
//------------------------------------------------------------------------------
//
//  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"));
}
コード例 #5
0
static uint8_t read_reg(uint32_t reg, bool use_mmio)
{
	if (use_mmio)
		return INREG8(reg);
	else
		return inb(reg);
}
コード例 #6
0
//------------------------------------------------------------------------------
//
//  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;
}
コード例 #7
0
ファイル: Device.c プロジェクト: DanielGit/Intrisit201202
////////////////////////////////////////////////////
// 功能: codec 寄存器读出
// 输入: 
// 输出:
// 返回: 
// 说明: 
////////////////////////////////////////////////////
static unsigned char codec_reg_read(unsigned char addr)
{
	AIC_RW_CODEC_START();
	OUTREG16(AIC_RGADW, (addr << RGADW_ADDR_BIT));

	return (INREG8(AIC_RGDAT));
}
コード例 #8
0
//------------------------------------------------------------------------------
//
//  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"));
}
コード例 #9
0
ファイル: register_io.cpp プロジェクト: mmanley/Antares
uint8 ReadReg8(uint32 addr)
{
    if (gInfo.sharedInfo->chipType == S3_TRIO64)
        return ReadPIO(addr, 1);

    return INREG8(addr);
}
コード例 #10
0
ファイル: register_io.cpp プロジェクト: mmanley/Antares
uint8 ReadMiscOutReg()
{
    if (gInfo.sharedInfo->chipType == S3_TRIO64)
        return ReadPIO_8(0x3cc);

    return INREG8(0x83cc);
}
コード例 #11
0
ファイル: uart.c プロジェクト: Stadtpirat/open-p3go
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
}
コード例 #12
0
ファイル: debug.c プロジェクト: laoyouji/wince6.0-1b
//------------------------------------------------------------------------------
//
//  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);
}
コード例 #13
0
ファイル: register_io.cpp プロジェクト: mmanley/Antares
uint8 ReadSeqReg(uint8 index)
{
    if (gInfo.sharedInfo->chipType == S3_TRIO64) {
        WritePIO_8(0x3c4, index);
        return ReadPIO_8(0x3c5);
    }

    OUTREG8(0x83c4, index);
    return INREG8(0x83c5);
}
コード例 #14
0
/*
 * 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();
}
コード例 #15
0
//------------------------------------------------------------------------------
// 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);

}
コード例 #16
0
ファイル: Device.c プロジェクト: DanielGit/Intrisit201202
////////////////////////////////////////////////////
// 功能: codec 寄存器清除
// 输入: 
// 输出:
// 返回: 
// 说明: 
////////////////////////////////////////////////////
static void codec_reg_clear(unsigned char addr, unsigned char data)
{
	unsigned int	temp = addr << RGADW_ADDR_BIT;

	AIC_RW_CODEC_START();
	OUTREG16(AIC_RGADW, temp);
	temp |= (INREG8(AIC_RGDAT) & (~data));
	OUTREG32(AIC_RGADW, temp);
	OUTREG32(AIC_RGADW, (temp | AIC_RGADW_RGWR));

	AIC_RW_CODEC_STOP();
}
コード例 #17
0
ファイル: uart.c プロジェクト: laoyouji/wince6.0-1b
//------------------------------------------------------------------------------
//
//  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;
}
コード例 #18
0
ファイル: register_io.cpp プロジェクト: mmanley/Antares
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));
    }
}
コード例 #19
0
ファイル: uart.c プロジェクト: laoyouji/wince6.0-1b
//------------------------------------------------------------------------------
//
//  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;
}
コード例 #20
0
ファイル: hp-agp.c プロジェクト: GodFox/magx_kernel_xpixl
static int
hp_zx1_lba_find_capability (volatile u8 __iomem *hpa, int cap)
{
	u16 status;
	u8 pos, id;
	int ttl = 48;

	status = INREG16(hpa, PCI_STATUS);
	if (!(status & PCI_STATUS_CAP_LIST))
		return 0;
	pos = INREG8(hpa, PCI_CAPABILITY_LIST);
	while (ttl-- && pos >= 0x40) {
		pos &= ~3;
		id = INREG8(hpa, pos + PCI_CAP_LIST_ID);
		if (id == 0xff)
			break;
		if (id == cap)
			return pos;
		pos = INREG8(hpa, pos + PCI_CAP_LIST_NEXT);
	}
	return 0;
}
コード例 #21
0
ファイル: uart.c プロジェクト: laoyouji/wince6.0-1b
//------------------------------------------------------------------------------
//
//  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;
}
コード例 #22
0
ファイル: sworks-agp.c プロジェクト: wxlong/Test
/*
 * 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");
		}
	}
}
コード例 #23
0
ファイル: uart.c プロジェクト: Stadtpirat/open-p3go
void serial_waitfinish()
{
	while(!(INREG8((DEBUG_UART_BASE + UART_ULSR_OFFSET)) & ULSR_TEMP ) );
}
コード例 #24
0
ファイル: uart.c プロジェクト: Stadtpirat/open-p3go
int serial_tstc (void)
{
	/* Data in rfifo */
	return  (INREG8((DEBUG_UART_BASE + UART_ULSR_OFFSET)) & ULSR_DRY );
}
コード例 #25
0
ファイル: uart.c プロジェクト: Stadtpirat/open-p3go
int serial_getc (void)
{
	while (!serial_tstc());
	return INREG8((DEBUG_UART_BASE + UART_URBR_OFFSET));
}
コード例 #26
0
ファイル: mach64_mode.cpp プロジェクト: mmanley/Antares
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;
}