/* vim: set filetype=c:
 *
 * pci.h86  -  Definitions for ROM PCI header
 *
 * Copyright (C) 2003-2007 Gero Kuhlmann <gero@gkminix.han.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: pci.h86,v 1.9 2007/01/06 18:31:10 gkminix Exp $
 */

#ifndef SYSTEM_PCI_H86
#define SYSTEM_PCI_H86


/*
 * First include the main header file.
 */
#define GCC_INCLUDE
#include <system/pci.h>



/*
 **************************************************************************
 *
 * PCI BIOS interface
 */

/*
 * PCI BIOS functions
 */
#define PCI_FUNC_INST_CHECK	0xB101		/* PCI BIOS inst. check */
#define PCI_FUNC_FIND_DEV	0xB102		/* find PCI device */
#define PCI_FUNC_FIND_CLASS	0xB103		/* find PCI class code */
#define PCI_FUNC_BUS_OP		0xB106		/* PCI bus-specific operation */
#define PCI_FUNC_READ_BYTE	0xB108		/* read configuration byte */
#define PCI_FUNC_READ_WORD	0xB109		/* read configuration word */
#define PCI_FUNC_READ_DWORD	0xB10A		/* read configuration dword */
#define PCI_FUNC_WRITE_BYTE	0xB10B		/* write configuration byte */
#define PCI_FUNC_WRITE_WORD	0xB10C		/* write configuration word */
#define PCI_FUNC_WRITE_DWORD	0xB10D		/* write configuration dword */
#define PCI_FUNC_GET_IRQ	0xB10E		/* get IRQ routing table */
#define PCI_FUNC_SET_IRQ	0xB10F		/* set IRQ routing table */



/*
 * PCI installation check magic ID
 */
#define PCI_INST_MAGIC		0x20494350



/*
 * PCI register offsets
 */
#define PCI_REG_VENDOR_ID	0x0000		/* vendor ID (word) */
#define PCI_REG_DEVICE_ID	0x0002		/* device ID (word) */
#define PCI_REG_COMMAND		0x0004		/* command flags (word) */
#define PCI_REG_STATUS		0x0006		/* status register (word) */
#define PCI_REG_REVISION	0x0008		/* revision ID (byte) */
#define PCI_REG_CLASS_PROG	0x0009		/* interface level (byte) */
#define PCI_REG_CLASS_DEVICE	0x000A		/* device class (word) */
#define PCI_REG_CACHE_SIZE	0x000C		/* cache line size (byte) */
#define PCI_REG_LATENCY_TIMER	0x000D		/* latency timer (byte) */
#define PCI_REG_HEADER_TYPE	0x000E		/* header type (byte) */
#define PCI_REG_BIST		0x000F		/* self test (byte) */
#define PCI_REG_ADDR_0		0x0010		/* base addresses (dword) */
#define PCI_REG_ADDR_1		0x0014
#define PCI_REG_ADDR_2		0x0018
#define PCI_REG_ADDR_3		0x001C
#define PCI_REG_ADDR_4		0x0020
#define PCI_REG_ADDR_5		0x0024



/*
 * Header type 0 (normal devices)
 */

#define PCI_REG_CARDBUS_CIS	0x0028
#define PCI_REG_SUBSYS_VEND	0x002C		/* subsystem vendor ID (word) */
#define PCI_REG_SUBSYS_ID	0x002E		/* subsystem device ID (word) */
#define PCI_REG_ROM_ADDR	0x0030		/* ROM address (dword) */
#define PCI_REG_CAP_LIST	0x0034		/* start of capability list */
#define PCI_REG_INT_LINE	0x003C		/* IRQ line number (byte) */
#define PCI_REG_INT_PIN		0x003D		/* IRQ pin number (byte) */
#define PCI_REG_MIN_GNT		0x003E		/* min. grant time (byte) */
#define PCI_REG_MAX_LAT		0x003F		/* max. latency time (byte) */



/*
 * Command register bit fields
 */
#define PCI_CMD_IO		0b0000000000000001 /* enable I/O space */
#define PCI_CMD_MEMORY		0b0000000000000010 /* enable memory space */
#define PCI_CMD_MASTER		0b0000000000000100 /* enable bus mastering */
#define PCI_CMD_SPECIAL		0b0000000000001000 /* enable special cycles */
#define PCI_CMD_INVALIDATE	0b0000000000010000 /* use memory invalidate */
#define PCI_CMD_VGA_PALETTE	0b0000000000100000 /* enable palette snoop */
#define PCI_CMD_PARITY		0b0000000001000000 /* enable parity checking */
#define PCI_CMD_WAIT		0b0000000010000000 /* enable addr stepping */
#define PCI_CMD_SERR		0b0000000100000000 /* enable SERR */
#define PCI_CMD_FAST_BACK	0b0000001000000000 /* enable back-to-back */



/*
 * Status register bit fields
 */
#define PCI_STS_CAP_LIST	0b0000000000010000 /* support capabil. list */
#define PCI_STS_66MHZ		0b0000000000100000 /* support 66 MHz bus */
#define PCI_STS_UDF		0b0000000001000000 /* support UDF (obsolete) */
#define PCI_STS_FAST_BACK	0b0000000010000000 /* support back-to-back */
#define PCI_STS_PARITY		0b0000000100000000 /* detected parity error */
#define PCI_STS_DEVSEL_MASK	0b0000011000000000 /* DEVSEL timing bits */
#define PCI_STS_SIG_TARGET	0b0000100000000000 /* set on target abort */
#define PCI_STS_REC_TARGET	0b0001000000000000 /* ack of target abort */
#define PCI_STS_SIG_MASTER	0b0010000000000000 /* set on master abort */
#define PCI_STS_SIG_SYSTEM	0b0100000000000000 /* set on system error */
#define PCI_STS_DET_PARITY	0b1000000000000000 /* parity detected */



/*
 **************************************************************************
 *
 * Macros to call PCI BIOS
 */

#ifndef _ASSEMBLY_

/*
 * Read a byte from PCI configuration space
 */
__nb_inline__ __u8 pci_read_byte(__u16 pcipfa, __u16 regnum)
{
  __u8 ret;
  __u32 d0, d1, d2;

  __asm__ __volatile__(
	"int $0x1A"
	: "=&a" (d0), "=&b" (d1), "=c" (ret), "=&d" (d2)
	: "0" (PCI_FUNC_READ_BYTE), "1" (pcipfa), "D" (regnum));

  return(ret);
}


/*
 * Read a word from PCI configuration space
 */
__nb_inline__ __u16 pci_read_word(__u16 pcipfa, __u16 regnum)
{
  __u16 ret;
  __u32 d0, d1, d2;

  __asm__ __volatile__(
	"int $0x1A"
	: "=&a" (d0), "=&b" (d1), "=c" (ret), "=&d" (d2)
	: "0" (PCI_FUNC_READ_WORD), "1" (pcipfa), "D" (regnum));

  return(ret);
}


/*
 * Read a double-word from PCI configuration space
 */
__nb_inline__ __u32 pci_read_dword(__u16 pcipfa, __u16 regnum)
{
  __u32 ret;
  __u32 d0, d1, d2;

  __asm__ __volatile__(
	"int $0x1A"
	: "=&a" (d0), "=&b" (d1), "=c" (ret), "=d" (d2)
	: "0" (PCI_FUNC_READ_DWORD), "1" (pcipfa), "D" (regnum));

  return(ret);
}


/*
 * Write a byte into PCI configuration space
 */
__nb_inline__ void pci_write_byte(__u16 pcipfa, __u16 regnum, __u8 value)
{
  __u32 d0, d1, d2, d3;

  __asm__ __volatile__(
	"int $0x1A"
	: "=&a" (d0), "=&b" (d1), "=&c" (d2), "=d" (d3)
	: "0" (PCI_FUNC_WRITE_BYTE), "1" (pcipfa), "2" (value), "D" (regnum));
}


/*
 * Write a word into PCI configuration space
 */
__nb_inline__ void pci_write_word(__u16 pcipfa, __u16 regnum, __u16 value)
{
  __u32 d0, d1, d2, d3;

  __asm__ __volatile__(
	"int $0x1A"
	: "=&a" (d0), "=&b" (d1), "=&c" (d2), "=d" (d3)
	: "0" (PCI_FUNC_WRITE_WORD), "1" (pcipfa), "2" (value), "D" (regnum));
}


/*
 * Write a double-word into PCI configuration space
 */
__nb_inline__ void pci_write_dword(__u16 pcipfa, __u16 regnum, __u32 value)
{
  __u32 d0, d1, d2, d3;

  __asm__ __volatile__(
	"int $0x1A"
	: "=&a" (d0), "=&b" (d1), "=&c" (d2), "=d" (d3)
	: "0" (PCI_FUNC_WRITE_DWORD), "1" (pcipfa), "2" (value), "D" (regnum));
}


#endif

#endif

