122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie/*
222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * Copyright 2004 The Unichrome Project. All Rights Reserved.
322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie *
522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * Permission is hereby granted, free of charge, to any person obtaining a
622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * copy of this software and associated documentation files (the "Software"),
722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * to deal in the Software without restriction, including without limitation
822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * the rights to use, copy, modify, merge, publish, distribute, sub license,
922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * and/or sell copies of the Software, and to permit persons to whom the
1022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * Software is furnished to do so, subject to the following conditions:
1122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie *
1222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * The above copyright notice and this permission notice (including the
1322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * next paragraph) shall be included in all copies or substantial portions
1422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * of the Software.
1522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie *
1622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
1922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
2022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * DEALINGS IN THE SOFTWARE.
2322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie *
2422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * Author: Thomas Hellstrom 2004, 2005.
2522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * This code was written using docs obtained under NDA from VIA Inc.
2622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie *
2722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * Don't run this code directly on an AGP buffer. Due to cache problems it will
2822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * be very slow.
2922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie */
3022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
3122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie#include "via_3d_reg.h"
3222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie#include "drmP.h"
3322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie#include "drm.h"
3422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie#include "via_drm.h"
3522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie#include "via_verifier.h"
3622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie#include "via_drv.h"
3722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
38b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlietypedef enum {
3922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	state_command,
4022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	state_header2,
4122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	state_header1,
4222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	state_vheader5,
4322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	state_vheader6,
4422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	state_error
4522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie} verifier_state_t;
4622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
47b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlietypedef enum {
4822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	no_check = 0,
4922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_for_header2,
5022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_for_header1,
5122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_for_header2_err,
5222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_for_header1_err,
5322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_for_fire,
5422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_z_buffer_addr0,
5522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_z_buffer_addr1,
5622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_z_buffer_addr_mode,
5722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_destination_addr0,
5822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_destination_addr1,
5922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_destination_addr_mode,
6022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_for_dummy,
6122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_for_dd,
6222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_texture_addr0,
6322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_texture_addr1,
6422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_texture_addr2,
6522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_texture_addr3,
6622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_texture_addr4,
6722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_texture_addr5,
6822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_texture_addr6,
6922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_texture_addr7,
7022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_texture_addr8,
7122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_texture_addr_mode,
7222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_for_vertex_count,
7322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	check_number_texunits,
7422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	forbidden_command
75b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie} hazard_t;
7622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
7722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie/*
7822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * Associates each hazard above with a possible multi-command
7922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * sequence. For example an address that is split over multiple
80b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie * commands and that needs to be checked at the first command
8122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * that does not include any part of the address.
8222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie */
8322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
84b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airliestatic drm_via_sequence_t seqs[] = {
8522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	no_sequence,
8622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	no_sequence,
8722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	no_sequence,
8822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	no_sequence,
8922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	no_sequence,
9022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	no_sequence,
9122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	z_address,
9222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	z_address,
9322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	z_address,
9422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	dest_address,
9522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	dest_address,
9622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	dest_address,
9722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	no_sequence,
9822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	no_sequence,
9922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	tex_address,
10022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	tex_address,
10122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	tex_address,
10222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	tex_address,
10322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	tex_address,
10422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	tex_address,
10522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	tex_address,
10622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	tex_address,
10722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	tex_address,
10822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	tex_address,
10922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	no_sequence
11022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie};
111b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
112b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlietypedef struct {
11322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	unsigned int code;
11422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	hazard_t hz;
11522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie} hz_init_t;
11622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
11722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic hz_init_t init_table1[] = {
11822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xf2, check_for_header2_err},
11922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xf0, check_for_header1_err},
12022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xee, check_for_fire},
12122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xcc, check_for_dummy},
12222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xdd, check_for_dd},
12322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x00, no_check},
12422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x10, check_z_buffer_addr0},
12522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x11, check_z_buffer_addr1},
12622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x12, check_z_buffer_addr_mode},
12722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x13, no_check},
12822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x14, no_check},
12922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x15, no_check},
13022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x23, no_check},
13122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x24, no_check},
13222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x33, no_check},
13322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x34, no_check},
13422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x35, no_check},
13522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x36, no_check},
13622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x37, no_check},
13722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x38, no_check},
13822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x39, no_check},
13922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x3A, no_check},
14022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x3B, no_check},
14122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x3C, no_check},
14222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x3D, no_check},
14322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x3E, no_check},
14422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x40, check_destination_addr0},
14522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x41, check_destination_addr1},
14622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x42, check_destination_addr_mode},
14722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x43, no_check},
14822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x44, no_check},
14922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x50, no_check},
15022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x51, no_check},
15122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x52, no_check},
15222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x53, no_check},
15322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x54, no_check},
15422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x55, no_check},
15522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x56, no_check},
15622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x57, no_check},
15722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x58, no_check},
15822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x70, no_check},
15922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x71, no_check},
16022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x78, no_check},
16122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x79, no_check},
16222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x7A, no_check},
16322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x7B, no_check},
16422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x7C, no_check},
16522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x7D, check_for_vertex_count}
16622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie};
16722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
16822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic hz_init_t init_table2[] = {
16922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xf2, check_for_header2_err},
17022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xf0, check_for_header1_err},
17122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xee, check_for_fire},
17222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xcc, check_for_dummy},
17322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x00, check_texture_addr0},
17422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x01, check_texture_addr0},
17522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x02, check_texture_addr0},
17622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x03, check_texture_addr0},
17722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x04, check_texture_addr0},
17822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x05, check_texture_addr0},
17922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x06, check_texture_addr0},
18022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x07, check_texture_addr0},
18122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x08, check_texture_addr0},
18222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x09, check_texture_addr0},
18322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x20, check_texture_addr1},
18422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x21, check_texture_addr1},
18522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x22, check_texture_addr1},
18622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x23, check_texture_addr4},
18722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x2B, check_texture_addr3},
18822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x2C, check_texture_addr3},
18922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x2D, check_texture_addr3},
19022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x2E, check_texture_addr3},
19122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x2F, check_texture_addr3},
19222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x30, check_texture_addr3},
19322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x31, check_texture_addr3},
19422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x32, check_texture_addr3},
19522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x33, check_texture_addr3},
19622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x34, check_texture_addr3},
19722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x4B, check_texture_addr5},
19822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x4C, check_texture_addr6},
19922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x51, check_texture_addr7},
20022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x52, check_texture_addr8},
20122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x77, check_texture_addr2},
20222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x78, no_check},
20322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x79, no_check},
20422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x7A, no_check},
20522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x7B, check_texture_addr_mode},
20622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x7C, no_check},
20722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x7D, no_check},
20822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x7E, no_check},
20922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x7F, no_check},
21022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x80, no_check},
21122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x81, no_check},
21222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x82, no_check},
21322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x83, no_check},
21422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x85, no_check},
21522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x86, no_check},
21622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x87, no_check},
21722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x88, no_check},
21822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x89, no_check},
21922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x8A, no_check},
22022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x90, no_check},
22122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x91, no_check},
22222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x92, no_check},
22322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x93, no_check}
22422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie};
22522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
22622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic hz_init_t init_table3[] = {
22722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xf2, check_for_header2_err},
22822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xf0, check_for_header1_err},
22922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0xcc, check_for_dummy},
23022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	{0x00, check_number_texunits}
23122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie};
23222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
233b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airliestatic hazard_t table1[256];
234b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airliestatic hazard_t table2[256];
235b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airliestatic hazard_t table3[256];
23622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
23722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic __inline__ int
23858c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaisereat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words)
23922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
240925142431bd653175b80ae153bd7a8bc13628bdeDave Airlie	if ((buf_end - *buf) >= num_words) {
24122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		*buf += num_words;
24222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
243b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	}
24422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	DRM_ERROR("Illegal termination of DMA command buffer\n");
24522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return 1;
24622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
24722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
24822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie/*
24922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * Partially stolen from drm_memory.h
25022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie */
25122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
252925142431bd653175b80ae153bd7a8bc13628bdeDave Airliestatic __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
253b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie						    unsigned long offset,
254b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie						    unsigned long size,
25558c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser						    struct drm_device *dev)
25622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
25755910517af381eba4f978740e5e46e23eb269326Dave Airlie	struct drm_map_list *r_list;
258925142431bd653175b80ae153bd7a8bc13628bdeDave Airlie	drm_local_map_t *map = seq->map_cache;
25922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
260b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	if (map && map->offset <= offset
261b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	    && (offset + size) <= (map->offset + map->size)) {
26222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return map;
26322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
264b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
265bd1b331fae2813d9f03ceee649296f02edc0b893Dave Airlie	list_for_each_entry(r_list, &dev->maplist, head) {
26622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		map = r_list->map;
26722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if (!map)
26822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			continue;
269b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (map->offset <= offset
270b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    && (offset + size) <= (map->offset + map->size)
271b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    && !(map->flags & _DRM_RESTRICTED)
272b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    && (map->type == _DRM_AGP)) {
27322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			seq->map_cache = map;
27422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			return map;
27522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
27622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
27722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return NULL;
27822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
27922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
28022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie/*
281b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie * Require that all AGP texture levels reside in the same AGP map which should
28222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * be mappable by the client. This is not a big restriction.
283b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie * FIXME: To actually enforce this security policy strictly, drm_rmmap
284b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie * would have to wait for dma quiescent before removing an AGP map.
28522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * The via_drm_lookup_agp_map call in reality seems to take
28622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie * very little CPU time.
28722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie */
28822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
289b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airliestatic __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
29022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
291b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	switch (cur_seq->unfinished) {
29222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case z_address:
29322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
29422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
29522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case dest_address:
296b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		DRM_DEBUG("Destination start address is 0x%x\n",
297b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			  cur_seq->d_addr);
29822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
29922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case tex_address:
300b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (cur_seq->agp_texture) {
301b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			unsigned start =
302b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			    cur_seq->tex_level_lo[cur_seq->texture];
30322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
304b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			unsigned long lo = ~0, hi = 0, tmp;
30522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			uint32_t *addr, *pitch, *height, tex;
30622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			unsigned i;
3079b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom			int npot;
30822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
309b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			if (end > 9)
310b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				end = 9;
311b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			if (start > 9)
312b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				start = 9;
31322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
314b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			addr =
315b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			    &(cur_seq->t_addr[tex = cur_seq->texture][start]);
31622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			pitch = &(cur_seq->pitch[tex][start]);
31722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			height = &(cur_seq->height[tex][start]);
3189b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom			npot = cur_seq->tex_npot[tex];
319b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			for (i = start; i <= end; ++i) {
32022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				tmp = *addr++;
321b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				if (tmp < lo)
322b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie					lo = tmp;
3239b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom				if (i == 0 && npot)
3249b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom					tmp += (*height++ * *pitch++);
3259b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom				else
3269b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom					tmp += (*height++ << *pitch++);
327b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				if (tmp > hi)
328b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie					hi = tmp;
32922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			}
33022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
331b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			if (!via_drm_lookup_agp_map
332b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			    (cur_seq, lo, hi - lo, cur_seq->dev)) {
333b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				DRM_ERROR
334b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				    ("AGP texture is not in allowed map\n");
33522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				return 2;
33622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			}
337b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		}
33822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
33922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	default:
34022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
34122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
34222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	cur_seq->unfinished = no_sequence;
34322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return 0;
34422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
34522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
346b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airliestatic __inline__ int
34758c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiserinvestigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
34822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
34922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	register uint32_t tmp, *tmp_addr;
35022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
35122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
35222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		int ret;
353b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if ((ret = finish_current_sequence(cur_seq)))
354b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			return ret;
35522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
35622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
357b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	switch (hz) {
35822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_for_header2:
359b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (cmd == HALCYON_HEADER2)
360b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			return 1;
36122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
36222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_for_header1:
363b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
364b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			return 1;
36522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
36622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_for_header2_err:
367b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (cmd == HALCYON_HEADER2)
368b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			return 1;
36922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
37022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
37122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_for_header1_err:
372b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
373b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			return 1;
37422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
37522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
37622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_for_fire:
377b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
378b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			return 1;
37922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
38022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
38122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_for_dummy:
382b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (HC_DUMMY == cmd)
383b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			return 0;
38422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal DMA HC_DUMMY command\n");
38522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
38622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_for_dd:
387b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (0xdddddddd == cmd)
388b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			return 0;
38922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal DMA 0xdddddddd command\n");
39022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
39122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_z_buffer_addr0:
39222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = z_address;
39322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
394b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    (cmd & 0x00FFFFFF);
39522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
39622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_z_buffer_addr1:
39722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = z_address;
39822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
399b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    ((cmd & 0xFF) << 24);
40022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
40122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_z_buffer_addr_mode:
40222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = z_address;
403b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if ((cmd & 0x0000C000) == 0)
404b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			return 0;
40522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Attempt to place Z buffer in system memory\n");
40622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 2;
40722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_destination_addr0:
40822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = dest_address;
40922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
410b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    (cmd & 0x00FFFFFF);
41122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
41222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_destination_addr1:
41322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = dest_address;
41422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
415b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    ((cmd & 0xFF) << 24);
41622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
41722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_destination_addr_mode:
41822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = dest_address;
419b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if ((cmd & 0x0000C000) == 0)
420b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			return 0;
421b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		DRM_ERROR
422b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    ("Attempt to place 3D drawing buffer in system memory\n");
423b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		return 2;
42422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_texture_addr0:
42522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = tex_address;
42622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp = (cmd >> 24);
42722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
42822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		*tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF);
42922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
43022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_texture_addr1:
43122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = tex_address;
43222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp = ((cmd >> 24) - 0x20);
43322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp += tmp << 1;
43422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
43522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		*tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
43622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr++;
43722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		*tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16);
43822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr++;
43922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		*tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8);
44022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
44122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_texture_addr2:
44222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = tex_address;
44322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F;
44422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6;
44522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
44622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_texture_addr3:
44722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = tex_address;
4489b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom		tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit);
4499b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom		if (tmp == 0 &&
4509b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom		    (cmd & HC_HTXnEnPit_MASK)) {
4519b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom			cur_seq->pitch[cur_seq->texture][tmp] =
4529b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom				(cmd & HC_HTXnLnPit_MASK);
4539b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom			cur_seq->tex_npot[cur_seq->texture] = 1;
4549b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom		} else {
4559b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom			cur_seq->pitch[cur_seq->texture][tmp] =
4569b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom				(cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT;
4579b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom			cur_seq->tex_npot[cur_seq->texture] = 0;
4589b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom			if (cmd & 0x000FFFFF) {
4599b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom				DRM_ERROR
4609b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom					("Unimplemented texture level 0 pitch mode.\n");
4619b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom				return 2;
4629b8d9d0e0181286c0608e6426da1eac45463ecd2Thomas Hellstrom			}
46322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
46422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
46522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_texture_addr4:
46622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = tex_address;
46722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr = &cur_seq->t_addr[cur_seq->texture][9];
46822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		*tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
46922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
47022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_texture_addr5:
47122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_texture_addr6:
47222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = tex_address;
47322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		/*
47422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		 * Texture width. We don't care since we have the pitch.
475b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		 */
47622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
47722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_texture_addr7:
47822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = tex_address;
47922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
48022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20);
48122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16);
48222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12);
48322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8);
48422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4);
48522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr[0] = 1 << (cmd & 0x0000000F);
48622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
48722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_texture_addr8:
48822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = tex_address;
48922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
49022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
491b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
49222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
49322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		tmp_addr[6] = 1 << (cmd & 0x0000000F);
49422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
49522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_texture_addr_mode:
49622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->unfinished = tex_address;
497b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (2 == (tmp = cmd & 0x00000003)) {
498b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			DRM_ERROR
499b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			    ("Attempt to fetch texture from system memory.\n");
50022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			return 2;
50122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
50222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->agp_texture = (tmp == 3);
503b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		cur_seq->tex_palette_size[cur_seq->texture] =
504b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    (cmd >> 16) & 0x000000007;
50522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
50622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_for_vertex_count:
50722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cur_seq->vertex_count = cmd & 0x0000FFFF;
50822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
50922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case check_number_texunits:
510b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		cur_seq->multitex = (cmd >> 3) & 1;
51122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 0;
51222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	default:
51322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
51422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 2;
51522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
51622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return 2;
51722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
51822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
51922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic __inline__ int
520b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlievia_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
52158c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser		    drm_via_state_t *cur_seq)
52222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
523b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	drm_via_private_t *dev_priv =
524b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	    (drm_via_private_t *) cur_seq->dev->dev_private;
525b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	uint32_t a_fire, bcmd, dw_count;
52622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	int ret = 0;
52722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	int have_fire;
52822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	const uint32_t *buf = *buffer;
52922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
530b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	while (buf < buf_end) {
531b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		have_fire = 0;
53222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if ((buf_end - buf) < 2) {
533b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			DRM_ERROR
534b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			    ("Unexpected termination of primitive list.\n");
53522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			ret = 1;
53622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
53722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
538b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
539b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			break;
54022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		bcmd = *buf++;
54122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
54222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
54322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				  *buf);
54422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			ret = 1;
54522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
54622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
547b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		a_fire =
548b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
549b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    HC_HE3Fire_MASK;
550b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
55122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		/*
55222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		 * How many dwords per vertex ?
553b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		 */
554b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
55522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
55622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			DRM_ERROR("Illegal B command vertex data for AGP.\n");
55722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			ret = 1;
55822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
559b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		}
56022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
56122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		dw_count = 0;
562b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (bcmd & (1 << 7))
563b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			dw_count += (cur_seq->multitex) ? 2 : 1;
564b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (bcmd & (1 << 8))
565b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			dw_count += (cur_seq->multitex) ? 2 : 1;
566b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (bcmd & (1 << 9))
567b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			dw_count++;
568b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (bcmd & (1 << 10))
569b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			dw_count++;
570b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (bcmd & (1 << 11))
571b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			dw_count++;
572b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (bcmd & (1 << 12))
573b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			dw_count++;
574b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (bcmd & (1 << 13))
575b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			dw_count++;
576b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (bcmd & (1 << 14))
577b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			dw_count++;
578b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
579b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		while (buf < buf_end) {
58022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			if (*buf == a_fire) {
581b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				if (dev_priv->num_fire_offsets >=
582b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				    VIA_FIRE_BUF_SIZE) {
58322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie					DRM_ERROR("Fire offset buffer full.\n");
58422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie					ret = 1;
58522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie					break;
58622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				}
587b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				dev_priv->fire_offsets[dev_priv->
588b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie						       num_fire_offsets++] =
589b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				    buf;
590b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				have_fire = 1;
59122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				buf++;
592b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				if (buf < buf_end && *buf == a_fire)
59322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie					buf++;
59422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				break;
59522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			}
596b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			if ((*buf == HALCYON_HEADER2) ||
59722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			    ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
59822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				DRM_ERROR("Missing Vertex Fire command, "
59922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie					  "Stray Vertex Fire command  or verifier "
60022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie					  "lost sync.\n");
60122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				ret = 1;
60222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				break;
60322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			}
60422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			if ((ret = eat_words(&buf, buf_end, dw_count)))
60522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				break;
60622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
60722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if (buf >= buf_end && !have_fire) {
60822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			DRM_ERROR("Missing Vertex Fire command or verifier "
60922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				  "lost sync.\n");
61022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			ret = 1;
61122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
61222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
61322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) {
61422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			DRM_ERROR("AGP Primitive list end misaligned.\n");
61522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			ret = 1;
61622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
61722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
618b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	}
61922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	*buffer = buf;
62022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return ret;
62122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
62222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
62322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic __inline__ verifier_state_t
62458c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiservia_check_header2(uint32_t const **buffer, const uint32_t *buf_end,
62558c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser		  drm_via_state_t *hc_state)
62622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
62722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	uint32_t cmd;
62822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	int hz_mode;
62922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	hazard_t hz;
63022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	const uint32_t *buf = *buffer;
63122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	const hazard_t *hz_table;
63222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
63322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if ((buf_end - buf) < 2) {
634b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		DRM_ERROR
635b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
63622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
63722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
63822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	buf++;
63922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	cmd = (*buf++ & 0xFFFF0000) >> 16;
64022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
641b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	switch (cmd) {
64222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case HC_ParaType_CmdVdata:
643b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if (via_check_prim_list(&buf, buf_end, hc_state))
64422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			return state_error;
64522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		*buffer = buf;
64622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_command;
64722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case HC_ParaType_NotTex:
64822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		hz_table = table1;
64922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
65022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case HC_ParaType_Tex:
65122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		hc_state->texture = 0;
65222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		hz_table = table2;
65322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
65422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
65522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		hc_state->texture = 1;
65622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		hz_table = table2;
65722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
65822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
65922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		hz_table = table3;
66022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
66122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case HC_ParaType_Auto:
66222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if (eat_words(&buf, buf_end, 2))
66322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			return state_error;
66422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		*buffer = buf;
66522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_command;
66622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)):
66722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if (eat_words(&buf, buf_end, 32))
66822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			return state_error;
66922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		*buffer = buf;
67022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_command;
67122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)):
67222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)):
67322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Texture palettes are rejected because of "
67422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			  "lack of info how to determine their size.\n");
67522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
67622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)):
67722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Fog factor palettes are rejected because of "
67822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			  "lack of info how to determine their size.\n");
67922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
68022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	default:
68122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
68222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		/*
68322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		 * There are some unimplemented HC_ParaTypes here, that
68422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		 * need to be implemented if the Mesa driver is extended.
68522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		 */
68622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
68722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
688b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			  "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
689b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			  cmd, *(buf - 2));
69022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		*buffer = buf;
69122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
69222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
69322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
694b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	while (buf < buf_end) {
69522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cmd = *buf++;
69622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if ((hz = hz_table[cmd >> 24])) {
69722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
69822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				if (hz_mode == 1) {
69922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie					buf--;
70022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie					break;
70122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				}
70222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				return state_error;
70322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			}
704b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		} else if (hc_state->unfinished &&
70522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			   finish_current_sequence(hc_state)) {
70622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			return state_error;
70722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
70822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
70958c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser	if (hc_state->unfinished && finish_current_sequence(hc_state))
71022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
71122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	*buffer = buf;
71222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return state_command;
71322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
71422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
71522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic __inline__ verifier_state_t
71658c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiservia_parse_header2(drm_via_private_t *dev_priv, uint32_t const **buffer,
71758c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser		  const uint32_t *buf_end, int *fire_count)
71822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
71922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	uint32_t cmd;
72022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	const uint32_t *buf = *buffer;
721b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	const uint32_t *next_fire;
72222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	int burst = 0;
72322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
72422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	next_fire = dev_priv->fire_offsets[*fire_count];
72522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	buf++;
72622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	cmd = (*buf & 0xFFFF0000) >> 16;
72722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
728b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	switch (cmd) {
72922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	case HC_ParaType_CmdVdata:
73022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		while ((buf < buf_end) &&
731b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		       (*fire_count < dev_priv->num_fire_offsets) &&
732b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		       (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
733b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			while (buf <= next_fire) {
734b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
735b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie					  (burst & 63), *buf++);
73622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				burst += 4;
73722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			}
738b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			if ((buf < buf_end)
739b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			    && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
74022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				buf++;
74122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
742b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			if (++(*fire_count) < dev_priv->num_fire_offsets)
74322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				next_fire = dev_priv->fire_offsets[*fire_count];
74422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
74522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		break;
74622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	default:
747b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		while (buf < buf_end) {
748b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
749b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			if (*buf == HC_HEADER2 ||
750b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			    (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
751b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			    (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
752b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			    (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
753b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				break;
754b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
755b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
756b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				  (burst & 63), *buf++);
757b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			burst += 4;
75822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
75922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
76022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	*buffer = buf;
76122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return state_command;
76222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
76322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
764b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airliestatic __inline__ int verify_mmio_address(uint32_t address)
76522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
766b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	if ((address > 0x3FF) && (address < 0xC00)) {
76722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Invalid VIDEO DMA command. "
76822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			  "Attempt to access 3D- or command burst area.\n");
76922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 1;
77022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	} else if ((address > 0xCFF) && (address < 0x1300)) {
77122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Invalid VIDEO DMA command. "
77222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			  "Attempt to access PCI DMA area.\n");
773b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		return 1;
774b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	} else if (address > 0x13FF) {
77522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Invalid VIDEO DMA command. "
77622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			  "Attempt to access VGA registers.\n");
77722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 1;
77822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
77922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return 0;
78022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
78122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
78222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic __inline__ int
783b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlieverify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
784b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		  uint32_t dwords)
78522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
78622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	const uint32_t *buf = *buffer;
78722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
78822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if (buf_end - buf < dwords) {
78922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal termination of video command.\n");
79022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return 1;
79122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
79222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	while (dwords--) {
79322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if (*buf++) {
79422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			DRM_ERROR("Illegal video command tail.\n");
79522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			return 1;
79622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
79722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
79822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	*buffer = buf;
79922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return 0;
80022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
80122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
80222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic __inline__ verifier_state_t
803b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlievia_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
80422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
80522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	uint32_t cmd;
80622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	const uint32_t *buf = *buffer;
80722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	verifier_state_t ret = state_command;
80822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
80922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	while (buf < buf_end) {
81022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cmd = *buf;
81122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
812b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		    (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
813b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
81422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				break;
81522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			DRM_ERROR("Invalid HALCYON_HEADER1 command. "
81622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				  "Attempt to access 3D- or command burst area.\n");
81722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			ret = state_error;
81822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
81922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		} else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
820b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
82122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				break;
82222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			DRM_ERROR("Invalid HALCYON_HEADER1 command. "
82322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				  "Attempt to access VGA registers.\n");
82422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			ret = state_error;
825b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			break;
826b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		} else {
82722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			buf += 2;
82822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
82922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
83022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	*buffer = buf;
83122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return ret;
83222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
83322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
83422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic __inline__ verifier_state_t
83558c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiservia_parse_header1(drm_via_private_t *dev_priv, uint32_t const **buffer,
83658c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser		  const uint32_t *buf_end)
83722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
83822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	register uint32_t cmd;
83922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	const uint32_t *buf = *buffer;
84022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
84122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	while (buf < buf_end) {
84222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		cmd = *buf;
843b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
844b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			break;
845b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		VIA_WRITE((cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
84622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		buf++;
84722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
84822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	*buffer = buf;
84922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return state_command;
85022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
85122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
85222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic __inline__ verifier_state_t
85358c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiservia_check_vheader5(uint32_t const **buffer, const uint32_t *buf_end)
85422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
85522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	uint32_t data;
85622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	const uint32_t *buf = *buffer;
85722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
85822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if (buf_end - buf < 4) {
85922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal termination of video header5 command\n");
86022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
86122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
86222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
86322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	data = *buf++ & ~VIA_VIDEOMASK;
86422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if (verify_mmio_address(data))
86522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
86622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
86722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	data = *buf++;
86822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if (*buf++ != 0x00F50000) {
86922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal header5 header data\n");
87022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
87122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
87222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if (*buf++ != 0x00000000) {
87322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal header5 header data\n");
87422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
87522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
876b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	if (eat_words(&buf, buf_end, data))
87722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
878b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
87922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
88022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	*buffer = buf;
88122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return state_command;
882b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
883b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie}
88422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
88522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic __inline__ verifier_state_t
88658c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiservia_parse_vheader5(drm_via_private_t *dev_priv, uint32_t const **buffer,
88758c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser		   const uint32_t *buf_end)
88822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
889b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	uint32_t addr, count, i;
89022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	const uint32_t *buf = *buffer;
891b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
89222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	addr = *buf++ & ~VIA_VIDEOMASK;
89322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	i = count = *buf;
89422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	buf += 3;
89558c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser	while (i--)
89622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		VIA_WRITE(addr, *buf++);
897b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	if (count & 3)
898b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		buf += 4 - (count & 3);
89922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	*buffer = buf;
900b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	return state_command;
901b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie}
90222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
90322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic __inline__ verifier_state_t
904b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlievia_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
90522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
90622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	uint32_t data;
90722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	const uint32_t *buf = *buffer;
90822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	uint32_t i;
90922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
91022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if (buf_end - buf < 4) {
91122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal termination of video header6 command\n");
91222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
91322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
91422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	buf++;
91522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	data = *buf++;
91622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if (*buf++ != 0x00F60000) {
91722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal header6 header data\n");
91822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
91922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
92022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if (*buf++ != 0x00000000) {
92122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal header6 header data\n");
92222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
92322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
92422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if ((buf_end - buf) < (data << 1)) {
92522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		DRM_ERROR("Illegal termination of video header6 command\n");
92622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
92722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
928b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	for (i = 0; i < data; ++i) {
92922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		if (verify_mmio_address(*buf++))
93022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			return state_error;
93122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		buf++;
93222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
93322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	data <<= 1;
93422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
93522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		return state_error;
93622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	*buffer = buf;
93722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return state_command;
938b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie}
93922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
94022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliestatic __inline__ verifier_state_t
94158c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiservia_parse_vheader6(drm_via_private_t *dev_priv, uint32_t const **buffer,
94258c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser		   const uint32_t *buf_end)
94322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
94422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
945b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	uint32_t addr, count, i;
94622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	const uint32_t *buf = *buffer;
94722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
94822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	i = count = *++buf;
94922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	buf += 3;
950b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	while (i--) {
95122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		addr = *buf++;
95222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		VIA_WRITE(addr, *buf++);
95322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
95422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	count <<= 1;
955b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	if (count & 3)
956b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		buf += 4 - (count & 3);
95722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	*buffer = buf;
95822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return state_command;
959b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie}
96022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
961b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlieint
962b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlievia_verify_command_stream(const uint32_t * buf, unsigned int size,
96384b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlie			  struct drm_device * dev, int agp)
96422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
96522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
96622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
96722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	drm_via_state_t *hc_state = &dev_priv->hc_state;
96822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	drm_via_state_t saved_state = *hc_state;
96922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	uint32_t cmd;
970b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	const uint32_t *buf_end = buf + (size >> 2);
97122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	verifier_state_t state = state_command;
972689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom	int cme_video;
973689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom	int supported_3d;
974689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom
975689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom	cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A ||
976689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom		     dev_priv->chipset == VIA_DX9_0);
977689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom
978689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom	supported_3d = dev_priv->chipset != VIA_DX9_0;
979b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
98022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	hc_state->dev = dev;
98122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	hc_state->unfinished = no_sequence;
98222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	hc_state->map_cache = NULL;
98322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	hc_state->agp = agp;
98422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	hc_state->buf_start = buf;
98522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	dev_priv->num_fire_offsets = 0;
98622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
98722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	while (buf < buf_end) {
98822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
98922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		switch (state) {
99022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_header2:
991b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			state = via_check_header2(&buf, buf_end, hc_state);
99222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
99322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_header1:
994b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			state = via_check_header1(&buf, buf_end);
99522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
99622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_vheader5:
997b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			state = via_check_vheader5(&buf, buf_end);
99822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
99922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_vheader6:
1000b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			state = via_check_vheader6(&buf, buf_end);
100122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
100222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_command:
1003689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom			if ((HALCYON_HEADER2 == (cmd = *buf)) &&
1004689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom			    supported_3d)
100522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				state = state_header2;
1006b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
100722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				state = state_header1;
1008689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom			else if (cme_video
1009b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				 && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
101022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				state = state_vheader5;
1011689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom			else if (cme_video
1012b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				 && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
101322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				state = state_vheader6;
1014689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom			else if ((cmd == HALCYON_HEADER2) && !supported_3d) {
1015689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom				DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n");
1016689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom				state = state_error;
1017689692e73ea4b95c9fa5d5913eade33147db2e5aThomas Hellstrom			} else {
1018b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				DRM_ERROR
1019b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				    ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
1020b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				     cmd);
102122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				state = state_error;
102222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			}
102322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
102422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_error:
102522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		default:
102622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			*hc_state = saved_state;
102720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt			return -EINVAL;
102822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
1029b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	}
103022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	if (state == state_error) {
103122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		*hc_state = saved_state;
103220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
103322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	}
103422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return 0;
103522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
103622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
1037b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlieint
103858c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiservia_parse_command_stream(struct drm_device *dev, const uint32_t *buf,
1039b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			 unsigned int size)
104022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
104122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
104222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
104322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	uint32_t cmd;
1044b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	const uint32_t *buf_end = buf + (size >> 2);
104522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	verifier_state_t state = state_command;
104622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	int fire_count = 0;
1047b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie
104822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	while (buf < buf_end) {
104922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
105022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		switch (state) {
105122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_header2:
1052b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			state =
1053b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			    via_parse_header2(dev_priv, &buf, buf_end,
1054b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie					      &fire_count);
105522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
105622f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_header1:
1057b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			state = via_parse_header1(dev_priv, &buf, buf_end);
105822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
105922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_vheader5:
1060b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			state = via_parse_vheader5(dev_priv, &buf, buf_end);
106122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
106222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_vheader6:
1063b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			state = via_parse_vheader6(dev_priv, &buf, buf_end);
106422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
106522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_command:
1066b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			if (HALCYON_HEADER2 == (cmd = *buf))
106722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				state = state_header2;
1068b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
106922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				state = state_header1;
107022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
107122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				state = state_vheader5;
107222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
107322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				state = state_vheader6;
107422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			else {
1075b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				DRM_ERROR
1076b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				    ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
1077b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie				     cmd);
107822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie				state = state_error;
107922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			}
108022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie			break;
108122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		case state_error:
108222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		default:
108320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt			return -EINVAL;
108422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		}
1085b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	}
108658c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser	if (state == state_error)
108720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
108822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	return 0;
108922f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
109022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
1091b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airliestatic void
109222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airliesetup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
109322f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
109422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie	int i;
109522f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
109658c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser	for (i = 0; i < 256; ++i)
109722f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		table[i] = forbidden_command;
109822f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
109958c1e85af3645ac8df021dbf14acd215b5687f54Nicolas Kaiser	for (i = 0; i < size; ++i)
110022f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie		table[init_table[i].code] = init_table[i].hz;
110122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
110222f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie
1103b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlievoid via_init_command_verifier(void)
110422f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie{
1105b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	setup_hazard_table(init_table1, table1,
1106b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			   sizeof(init_table1) / sizeof(hz_init_t));
1107b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	setup_hazard_table(init_table2, table2,
1108b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			   sizeof(init_table2) / sizeof(hz_init_t));
1109b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	setup_hazard_table(init_table3, table3,
1110b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			   sizeof(init_table3) / sizeof(hz_init_t));
111122f579c621e2f264e6d093b07d75f99bc97d5df2Dave Airlie}
1112