.. _vga-stack: ========= VGA stack ========= .. contents:: Introduction ============ A dedicated RAM made of 0x200 8-bit cells arranged into a hw stack. NFI what it is for, apparently related to VGA. Present on NV41+ cards. .. _pbus-mmio-vga-stack: .. _pdisplay-mmio-vga-stack: .. _nv3-cr-vga-stack: .. _g80-cr-vga-stack: MMIO registers ============== On NV41:G80, the registers are located in PBUS area: - 001380 VAL - 001384 CTRL - 001388 CONFIG - 00138c SP They are also aliased in the VGA CRTC register space: - CR90 VAL - CR91 CTRL On G80+, the registers are located in PDISPLAY.VGA area: - 619e40 VAL - 619e44 CTRL - 619e48 CONFIG - 619e4c SP And aliased in VGA CRTC register space, but in a different place: - CRA2 VAL - CRA3 CTRL Description =========== The stack is made of the following data: - an array of 0x200 bytes [the actual stack] - a write shadow byte, WVAL [G80+ only] - a read shadow byte, RVAL [G80+ only] - a 10-bit stack pointer [SP] - 3 config bits: - push mode: auto or manual - pop mode: auto or manual - manual pop mode: read before pop or read after pop - 2 sticky error bits: - stack underflow - stack overflow The stack grows upwards. The stack pointer points to the cell that would be written by a push. The valid values for stack pointer are thus 0-0x200, with 0 corresponding to an empty stack and 0x200 to a full stack. If stack is ever accessed at position >= 0x200 [which is usually an error], the address wraps modulo 0x200. There are two major modes the stack can be operated in: auto mode and manual mode. The mode settings are independent for push and pop accesses - one can use automatic pushes and manual pops, for example. In automatic mode, the read/write access to the VAL register automatically performs the push/pop operation. In manual mode, the push/pop needs to be manually triggered in addition to accessing the VAL reg. For manual pushes, the push should be triggered after writing the value. For pops, the pop should be triggered before or after reading the value, depending on selected manual pop mode. The stack also keeps track of overflow and underflow errors. On NV41:G80, while these error conditions are detected, the offending access is still executed [and the stack pointer wraps]. On G80+, the offending access is discarded. The error status is sticky. On NV41:G80, it can only be cleared by poking the CONFIG register clear bits. On G80+, the overflow status is cleared by executing a pop, and the underflow status is cleared by executing a push. Stack access registers ====================== The stack data is read or written through the VAL register: MMIO 0x001380 / CR 0x90: VAL [NV41:G80] MMIO 0x619e40 / CR 0xa2: VAL [G80-] Accesses a stack entry. A write to this register stored the low 8 bits of written data as a byte to be pushed. If automatic push mode is set, the value is pushed immediately. Otherwise, it is pushed after PUSH_TRIGGER is set. A read from this register returns popped data [causing a pop in the process if automatic pop mode is set]. If manual read-before-pop mode is in use, the returned byte is the byte that the next POP_TRIGGER would pop. In manual pop-before-read, it is the byte that the last POP_TRIGGER popped. The CTRL register is used to manually push/pop the stack and check its status: MMIO 0x001384 / CR 0x91: CTRL [NV41:G80] MMIO 0x619e44 / CR 0xa3: CTRL [G80-] - bit 0: PUSH_TRIGGER - when written as 1, executes a push. Always reads as 0. - bit 1: POP_TRIGGER - like above, for pop. - bit 4: EMPTY - read-only, reads as 1 when SP == 0. - bit 5: FULL - read-only, reads as 1 when SP >= 0x200. - bit 6: OVERFLOW - read-only, the sticky overflow error bit - bit 7: UNDERFLOW - read-only, the sticky underflow error bit = Stack configuration registers = To configure the stack, the CONFIG register is used: MMIO 0x001388: CONFIG [NV41:G80] MMIO 0x619e48: CONFIG [G80-] - bit 0: PUSH_MODE - selects push mode [see above] - 0: MANUAL - 1: AUTO - bit 1: POP_MODE - selects pop mode [see above] - 0: MANUAL - 1: AUTO - bit 2: MANUAL_POP_MODE - for manual pop mode, selects manual pop submode. Unused for auto pop mode. - 0: POP_READ - pop before read - 1: READ_POP - read before pop - bit 6: OVERFLOW_CLEAR [NV41:G80] - when written as 1, clears CTRL.OVERFLOW to 0. Always reads as 0. - bit 7: UNDERFLOW_CLEAR [NV41:G80] - like above, for CTRL.UNDERFLOW The stack pointer can be accessed directly by the SP register: MMIO 0x00138c: SP [NV41:G80] MMIO 0x619e4c: SP [G80-] The stack pointer. Only low 10 bits are valid. Internal operation ================== NV41:G80 VAL write:: if (SP >= 0x200) CTRL.OVERFLOW = 1; STACK[SP] = val; if (CONFIG.PUSH_MODE == AUTO) PUSH(); NV41:G80 PUSH:: SP++; NV41:G80 VAL read:: if (SP == 0) CTRL.UNDERFLOW = 1; if (CONFIG.POP_MODE == AUTO) { POP(); res = STACK[SP]; } else { if (CONFIG.MANUAL_POP_MODE == POP_READ) res = STACK[SP]; else res = STACK[SP-1]; } NV41:G80 POP:: SP--; G80+ VAL write:: WVAL = val; if (CONFIG.PUSH_MODE == AUTO) PUSH(); G80+ PUSH:: if (SP >= 0x200) CTRL.OVERFLOW = 1; else STACK[SP++] = WVAL; CTRL.UNDERFLOW = 0; G80+ VAL read:: if (CONFIG.POP_MODE == AUTO) { POP(); res = RVAL; } else { if (CONFIG.MANUAL_POP_MODE == POP_READ || SP == 0) res = RVAL; else res = STACK[SP-1]; } G80+ POP:: if (SP == 0) CTRL.UNDERFLOW = 1; else RVAL = STACK[--SP]; CTRL.OVERFLOW = 0;