/*
    Copyright 2000 (c) by Author,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public 
    Licence. A full copy of the GNU GPL is provided in the file COPYING 
    found in the development root of Topsy.
*/
/*
	
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/IO/ia32/Drivers/names.c,v $
    Author(s):             
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Creation Date:         
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $      by: $Author: baderma $
 
 
    $Log: names.c,v $
    Revision 1.2  2000/11/23 11:17:47  cjeker
    fixes for ia32 Now ia32 and mips should work again
 
 
*/

/*
 *	PCI Class and Device Name Tables
 */

#include "IOPci.h"
#include "Support.h"

//-CJ #ifdef LINUX
//-CJ #include <stdio.h>
//-CJ #endif LINUX


#ifdef CONFIG_PCI_NAMES

typedef struct pci_device_info_t
{
  unsigned short deviceID;
  unsigned short seen;
  const char *name;
}
pci_device_info;

typedef struct pci_vendor_info_t
{
  unsigned short vendorID;
  unsigned short nrDevices;
  const char *name;
  pci_device_info *devices;
}
pci_vendor_info;


#define VENDOR( vendor, name )		static const char __vendorstr_##vendor[] = name;
#define ENDVENDOR()
#define DEVICE( vendor, device, name ) 	static const char __devicestr_##vendor##device[] = name;
#include "devlist.h"


#define VENDOR( vendor, name )		static pci_device_info __devices_##vendor[] = {
#define ENDVENDOR()			};
#define DEVICE( vendor, device, name )	{ 0x##device, 0, __devicestr_##vendor##device },
#include "devlist.h"


static const pci_vendor_info pci_vendor_list[] =
  {
#define VENDOR( vendor, name )		{ 0x##vendor, sizeof(__devices_##vendor) / sizeof(pci_device_info), __vendorstr_##vendor, __devices_##vendor },
#define ENDVENDOR()
#define DEVICE( vendor, device, name )
#include "devlist.h"
  };


#define VENDORS (sizeof(pci_vendor_list)/sizeof(pci_vendor_info))

void ioPciNameDevice(IOPciDeviceDesc* devPciPtr)
{
  const pci_vendor_info *vendor_p = pci_vendor_list;
  int i = VENDORS;
  char *name = devPciPtr->name;

  do
  {
    if (vendor_p->vendorID == devPciPtr->vendorID)
      goto match_vendor;
    vendor_p++;
  }
  while (--i);

  /* Couldn't find either the vendor nor the device */
  snprintf(name, IO_MAX_NAME_SIZE, "PCI device %04x:%04x", devPciPtr->vendorID, devPciPtr->deviceID);
  return;

match_vendor:
  {
    pci_device_info *device_p = vendor_p->devices;
    int i = vendor_p->nrDevices;

    while (i > 0)
    {
      if (device_p->deviceID == devPciPtr->deviceID)
        goto match_device;
      device_p++;
      i--;
    }

    /* Ok, found the vendor, but unknown device */
    snprintf(name, IO_MAX_NAME_SIZE, "PCI device %04x:%04x (%s)", devPciPtr->vendorID, devPciPtr->deviceID, vendor_p->name);
    return;

    /* Full match */
match_device:
    {
      char *n = name + snprintf(name, IO_MAX_NAME_SIZE, "%s %s", vendor_p->name, device_p->name);
      int nr = device_p->seen + 1;
      device_p->seen = nr;
      if (nr > 1)
        snprintf(n, IO_MAX_NAME_SIZE -(n - name), " (#%d)", nr);
    }
  }
}

/*
 *  Class names
 */

static u16 pci_class_numbers[] =
  {
#define CLASS(x,y) 0x##x,
#include "classlist.h"
  };

static char *pci_class_names[] =
  {
#define CLASS(x,y) y,
#include "classlist.h"
  };

void ioPciNameClass(IOPciDeviceDesc* devPciPtr)
{
  int i;
  u16 classCode; /* =ClassID and SubClassID */

  classCode = (u16)(devPciPtr->classID);
  classCode = classCode << 8;
  classCode = classCode | (u16)(devPciPtr->subClassID);

  for(i=0; i<sizeof(pci_class_numbers)/sizeof(pci_class_numbers[0]); i++)
  {
    if (pci_class_numbers[i] == classCode)
    {
      str_cpy(devPciPtr->className, pci_class_names[i]);
    }
  }
}
#endif CONFIG_PCI_NAMES
