rem: exec_cmd_39_type2(rom, offset32, tabs, &exec); LOG(8,("INFO: ---Doubling PLL frequency to be set for cmd $34.\n")); data2 <<= 1;
add: exec_cmd_39_type2(rom, offset32, tabs, &double_f); LOG(8,("INFO: (cont. cmd $34) Doubling PLL frequency to be set for cmd $34.\n")); if (double_f) data2 <<= 1; LOG(8,("INFO: Reverting to pre-subcmd ($39) 'execution' mode.\n"));
context: static status_t exec_type2_script(uint8* rom, uint16 adress, int16* size, PinsTables tabs, uint16 ram_tab){	status_t result = B_OK;	bool end = false;	bool exec = true;	uint8 index, byte, byte2, safe, shift;	uint32 reg, reg2, data, data2, and_out, and_out2, or_in, safe32, offset32, size32;	LOG(8,("\nINFO: executing type2 script at adress $%04x...\n", adress));	while (!end)	{		LOG(8,("INFO: $%04x ($%02x); ", adress, rom[adress]));		//fixme: complete (if possible) ...		switch (rom[adress])		{		case 0x32: /* new */			*size -= (11 + ((*((uint8*)(&(rom[(adress + 6)])))) << 2));			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			reg = *((uint16*)(&(rom[adress])));			adress += 2;			index = *((uint8*)(&(rom[adress])));			adress += 1;			and_out = *((uint8*)(&(rom[adress])));			adress += 1;			byte2 = *((uint8*)(&(rom[adress])));			adress += 1;			size32 = ((*((uint8*)(&(rom[adress])))) << 2);			adress += 1;			reg2 = *((uint32*)(&(rom[adress])));			adress += 4;			LOG(8,("cmd 'RD idx ISA reg $%02x via $%04x, AND-out = $%02x, shift-right = $%02x,\n",				index, reg, and_out, byte2));			LOG(8,("INFO: (cont.) RD 32bit data from subtable with size $%04x, at offset (result << 2),\n",				size32));			LOG(8,("INFO: (cont.) then WR result data to 32bit reg $%08x'\n", reg2));			if (exec && reg2)			{				safe = ISARB(reg);				ISAWB(reg, index);				byte = ISARB(reg + 1);				ISAWB(reg, safe);				byte &= (uint8)and_out;				byte >>= byte2;				offset32 = (byte << 2);				data = *((uint32*)(&(rom[(adress + offset32)])));				NV_REG32(reg2) = data;			}			adress += size32;			break;		case 0x34: /* new */			*size -= (12 + ((*((uint8*)(&(rom[(adress + 7)])))) << 1));			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			reg = *((uint16*)(&(rom[adress])));			adress += 2;			index = *((uint8*)(&(rom[adress])));			adress += 1;			and_out = *((uint8*)(&(rom[adress])));			adress += 1;			shift = *((uint8*)(&(rom[adress])));			adress += 1;			offset32 = *((uint8*)(&(rom[adress])));			adress += 1;			size32 = ((*((uint8*)(&(rom[adress])))) << 1);			adress += 1;			reg2 = *((uint32*)(&(rom[adress])));			adress += 4;			safe = ISARB(reg);			ISAWB(reg, index);			byte = ISARB(reg + 1);			ISAWB(reg, safe);			byte &= (uint8)and_out;			data = (byte >> shift);			data <<= 1;			data2 = *((uint16*)(&(rom[(adress + data)])));			LOG(8,("cmd 'RD idx ISA reg $%02x via $%04x, AND-out = $%02x, shift-right = $%02x,\n",				index, reg, and_out, shift));			LOG(8,("INFO: (cont.) RD 16bit PLL frequency to pgm from subtable with size $%04x, at offset (result << 1),\n",				size32));			LOG(8,("INFO: (cont.) RD table-index ($%02x) for cmd $39'\n",				offset32));			if (offset32 < 0x80)			{				LOG(8,("INFO: Do subcmd ($39); "));				exec_cmd_39_type2(rom, offset32, tabs, &exec);				LOG(8,("INFO: ---Doubling PLL frequency to be set for cmd $34.\n"));				data2 <<= 1;			}			else			{				LOG(8,("INFO: table index is negative, not executing subcmd ($39).\n"));			}			LOG(8,("INFO: (cont. cmd $34) 'calc and set PLL 32bit reg $%08x for %.3fMHz'\n",				reg2, (data2 / 100.0)));			if (exec && reg2)			{				//fixme: setup core and RAM PLL calc routine(s), now (mis)using DAC's...				display_mode target;				float calced_clk;				uint8 m, n, p;				target.space = B_CMAP8;				target.timing.pixel_clock = (data2 * 10);				nv_dac_pix_pll_find(target, &calced_clk, &m, &n, &p, 0);				NV_REG32(reg2) = ((p << 16) | (n << 8) | m);//fixme?				/* program 2nd set N and M scalers if they exist (b31=1 enables them) *///				if ((si->ps.card_type == NV31) || (si->ps.card_type == NV36))//					DACW(PIXPLLC2, 0x80000401);			}			log_pll(reg2);			adress += size32;			break;		case 0x37: /* new */			*size -= 11;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			reg = *((uint32*)(&(rom[adress])));			adress += 4;			byte2 = *((uint8*)(&(rom[adress])));			adress += 1;			and_out = *((uint8*)(&(rom[adress])));			adress += 1;			reg2 = *((uint16*)(&(rom[adress])));			adress += 2;			index = *((uint8*)(&(rom[adress])));			adress += 1;			and_out2 = *((uint8*)(&(rom[adress])));			adress += 1;			LOG(8,("cmd 'RD 32bit reg $%08x, shift-right = $%02x, AND-out lsb = $%02x,\n",				reg, byte2, and_out));			LOG(8,("INFO: (cont.) RD 8bit ISA reg $%02x via $%04x, AND-out = $%02x, OR-in lsb result 32bit, WR-bk'\n",				index, reg2, and_out2));			if (exec)			{				data = NV_REG32(reg);				if (byte2 < 0x80)				{					data >>= byte2;				}				else				{					data <<= (0x0100 - byte2);				}				data &= and_out;				safe = ISARB(reg2);				ISAWB(reg2, index);				byte = ISARB(reg2 + 1);				byte &= (uint8)and_out2;				byte |= (uint8)data;				ISAWB((reg2 + 1), byte);				ISAWB(reg2, safe);			}			break;		case 0x38: /* new */			*size -= 1;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			LOG(8,("cmd 'invert current mode'\n"));			exec = !exec;			if (exec)				LOG(8,("INFO: ---Executing following command(s):'\n"));			else				LOG(8,("INFO: ---Not executing following command(s):'\n"));			break;		case 0x39: /* new */			*size -= 2;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			data = *((uint8*)(&(rom[adress])));			adress += 1;			exec_cmd_39_type2(rom, data, tabs, &exec);			break;		case 0x62: /* new */			*size -= 5;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			reg = *((uint16*)(&(rom[adress])));			adress += 2;			index = *((uint8*)(&(rom[adress])));			adress += 1;			byte = *((uint8*)(&(rom[adress])));			adress += 1;			LOG(8,("cmd 'WR idx ISA reg $%02x via $%04x = $%02x'\n", index, reg, byte));			if (exec)			{				safe = ISARB(reg);				ISAWW(reg, ((((uint16)byte) << 8) | index));				ISAWB(reg, safe);			}			break;		case 0x63:			*size -= 1;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			LOG(8,("cmd 'setup RAM config' (always done)\n"));			//fixme: setup...			/* always done */			setup_ram_config_nv10_up(rom, ram_tab);			break;		case 0x65: /* identical to type1 */			*size -= 13;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			reg = *((uint32*)(&(rom[adress])));			adress += 4;			data = *((uint32*)(&(rom[adress])));			adress += 4;			data2 = *((uint32*)(&(rom[adress])));			adress += 4;			LOG(8,("cmd 'WR 32bit reg $%08x = $%08x, then = $%08x' (always done)\n",				reg, data, data2));			/* always done */			/* (alternate NV-specific access to PCI config space registers:) */			safe32 = NV_REG32(0x00001800 + NVCFG_AGPCMD);			NV_REG32(0x00001800 + NVCFG_AGPCMD) = 0x00000000;			NV_REG32(reg) = data;			NV_REG32(reg) = data2;			NV_REG32(0x00001800 + NVCFG_AGPCMD) = safe32;			NV_REG32(0x00001800 + NVCFG_ROMSHADOW) &= 0xfffffffe;			break;		case 0x69: /* identical to type1 */			*size -= 5;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			reg = *((uint16*)(&(rom[adress])));			adress += 2;			and_out = *((uint8*)(&(rom[adress])));			adress += 1;			or_in = *((uint8*)(&(rom[adress])));			adress += 1;			LOG(8,("cmd 'RD 8bit ISA reg $%04x, AND-out = $%02x, OR-in = $%02x, WR-bk'\n",				reg, and_out, or_in));			if (exec)			{				byte = ISARB(reg);				byte &= (uint8)and_out;				byte |= (uint8)or_in;				ISAWB(reg, byte);			}			break;		case 0x6e: /* identical to type1 */			*size -= 13;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			reg = *((uint32*)(&(rom[adress])));			adress += 4;			and_out = *((uint32*)(&(rom[adress])));			adress += 4;			or_in = *((uint32*)(&(rom[adress])));			adress += 4;			LOG(8,("cmd 'RD 32bit reg $%08x, AND-out = $%08x, OR-in = $%08x, WR-bk'\n",				reg, and_out, or_in));			if (exec)			{				data = NV_REG32(reg);				data &= and_out;				data |= or_in;				NV_REG32(reg) = data;			}			break;		case 0x6f: /* new */			*size -= 2;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			data = (*((uint8*)(&(rom[adress]))) << 1);			adress += 1;			data += tabs.MacroIndexTablePtr;			offset32 = (*((uint8*)(&(rom[data]))) << 3);			size32 = *((uint8*)(&(rom[(data + 1)])));			offset32 += tabs.MacroTablePtr;			/* note: min 1, max 255 commands can be requested */			LOG(8,("cmd 'do $%02x time(s) a 32bit reg WR with 32bit data':\n", size32));			safe32 = 0;			while (safe32 < size32)			{				reg2 = *((uint32*)(&(rom[(offset32 + (safe32 << 3))])));				data2 = *((uint32*)(&(rom[(offset32 + (safe32 << 3) + 4)])));				LOG(8,("INFO: (cont.) (#$%02x) cmd 'WR 32bit reg' $%08x = $%08x\n",					safe32, reg2, data2));				safe32++; 			}			if (exec)			{				safe32 = 0;				while (safe32 < size32)				{					reg2 = *((uint32*)(&(rom[(offset32 + (safe32 << 3))])));					data2 = *((uint32*)(&(rom[(offset32 + (safe32 << 3) + 4)])));					NV_REG32(reg2) = data2;					safe32++;				}			}			break;		//fixme? this is correct on NV11, but how about newer cards???		case 0x36: /* new */		case 0x66: /* new */		case 0x67: /* new */		case 0x68: /* new */		case 0x6c: /* new */		case 0x71: /* identical to type1 */			LOG(8,("cmd 'END', execution completed.\n\n"));			end = true;			*size -= 1;			if (*size < 0)			{				LOG(8,("script size error!\n\n"));				result = B_ERROR;			}			break;		case 0x72: /* identical to type1 */			*size -= 1;			if (*size < 0)			{				LOG(8,("script size error!\n\n"));				result = B_ERROR;			}			/* execute */			adress += 1;			LOG(8,("cmd 'PGM commands'\n"));			LOG(8,("INFO: ---Executing following command(s):'\n"));			exec = true;			break;		case 0x74: /* identical to type1 */			*size -= 3;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			data = *((uint16*)(&(rom[adress])));			adress += 2;			LOG(8,("cmd 'SNOOZE for %d ($%04x) microSeconds' (always done)\n", data, data));			/* always done */			snooze(data);			break;		case 0x75: /* new */			*size -= 2;			if (*size < 0)			{				LOG(8,("script size error!\n\n"));				result = B_ERROR;			}			/* execute */			adress += 1;			data = *((uint8*)(&(rom[adress])));			adress += 1;			data *= 12;			data += tabs.ConditionTablePtr;			reg = *((uint32*)(&(rom[data])));			and_out = *((uint32*)(&(rom[(data + 4)])));			data2 = *((uint32*)(&(rom[(data + 8)])));			data = NV_REG32(reg);			data &= and_out;			LOG(8,("cmd 'CHK bits AND-out $%08x reg $%08x for $%08x'\n",				and_out, reg, data2));			if (data != data2)			{				LOG(8,("INFO: ---No match: not executing following command(s):\n"));				exec = false;			}			else			{				LOG(8,("INFO: ---Match, so this cmd has no effect.\n"));			}			break;		case 0x76: /* new */			*size -= 2;			if (*size < 0)			{				LOG(8,("script size error!\n\n"));				result = B_ERROR;			}			/* execute */			adress += 1;			data = *((uint8*)(&(rom[adress])));			adress += 1;			data *= 5;			data += tabs.IOConditionTablePtr;			reg = *((uint16*)(&(rom[data])));			index = *((uint8*)(&(rom[(data + 2)])));			and_out = *((uint8*)(&(rom[(data + 3)])));			byte2 = *((uint8*)(&(rom[(data + 4)])));			safe = ISARB(reg);			ISAWB(reg, index);			byte = ISARB(reg + 1);			ISAWB(reg, safe);			byte &= (uint8)and_out;			LOG(8,("cmd 'CHK bits AND-out $%02x idx ISA reg $%02x via $%04x for $%02x'\n",				and_out, index, reg, byte2));			if (byte != byte2)			{				LOG(8,("INFO: ---No match: not executing following command(s):\n"));				exec = false;			}			else			{				LOG(8,("INFO: ---Match, so this cmd has no effect.\n"));			}			break;		case 0x78: /* identical to type1 */			*size -= 6;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			reg = *((uint16*)(&(rom[adress])));			adress += 2;			index = *((uint8*)(&(rom[adress])));			adress += 1;			and_out = *((uint8*)(&(rom[adress])));			adress += 1;			or_in = *((uint8*)(&(rom[adress])));			adress += 1;			LOG(8,("cmd 'RD idx ISA reg $%02x via $%04x, AND-out = $%02x, OR-in = $%02x, WR-bk'\n",				index, reg, and_out, or_in));			if (exec)			{				safe = ISARB(reg);				ISAWB(reg, index);				byte = ISARB(reg + 1);				byte &= (uint8)and_out;				byte |= (uint8)or_in;				ISAWB((reg + 1), byte);				ISAWB(reg, safe);			}			break;		case 0x79:			*size -= 7;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			//fixme: setup new PLL routines that adhere to pins speeds for VCO, etc...			adress += 1;			reg = *((uint32*)(&(rom[adress])));			adress += 4;			data = *((uint16*)(&(rom[adress])));			adress += 2;			LOG(8,("cmd 'calculate and set PLL 32bit reg $%08x for %.3fMHz'\n", reg, (data / 100.0)));			if (exec)			{				//fixme: setup core and RAM PLL calc routine(s), now (mis)using DAC's...				display_mode target;				float calced_clk;				uint8 m, n, p;				target.space = B_CMAP8;				target.timing.pixel_clock = (data * 10);				nv_dac_pix_pll_find(target, &calced_clk, &m, &n, &p, 0);				NV_REG32(reg) = ((p << 16) | (n << 8) | m);//fixme?				/* program 2nd set N and M scalers if they exist (b31=1 enables them) *///				if ((si->ps.card_type == NV31) || (si->ps.card_type == NV36))//					DACW(PIXPLLC2, 0x80000401);			}			log_pll(reg);			break;		case 0x7a: /* identical to type1 */			*size -= 9;			if (*size < 0)			{				LOG(8,("script size error, aborting!\n\n"));				end = true;				result = B_ERROR;				break;			}			/* execute */			adress += 1;			reg = *((uint32*)(&(rom[adress])));			adress += 4;			data = *((uint32*)(&(rom[adress])));			adress += 4;			LOG(8,("cmd 'WR 32bit reg' $%08x = $%08x\n", reg, data));			if (exec) NV_REG32(reg) = data;			break;		default:			LOG(8,("unknown cmd, aborting!\n\n"));			end = true;			result = B_ERROR;			break;		}	}	return result;}