[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::digital_unix

Title:DIGITAL UNIX(FORMERLY KNOWN AS DEC OSF/1)
Notice:Welcome to the Digital UNIX Conference
Moderator:SMURF::DENHAM
Created:Thu Mar 16 1995
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:10068
Total number of notes:35879

8717.0. "PCI device driver problem for v4.0" by NETRIX::"[email protected]" (Roberto Romani) Wed Feb 05 1997 05:00

Hello all,

       I received the following mail from a customer and I wonder if some one
has seen this before

I have an AXPpci33 running DUnix 4.0B, and am developing a device driver 
for a PCI based DMA card (an Ikon 10116 DR11-W emulator) for a RT data 
acquisition system.

I had a driver working under DUnix 3.2C up to the point where I could do 
programmed transfers to the external channel of the Ikon card, but had 
not at that stage attempted DMA or interrupts. We then upgraded the 
machine to DUnix 4.0, and would like to operate under this version.

The symptom is that the OS hangs on LOADING the driver dynamically.

I have made the changes required for the driver to work under DUnix 4.0. 
I have also stripped all the code out which is specific to the Ikon card 
(so that the only code left in the driver is to do with 
autoconfiguration and configuration), so that it just interrogates the 
standard PCI header of the device.

More specifically, the cfgmgr calls the ikdrw_configure interface with 
the CFG_OP_CONFIGURE option to configure the driver and the following 
happens:
  o The driver calls cfgmgr_get_state to check that it is being
        loaded dynamically. It aborts if it is not.
  o The driver checks the sysconfigtab parameters, and they are ok.
  o The driver populates a controller_config struct and calls
        create_controller_struct to register it.
  o The driver populates a device_config struct and calls
        create_device_struct to register it.
  o The driver calls configure_driver to configure the driver. This
        seems to fail, hanging the kernel.
If I force the probe interface to return a failure, this works as 
expected. Diagnostics from the probe indicate that the device has been 
found properly, even returning correct values from things like the DMA 
FIFO status registers (indicating that the device really is working and 
talking correctly to the bus). If the probe returns success, the kernel 
hangs, with no diagnostics (from the printf statements) when the system 
is reset and rebooted. The problem seems to manifest itself somewhere 
between where the driver's probe interface returns to the kernel and 
where the kernel returns control to the driver (as the return from the 
configure_driver kernel interface).

The code is substantially identical to the /dev/none example driver.

Are there any known problems here? The driver source is attached. I have 
spent about two weeks trawling over the code making sure all the kernel 
calls match the online documentation, etc, and removed all extra code 
from the driver, so that it is the bare code to support configuration of 
the device. As I mentioned above, it has no Ikon specific code, and 
should work with any PCI device, but the behaviour is the same with an 
found properly, even returning correct values from things like the DMA 
FIFO status registers (indicating that the device really is working and 
talking correctly to the bus). If the probe returns success, the kernel 
hangs, with no diagnostics (from the printf statements) when the system 
is reset and rebooted. The problem seems to manifest itself somewhere 
between where the driver's probe interface returns to the kernel and 
where the kernel returns control to the driver (as the return from the 
configure_driver kernel interface).

The code is substantially identical to the /dev/none example driver.

Are there any known problems here? The driver source is attached. I have 
spent about two weeks trawling over the code making sure all the kernel 
calls match the online documentation, etc, and removed all extra code 
from the driver, so that it is the bare code to support configuration of 
the device. As I mentioned above, it has no Ikon specific code, and 
should work with any PCI device, but the behaviour is the same with an 

P.S.
The next reply will contain the source for those interested


regards
Roberto Romani
Unix Support
Sydney TSC
Australia


[Posted by WWW Notes gateway]
T.RTitleUserPersonal
Name
DateLines
8717.1source code and moreNETRIX::"[email protected]"Wed Feb 05 1997 05:35911
 /* ikdrw_driver.c */

#define DEBUG 1

/* 
 * Digital Unix device driver for Ikon 10116 DR11-W emulator.
 *
 * Author: David G Loone
 * Organization: CSIRO Australia Telescope
 *
 * The Ikon 10116 device is a PCI board which externally emulates a DEC
 * DR11-W. This device performs input and output DMA of 16-bit data words.
 *
 * The driver exists as a loadable kernel subsystem only. It will not build
 * as a static subsystem.
 */

/* Software version. This version string can be obtained at runtime
 * by doing a query of the subsystem. */
#define VERSION "0.00"
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__

/* Define how many controllers will be supported by the driver. */
#define MAX_NUM_CTLR 1

/* Define how many devices (maximum number of logical units). */
#define MAX_NUM_DEV 1

/* Define the controller name. */
#define CTLR_NAME "ikdrw"

/* Define the device name. */
#define DEV_NAME "ikdrwdev"

/* The device is on the PCI bus. */
#define BUS_NAME "pci"

/* Define a string which is the "device type". */
#define DEV_TYPE "DMA"

/* The maximum size of the PCI_Option sysconfigtab parameter. */
#define PCI_OPTION_SZ 400

/*
 ****************************************************************************
 * Include files section.
 ****************************************************************************
 */

/*
 * Common driver header files.
 */

 */
#include <sys/conf.h>
#include <sys/malloc.h>
#include <io/dec/pci/pci.h>
#include <sys/sysconfig.h>

/* Include file for things we want to share with user programs. */
#include "ikdrw_driver.h"

/*
 ****************************************************************************
 * Autoconfiguration support declarations and definitions section.
 ****************************************************************************
 */

/* Forward declarations of driver interfaces */
int ikdrw_probe();              /* probe */
int ikdrw_cattach();            /* cattach */
int ikdrw_ctlr_unattach();      /* ctlr_unattach */

char* toStr_base();

char* toStr_sub();

char* toStr_cfg_attr();

/* Declare an array of pointers to controller structs. There will be
 * one controller struct for each controller found. */
struct controller* controllers[MAX_NUM_CTLR];

/* Declare and initialize the driver structure. The driver structure defines
 * entry points and other driver-specific information. */
struct driver ikdrw_driver = {
  ikdrw_probe,          /* probe */
  NULL,                 /* slave */
  ikdrw_cattach,        /* cattach */
  NULL,                 /* dattach */
  NULL,                 /* go */
  NULL,                 /* addr_list */
  NULL,                 /* dev_name */
  NULL,                 /* dev_list */
  CTLR_NAME,            /* ctlr_name */
  controllers,          /* ctlr_list */
  0,                    /* xclu (not used) */
  0,                    /* addr1_size (VME only) */
  0,                    /* addr1_atype (VME only) */
  0,                    /* addr2_size (VME only) */
  0,                    /* addr2_atype (VME only) */
  ikdrw_ctlr_unattach,  /* ctlr_unattach */
  NULL                  /* dev_unattach */
};


/*
 ****************************************************************************
 * Loadable driver configuration support declarations and definitions
 * section.
 ****************************************************************************
 */

/* Declare and initialize the cfg_subsys_attr_t structure. This structure
 * contains attribute information for loadable drivers. Elements of this
 * structure correspond to elements of the sysconfigtab file entry. */
/* The following elements correspond exactly to the elements of the
 * sysconfigtab file entry. Values are loaded from the ikdrw section of
 * the sysconfigtab file into these variables at configuration time. */
static unsigned char moduleConfigName[CFG_ATTR_NAME_SZ] = "";
static unsigned char deviceMajorReq[CFG_ATTR_NAME_SZ] = "";
static unsigned char deviceCharMajor[CFG_ATTR_NAME_SZ] = "";
static unsigned char PCIOption[PCI_OPTION_SZ] = "";
/* The following elements are provided for extra communication between the
 * driver subsystem and the outside world. They are all set at configuration
 * time and can be queried by the subsystem manager, but not set. */
/* The character device major device number. This is set at configuration
 * time. */
static int majorNum = -1;
/* Begin unit number. This is the minor device number of the first unit. */
static int beginUnit = 0;
/* This is the number of units which were successfully probed. */
static int numUnit = 0;
/* This is the driver version number. */
static int ikdrwVersion = 0;
/* Put the above variables into an attributes structure. */
cfg_subsys_attr_t ikdrw_attributes[] = {
  {
    "Module_Config_Name",             /* name */
    CFG_ATTR_STRTYPE,                 /* type */
    CFG_OP_CONFIGURE | CFG_OP_QUERY,  /* operation */
    (caddr_t)moduleConfigName,        /* addr */
    2,                                /* min_val */
    CFG_ATTR_NAME_SZ,                 /* max_val */
    0                                 /* val_size */
    },
  {"Device_Major_Req",CFG_ATTR_STRTYPE,CFG_OP_CONFIGURE | CFG_OP_QUERY,
    (caddr_t)deviceMajorReq,0,CFG_ATTR_NAME_SZ,0},
  {"Device_Char_Major",CFG_ATTR_STRTYPE,CFG_OP_CONFIGURE | CFG_OP_QUERY,
    (caddr_t)deviceCharMajor,0,CFG_ATTR_NAME_SZ,0},
  {"PCI_Option",CFG_ATTR_STRTYPE,CFG_OP_CONFIGURE | CFG_OP_QUERY,
    (caddr_t)PCIOption,0,PCI_OPTION_SZ,0},
  {"majnum",CFG_ATTR_INTTYPE,CFG_OP_QUERY,(caddr_t)&majorNum,0,99,0},
  {"begunit",CFG_ATTR_INTTYPE,CFG_OP_QUERY,(caddr_t)&beginUnit,0,8,0},
  {"numunit",CFG_ATTR_INTTYPE,CFG_OP_QUERY,(caddr_t)&numUnit,0,
      MAX_NUM_DEV,0},
  {"version",CFG_ATTR_INTTYPE,CFG_OP_QUERY,(caddr_t)&ikdrwVersion,0,
      9999999,0},
  {"",0,0,0,0,0,0}
};

/* External function references. */
extern int nodev();
extern int nulldev();

/* A count of the number of controllers successfully probed. */
int num_ikdrw = 0;

/* Structure definition for an ikdrw unit. This holds all the things the
 * driver needs to remember for a single unit. */
struct UnitData {
  struct proc* proc;            /* The proc struct for the user process. */
  int attached;                 /* The unit is currently attached. */
  io_handle_t csrBase;          /* CSR base address (IKON address space). */

} unitData[MAX_NUM_CTLR];

/*
 ****************************************************************************
 * Loadable driver local structure and variable definitions section.
 ****************************************************************************
 */

/* State flag indicating driver configured. */
int configured = FALSE;

/* No major number assigned yet. Eventually the value of this variable
 * will end up in the numUnit variable. */
dev_t devNum = NODEV;

/* Device switch structure for dynamic configuration. Defines the driver's
 * entry points in the device switch table. */
struct dsent ikdrw_dsent = {
  nodev,                /* d_open */
  nodev,                /* d_close */
  nodev,                /* d_strategy */
  nodev,                /* d_read */
  nodev,                /* d_write */
  nodev,                /* d_ioctl */
  nodev,                /* d_dump */
  nodev,                /* d_psize */
  nodev,                /* d_stop */
  nodev,                /* d_reset */
  nodev,                /* d_select */
  0,                    /* d_mmap */
  0,                    /* d_segmap */
  NULL,                 /* d_ttys */
  DEV_FUNNEL_NULL,      /* d_funnel */
  0,                    /* d_bflags */
  0                     /* d_cflags */
};

/*
 ****************************************************************************
 * Autoconfiguration support section.
 ****************************************************************************
 */

/****************************************************************************
 * ikdrw_probe
 *
 * The xxprobe interface. */
int
ikdrw_probe(
  /* PCI configuration header. */
  struct pci_config_hdr* pci_cfg_hdr,
  /* Controller struct for this unit. */
  struct controller* ctlr
)
{
  /* Unit number. */
  int unit = ctlr->ctlr_num;

#ifdef DEBUG
  printf("ikdrw (probe): ctlr->ctlr_num = %d\n",ctlr->ctlr_num);
  printPCIInfo("ikdrw: ",pci_cfg_hdr);
#endif

  /* Don't initialize controllers past MAX_NUM_CTLR. If so then return
     failure code. */
  if(unit >= MAX_NUM_CTLR) {
    printf("ikdrw%d: Too many units.\n",unit);
    return(0);
  }

  /* Save PCI configure header in the private element of the controller
   * so that we can refer to it given the controller structure. */
  ctlr->private[0] = pci_cfg_hdr;

  /* Set up the unit data structure for this unit. */
  unitData[unit].proc = 0;
  unitData[unit].attached = 0;
  unitData[unit].csrBase = 0;

  /* Get the controller's CSR base address. This is base of the "local
   * address space" of the PCI device. */
  unitData[unit].csrBase = pci_cfg_hdr->bar2;
#ifdef DEBUG
  printf("ikdrw%d (probe): csrBase=0x%x\n",unit,unitData[unit].csrBase);
  switch(unitData[unit].csrBase & 0x1) {
   case BAR_MEM_MAP:
      printf("ikdrw%d (probe): device CSRs are memory mapped\n",unit);
      break;
    case BAR_IO_MAP:
      printf("ikdrw%d (probe): device CSRs are I/O mapped\n",unit);
      break;
  }
#endif

  /* Increment the number of instances of this controller. */
  num_ikdrw++;

  return(1);
}

/****************************************************************************
 * ikdrw_cattach
 *
 * The xxcattach interface is called by the ldbl_ctlr_configure kernel
 * interface once for each unit found on the bus. In principle, this
 * interface is called after the xxslave interface, but since this device
 * has no xxslave interface, the xxcattach interface is called immediately
 * after the xxprobe interface. */
int
ikdrw_cattach(
  /* Controller struct for this unit. */
  struct controller* ctlr
)
{
  register int unit = ctlr->ctlr_num;

  /* Set the attached flag for this unit. */
  unitData[unit].attached = 1;

  return;
}

/****************************************************************************
 * ikdrw_ctlr_unattach
 *
 * The xxctlr_unattach interface is called by the ldbl_ctlr_unconfigure
 * kernel interface once for each unit found on the bus. */
int
ikdrw_ctlr_unattach(
  /* Bus struct which this controller is connected to. */
  struct bus* bus,
  /* Controller struct for this unit. */
  struct controller* ctlr
)
{
  int i;

  register int unit = ctlr->ctlr_num;

  /* Make sure we are unattaching a unit which exists. */
  if((unit > num_ikdrw) || (unit < 0))
    return(ENODEV);

  /* Clear the unit data structure for this unit. */
  unitData[unit].attached = 0;

  return(ESUCCESS);
}

/*
 ****************************************************************************
 * Loadable device driver section.
 ****************************************************************************
 */

/****************************************************************************
 * ikdrw_configure
 *
 * The xx_configure interface is called when the subsystem is loaded,
 * unloaded or queried. The op argument specifies for which reason the
 * interface is being called. */
int
ikdrw_configure(
  /* Operation to be performed. */
  cfg_op_t op,
  cfg_attr_t* inData,
  size_t inDataLen,
  cfg_attr_t* outData,
  size_t outDataLen
)
{
{
  int i;
  /* Temp storage for return values. */
  int retVal,retVal2;
  /* Configuration manager state (dynamic or static). */
  int cfgmgrState;
  /* The user process. */
  struct proc* proc;
  /* The struct to pass to register_controller_config. */
  struct controller_config ctlrCfg;
  /* The struct to pass to register_device_config. */
  struct device_config devCfg;

#ifdef DEBUG
  switch(op) {
    case CFG_OP_CONFIGURE:
      printf("ikdrw (configure): configure\n");
      break;
    case CFG_OP_UNCONFIGURE:
      printf("ikdrw (configure): unconfigure\n");
      break;
    case CFG_OP_QUERY:
      printf("ikdrw (configure): query\n");
      break;
  }
#endif

  switch(op) {
    case CFG_OP_CONFIGURE:

      printf("ikdrw (configure): version %s, compiled at %s %s\n",
          VERSION,COMPILE_DATE,COMPILE_TIME);

      /* Make sure we are being called as a loadable driver. If it is not,
       * then print an error message and exit. */
      retVal = cfgmgr_get_state(CTLR_NAME,&cfgmgrState);
      if(retVal != ESUCCESS) {
        printf("ikdrw (configure): Error getting cfgmgr state.\n");
        return(retVal);
      }
      if (cfgmgrState != SUBSYSTEM_DYNAMICALLY_CONFIGURED) {
        printf("ikdrw (configure): Must be dynamically configured.\n");
        return(EINVAL);
      }

      /* Check each element of inData. If the status field is anything
       * other than ESUCCESS, print a diagnostic and return an error
       * code. */
      for(i=0; i<inDataLen; i++) {
        switch(inData[i].status) {
          case CFG_ATTR_SUCCESS:
            break;
          default:
            printf("ikdrw (configure): %s: %s\n",inData[i].name,
                toStr_cfg_attr(inData[i].status));
            return(EINVAL);
        }
      }

      /* Populate and register the controller_config structure. */
      ctlrCfg.revision = CTLR_CONFIG_REVISION;
      strcpy(ctlrCfg.subsystem_name,CTLR_NAME);
      strcpy(ctlrCfg.bus_name,BUS_NAME);
      ctlrCfg.devdriver = &ikdrw_driver;
      retVal = create_controller_struct(&ctlrCfg);
      if(retVal != ESUCCESS) {
        printf("ikdrw (configure): Error in create_controller_struct.\n");
        return(retVal);
      }

      /* Populate and register the device_config structure. */
      devCfg.revision = DEVICE_CONFIG_REVISION;
      strcpy(devCfg.device_type,DEV_TYPE);
      strcpy(devCfg.device_name,DEV_NAME);
      strcpy(devCfg.controller_name,CTLR_NAME);
      devCfg.phys_unit_num = 0;
      devCfg.logical_unit_number = 0;
      devCfg.controller_num = 0;
      retVal = create_device_struct(&devCfg);
      if(retVal != ESUCCESS) {
        printf("ikdrw (configure): Error in create_device_struct.\n");
        return(retVal);
      }

      /* Configure the driver. For a dynamically configured driver, the
       * kernel will thus call the probe interface for each device as part
      * of configure_driver. */
      retVal = configure_driver(CTLR_NAME,DRIVER_WILDNUM,BUS_NAME,
          &ikdrw_driver);
      if(retVal != ESUCCESS) {
        printf("ikdrw (configure): Error in configure_driver.\n");
        return(retVal);
      }

      /* Check that we probed at least one controller. */
      if(num_ikdrw == 0) {
        printf("ikdrw (configure): No controllers found.\n");
        return(EINVAL);
      }
/* DEBUGGING */
break;

      /* Register the driver's device switch entry points and obtain the
         major number. */
      /* Register the entry points for the driver interfaces. */
      devNum = devsw_add(CTLR_NAME,1,-1,&ikdrw_dsent);
      if(devNum == NODEV) {
        printf("ikdrw (configue): Error adding device switch table.\n");
        return(ENODEV);
      }
      
      /* Set up the ikdrw_attribute list so that it can be queried. */
      majorNum = major(devNum);
      
      /* Set the beginning minor number and number of instances. */
      beginUnit = 0;
      numUnit = num_ikdrw;
      
      /* The driver is now configured. */
      configured = TRUE;
      break;

    case CFG_OP_UNCONFIGURE:
      /* Make sure the driver has actually been configured. */
      if(configured != TRUE) {
        printf("ikdrw (configure): No devices configured.\n");
        return(EINVAL);
      }
      
      /* Unconfigure all instances. */
      retVal = unconfigure_driver(BUS_NAME,DRIVER_WILDNUM,&ikdrw_driver,
            CTLR_NAME,DRIVER_WILDNUM);
      if(retVal != 0) {
        printf("ikdrw (configure): Error during unconfigure_driver.\n");
        return(ESRCH);
      }
      

      
      /* The driver is now unconfigured. */
      configured = FALSE;
      break;

    case CFG_OP_QUERY:
      break;

    default:
      return(EINVAL);
      break;
  }
  return(0);
}

/****************************************************************************
 * printPCIInfo
 *

 * Prints PCI class information. */
printPCIInfo(
  char* prefix,
  struct pci_config_hdr* cfg
)
{
  /* Decode and print the contents of the command field. */
  printf("%scommand = ",prefix);
  if(cfg->command & CMD_IO_SPACE) printf("IO_SPACE ");
  if(cfg->command & CMD_MEM_SPACE) printf("MEM_SPACE ");
  if(cfg->command & CMD_BUS_MASTER) printf("BUS_MASTER ");
  if(cfg->command & CMD_SPEC_CYCLE) printf("SPEC_CYCLE ");
  if(cfg->command & CMD_MEM_WR_INV) printf("MEM_WR_INV ");
  if(cfg->command & CMD_VGA_PALETTE) printf("VGA_PALETTE ");
  if(cfg->command & CMD_PAR_ERR_RSP) printf("PAR_ERR_RSP ");
  if(cfg->command & CMD_WAIT_CYCLE) printf("WAIT_CYCLE ");
  if(cfg->command & CMD_SERR_EN) printf("SERR_EN ");
  if(cfg->command & CMD_FAST_BBE) printf("FAST_BBE ");
  printf("\n");

  /* Print the contents of the rev_id field. */
  printf("%srev_id = %d\n",prefix,cfg->rev_id);

  /* Decode and print the contents of the class_code field. */
  printf("%sclass_code = %s:%s",prefix,toStr_base(cfg->class_code.base),
      toStr_sub(cfg->class_code.base,cfg->class_code.sub_class));
  printf("\n");
}

/****************************************************************************
 * toStr_base
 *
 * Converts the BASE_xxx to a string. */
char *
toStr_base(
  int base
)
{
#define BASE_BC_STR "BC"
#define BASE_MASS_STR "MASS"
#define BASE_NETWORK_STR "NETWORK"
#define BASE_DISPLAY_STR "DISPLAY"
#define BASE_MULTMEDIA_STR "MULTMEDIA"
#define BASE_MEM_STR "MEM"
#define BASE_BRIDGE_STR "BRIDGE"
#define BASE_COMM_STR "COMM"
#define BASE_SYS_PERIPH_STR "PERIPH"
#define BASE_INPUT_STR "INPUT"
#define BASE_DOCK_STR "DOCK"
#define BASE_PROCESSOR_STR "PROCESSOR"
#define BASE_SERIAL_BUS_STR "SERIAL_BUS"
#define BASE_UNKNOWN_STR "UNKNOWN"

  char* retVal;

  switch(base) {
    case BASE_BC: retVal = BASE_BC_STR; break;
    case BASE_MASS: retVal = BASE_MASS_STR; break;
    case BASE_NETWORK: retVal = BASE_NETWORK_STR; break;
    case BASE_DISPLAY: retVal = BASE_DISPLAY_STR; break;
    case BASE_MULTMEDIA: retVal = BASE_MULTMEDIA_STR; break;
    case BASE_MEM: retVal = BASE_MEM_STR; break;
    case BASE_BRIDGE: retVal = BASE_BRIDGE_STR; break;
    case BASE_COMM: retVal = BASE_COMM_STR; break;
    case BASE_SYS_PERIPH: retVal = BASE_SYS_PERIPH_STR; break;
    case BASE_INPUT: retVal = BASE_INPUT_STR; break;
    case BASE_DOCK: retVal = BASE_DOCK_STR; break;
    case BASE_PROCESSOR: retVal = BASE_PROCESSOR_STR; break;
    case BASE_SERIAL_BUS: retVal = BASE_SERIAL_BUS_STR; break;
    case BASE_UNKNOWN: retVal = BASE_UNKNOWN_STR; break;
    default: retVal = ""; break;
  }

  return(retVal);
}


/****************************************************************************
 * toStr_sub
 *
 * Converts the SUB_xxx to a string. */
char *
toStr_sub(
  int base,
  int sub
)
{
#define SUB_PREDEF_STR "PREDEF"
#define SUB_PRE_VGA_STR "PRE_VGA"
#define SUB_SCSI_STR "SCSI"
#define SUB_IDE_STR "IDE"
#define SUB_FDDI_STR "FDDI"
#define SUB_IPI_STR "IPI"
#define SUB_MASS_OTHER_STR "MASS"
#define SUB_ETHERNET_STR "ETHERNET"
#define SUB_TOKEN_RING_STR "TOKEN_RING"
#define SUB_FDDI_STR "FDDI"
#define SUB_NETWORK_OTHER_STR "NETWORK_OTHER"
#define SUB_VGA_STR "VGA"
#define SUB_XGA_STR "XGA"
#define SUB_DISPLAY_OTHER_STR "DISPLAY_OTHER"
#define SUB_VIDEO_STR "VIDEO"
#define SUB_AUDIO_STR "AUDIO"
#define SUB_MULTMEDIA_OTHER_STR "MULTMEDIA_OTHER"
#define SUB_RAM_STR "RAM"
#define SUB_FLASH_STR "FLASH"
#define SUB_MEM_OTHER_STR "MEM"
#define SUB_HOST_STR "HOST"
#define SUB_ISA_STR "ISA"
#define SUB_EISA_STR "EISA"
#define SUB_MC_STR "MC"
#define SUB_PCI_STR "PCI"
#define SUB_PCMCIA_STR "PCMCIA"
#define SUB_NUBUS_STR "NUBUS"
#define SUB_CARDBUS_STR "CARDBUS"
#define SUB_BRIDGE_OTHER_STR "BRIDGE_OTHER"
#define SUB_PC_COMM_STR "PC_COMM"
#define SUB_PARALLEL_STR "PARALLEL"
#define SUB_COMM_OTHER_STR "COMM_OTHER"
#define SUB_8259_PIC_STR "8259_PIC"
#define SUB_SLV_DMA_STR "SLV_DMA"
#define SUB_TIMER_STR "TIMER"
#define SUB_RTC_TIMER_STR "RTC_TIMER"
#define SUB_KEYBOARD_STR "KEYBOARD"
#define SUB_PEN_STR "PEN"
#define SUB_MOUSE_STR "MOUSE"
#define SUB_INPUT_OTHER_STR "INPUT_OTHER"
#define SUB_DOCKING_STR "DOCKING"
#define SUB_DOCK_OTHER_STR "DOCK_OTHER"
#define SUB_386_STR "386"
#define SUB_486_STR "486"
#define SUB_PENTIUM_STR "PENTIUM"
#define SUB_ALPHA_STR "ALPHA"
#define SUB_COPROC_STR "COPROC"
#define SUB_P1394_STR "P1394"
#define SUB_ACCESS_STR "ACCESS"
#define SUB_SSA_STR "SSA"

  char* retVal;

  switch(base) {
    case BASE_BC:
      switch(sub) {
        case SUB_PREDEF: retVal = SUB_PREDEF_STR; break;
        case SUB_PRE_VGA: retVal = SUB_PRE_VGA_STR; break;
      }
      break;
    case BASE_MASS:
      switch(sub) {
        case SUB_SCSI: retVal = SUB_SCSI_STR; break;
        case SUB_IDE: retVal = SUB_IDE_STR; break;
        case SUB_FDDI: retVal = SUB_FDDI_STR; break;
        case SUB_IPI: retVal = SUB_IPI_STR; break;
        case SUB_MASS_OTHER: retVal = SUB_MASS_OTHER_STR; break;
      }
      break;
    case BASE_NETWORK:
      switch(sub) {
        case SUB_ETHERNET: retVal = SUB_ETHERNET_STR; break;
        case SUB_TOKEN_RING: retVal = SUB_TOKEN_RING_STR; break;
        case SUB_FDDI: retVal = SUB_FDDI_STR; break;
        case SUB_NETWORK_OTHER: retVal = SUB_NETWORK_OTHER_STR; break;
      }
      break;
    case BASE_DISPLAY:
      switch(sub) {
        case SUB_VGA: retVal = SUB_VGA_STR; break;
        case SUB_XGA: retVal = SUB_XGA_STR; break;
        case SUB_DISPLAY_OTHER: retVal = SUB_DISPLAY_OTHER_STR; break;
      }
      break;
    case BASE_MULTMEDIA:
      switch(sub) {
        case SUB_VIDEO: retVal = SUB_VIDEO_STR; break;
        case SUB_AUDIO: retVal = SUB_AUDIO_STR; break;
        case SUB_MULTMEDIA_OTHER: retVal = SUB_MULTMEDIA_OTHER_STR; break;
      }
      break;
    case BASE_MEM:
      switch(sub) {
        case SUB_RAM: retVal = SUB_RAM_STR; break;
        case SUB_FLASH: retVal = SUB_FLASH_STR; break;
        case SUB_MEM_OTHER: retVal = SUB_MEM_OTHER_STR; break;
      }
      break;
    case BASE_BRIDGE:
      switch(sub) {
        case SUB_HOST: retVal = SUB_HOST_STR; break;
        case SUB_ISA: retVal = SUB_ISA_STR; break;
        case SUB_EISA: retVal = SUB_EISA_STR; break;
        case SUB_MC: retVal = SUB_MC_STR; break;
        case SUB_PCI: retVal = SUB_PCI_STR; break;
        case SUB_PCMCIA: retVal = SUB_PCMCIA_STR; break;
        case SUB_NUBUS: retVal = SUB_NUBUS_STR; break;
        case SUB_CARDBUS: retVal = SUB_CARDBUS_STR; break;
        case SUB_BRIDGE_OTHER: retVal = SUB_BRIDGE_OTHER_STR; break;
      }
      break;
    case BASE_COMM:
      switch(sub) {
        case SUB_PC_COMM: retVal = SUB_PC_COMM_STR; break;
        case SUB_PARALLEL: retVal = SUB_PARALLEL_STR; break;
        case SUB_COMM_OTHER: retVal = SUB_COMM_OTHER_STR; break;
      }
      break;
    case BASE_SYS_PERIPH:
      switch(sub) {
        case SUB_8259_PIC: retVal = SUB_8259_PIC_STR; break;
        case SUB_SLV_DMA: retVal = SUB_SLV_DMA_STR; break;
        case SUB_TIMER: retVal = SUB_TIMER_STR; break;
        case SUB_RTC_TIMER: retVal = SUB_RTC_TIMER_STR; break;
      }
      break;
    case BASE_INPUT:
      switch(sub) {
        case SUB_KEYBOARD: retVal = SUB_KEYBOARD_STR; break;
        case SUB_PEN: retVal = SUB_PEN_STR; break;
        case SUB_MOUSE: retVal = SUB_MOUSE_STR; break;
        case SUB_INPUT_OTHER: retVal = SUB_INPUT_OTHER_STR; break;
      }
      break;
    case BASE_DOCK:
      switch(sub) {
        case SUB_DOCKING: retVal = SUB_DOCKING_STR; break;
        case SUB_DOCK_OTHER: retVal = SUB_DOCK_OTHER_STR; break;
      }
      break;
    case BASE_PROCESSOR:
      switch(sub) {
        case SUB_386: retVal = SUB_386_STR; break;
        case SUB_486: retVal = SUB_486_STR; break;
        case SUB_PENTIUM: retVal = SUB_PENTIUM_STR; break;
        case SUB_ALPHA: retVal = SUB_ALPHA_STR; break;
        case SUB_COPROC: retVal = SUB_COPROC_STR; break;
      }
      break;
    case BASE_SERIAL_BUS:
      switch(sub) {
       case SUB_P1394: retVal = SUB_P1394_STR; break;
        case SUB_ACCESS: retVal = SUB_ACCESS_STR; break;
        case SUB_SSA: retVal = SUB_SSA_STR; break;
      }
      break;
    case BASE_UNKNOWN:
      retVal = ""; break;
    default:
      retVal = ""; break;
  }

  return(retVal);
}

/****************************************************************************
 * toStr_cfg_attr
 *
 * Converts the CFG_ATTR_xxx constants to a string. */
char *
toStr_cfg_attr(
  int cfg_attr
)
{
#define CFG_ATTR_SUCCESS_STR "Success"
#define CFG_ATTR_EEXISTS_STR "Does not exist"
#define CFG_ATTR_EOP_STR "Option not supported"
#define CFG_ATTR_ESUBSYS_STR "Subsystem failed"
#define CFG_ATTR_ESMALL_STR "Too small"
#define CFG_ATTR_ELARGE_STR "Too large"
#define CFG_ATTR_ETYPE_STR "Invalid type"
#define CFG_ATTR_EINDEX_STR "Invalid index"
#define CFG_ATTR_EMEM_STR "Memory allocation error"
#define CFG_ATTR_ENOTNUMBER_STR "Not a number"

  /* The return value. */
  char* retVal;

  switch(cfg_attr) {
    case CFG_ATTR_SUCCESS: retVal = CFG_ATTR_SUCCESS_STR; break;
    case CFG_ATTR_EEXISTS: retVal = CFG_ATTR_EEXISTS_STR; break;
    case CFG_ATTR_EOP: retVal = CFG_ATTR_EOP_STR; break;
    case CFG_ATTR_ESUBSYS: retVal = CFG_ATTR_ESUBSYS_STR; break;
    case CFG_ATTR_ESMALL: retVal = CFG_ATTR_ESMALL_STR; break;
    case CFG_ATTR_ELARGE: retVal = CFG_ATTR_ELARGE_STR; break;
    case CFG_ATTR_ETYPE: retVal = CFG_ATTR_ETYPE_STR; break;
    case CFG_ATTR_EINDEX: retVal = CFG_ATTR_EINDEX_STR; break;
    case CFG_ATTR_EMEM: retVal = CFG_ATTR_EMEM_STR; break;
    case CFG_ATTR_ENOTNUMBER: retVal = CFG_ATTR_ENOTNUMBER_STR; break;
    default: retVal = ""; break;
  }
  return(retVal);
}


/* ikdrw_driver.h */

/*
 * Author: David G Loone
 * Organization: CSIRO Australia Telescope
 */

#ifndef IKDRW_DRIVER_H
#define IKDRW_DRIVER_H

#endif /* IKDRW_DRIVER_H */




ikdrw:
  # Ikon 10116 DR-11 emulator.
  Module_Config_Name = ikdrw
  Device_Major_Req = Same
  Device_Char_Major = ANY
  PCI_Option =  PCI_SE_Rev - 0x210, Vendor_Id - 0x11D5, Device_Id - 0x0116,
Rev 
- 0, Base - 0, Sub - 0, Pif - 0, Sub_Vid - 0, Sub_Did - 0, Vid_Mo_Flag - 1, 
Did_Mo_Flag - 1, Rev_Mo_Flag - 0, Base_Mo_Flag - 0, Sub_Mo_Flag - 0, 
Pif_Mo_Flag - 0, Sub_Vid_Mo_Flag - 0, Sub_Did_Mo_Flag - 0, Driver_Name -
ikdrw, 
Type - C, Adpt_Config - N


we have tried to include debugging information by 

# sysconfig -r pci PCI_Developer_Debug=1
I've done this, but I don't get any diagnostics, either in the 
/var/adm/messages file, or from the uerf program, or on the console.

The debugging info which the driver prints also does not emerge. If I force 
the probe interface to fail, the debugging info comes out ok and everything 
seems to be as expected, but the driver hasn't loaded, because the probe 
failed. Once the probe succeeds, the configure_driver call never returns, and 
none of the debugging info (either from the driver or from the PCI subsystem) 
gets saved (the CPU hangs and needs to be reset).






regards
Roberto Romani
Unix Support
Sydney TSC
Australia






























































[Posted by WWW Notes gateway]
8717.2questions and suggestionsADISSW::TENHAVEThu Feb 06 1997 08:2537
    
    Questions...
    
    1.) Do you know if your "attach()" routine is getting called?
    
    2.) When you load this driver, have you included a "-v" switch 
        with the "sysconfig -c ***-v** ikdrw" call?
    
        This may shed more light on the problem.  If you do
        this, post ALL the output to the console window here
        or send it to me.
    
    3.) Have you tried not registering the devices just before the
        configure_driver call?  You have no device support
        functions anyways.
    
    -------------
    
    As you see, PCI debug will not help much here.  
    
    ===> Change BUS_NAME define to "*"...and let me know what happens.
    
    ------------
    
    If things still not working, tar and uuencode all the driver files
    including:
    
    	files file, sysconfigtab file, *.h file, *.c driver file
    
    and then send them to me.  I can probably throw a few cycles at this
    early next week.  I do not work in UNIX Engineering, but my group
    does do custom device driver (UNIX, OVMS, WinNT) work, both development
    and consulting.
    
    				Tim
    
    
8717.3Does the old driver work on 4.0?ADISSW::TENHAVEThu Feb 06 1997 10:079
     
    Another point...
    
    The 3.2c driver should work fine under DUNIX 4.0x.
    
    Is this the case?
    
    			Tim
    
8717.4problem solvedNETRIX::&quot;[email protected]&quot;Roberto RomaniMon Feb 10 1997 17:4441
hello all,

	Here was the solution and a few more questions

I think we've solved the problem. There were two problems:

1.
I didn't need the call to create_device_struct, as you pointed out. That 
was causing the kernel to hang at laod.

2.
The code around the call call to devsw_add was configured incorrectly, 
so that the majorNum variable was being loaded with zero. This variable 
(being part of the sysconfig parameters) is important, among other 
things, creating a /dev/ikdrw device with major number 0. This must have 
been stuffing up the boot process somehow.


When the Device_Char_Files and Device_Char_Minor entries of the 
sysconfigtab were removed, no /dev/ikdrw file was created, and 
everything was ok.

I've fixed the code around devsw_add, and everything seems ok, in that 
it now makes a sensible major device number.

As a general comment, lots of things aren't terribly well explained in 
the online documentation. Stuff about major and minor numbers is a bit 
opaque, probably unless you are a Unix guru anyway. But then, it devots 
lots of space to the simple problem of how to allocate space for the 
device's unit data. In general, the doco relies too heavily on simply 
documenting the example, rather than explaining what's happening.



regards
Roberto Romani
Unix Support
Sydney TSC
Australia

[Posted by WWW Notes gateway]
8717.5Device ZeroNETRIX::&quot;[email protected]&quot;Tue Feb 11 1997 13:0116
Hi Roberto,

   If you allow your driver to claim the device table zero
entry I am not supprised that your system would not boot.
You basically clobbered the ws keyboard and mouse device
special files on your boot disk( When you allowed your 
device driver to claim devsw entry zero these other device
special files ws and keyboard... were removed from the
boot disk...) These devices are opened many times in the 
boot path and the system as you figured out does not
work without them...

Thanks,
Karl

[Posted by WWW Notes gateway]