Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 6 May 2006 19:21:35 +0800
From:      "Wallace William" <avalonwallace@gmail.com>
To:        freebsd-arch@freebsd.org, freebsd-hackers@freebsd.org
Subject:   fakedevice hotplug Demo with sourcecode
Message-ID:  <3a60de0b0605060421l708d8c06y29006c2c3cd75519@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
hello ,everyone .
          i have write a demo module to demostrate the hotplug of a pci
device under freeBSD 5.3 . when kldload the module ,the fakedevice will be
"plug "into the pci architechure,when kldunload ,the device will be removed=
.
pciconf -l ,and devinfo -v will be the tool to show this change : a new
device called wallace is added ,this device comes from the info in LINE97 o=
f
the fakeBSC.c:
 *dinfo=3D* ((struct pci_devinfo *)  device_get_ivars(devlist[6])  );
maybe u need to change the '6' according to ur need .

there r 4 file in this package :pci_hotplug_core.c fakeBSD.c pci_hotplug.h
and the Makefile .

way to RUN:
1 unzip the package
2 make
3 kldload ./fakeBSD.ko
4 pciconf -l ,and devinfo -v to see the change
5 kldunload fakeBSD.ko
welcome for ur feedback,next i will do my best to write the  driver for rea=
l
pci device hotplug, as what cardbus has done

////////////////pci_hotplug_core.c//////////////////////////////////

/////////////from PCIexample////////////////
#include <sys/param.h>  /* defines used in kernel.h */
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/kernel.h> /* types used in module initialization */
#include <sys/conf.h>   /* cdevsw struct */
#include <sys/uio.h>    /* uio struct */
#include <sys/malloc.h>
#include <sys/bus.h>  /* structs, prototypes for pci bus stuff */

#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>

#include <dev/pci/pcivar.h> /* For get_pci macros! */
#include <dev/pci/pcireg.h>
  ////////////////////////////////////
#include<dev/drm/drm_linux_list.h>
#include "pci_hotplug.h"

//WB//
#define MY_NAME "pci_hotplug"
//simplified//WB//
#define dbg(fmt, arg...) do { if (debug) printf( fmt , ## arg); } while (0)
#define err(format, arg...) printf( format, MY_NAME , ## arg)
#define info(format, arg...) printf(format, MY_NAME , ## arg)
#define warn(format, arg...) printf(format ,  MY_NAME, ## arg)


/* local variables */
static int debug;

//////////////////////////////////////////////////////////////////

static LIST_HEAD(pci_hotplug_slot_list);

/* these strings match up with the values in pci_bus_speed */
static char *pci_bus_speed_strings[] =3D {
 "33 MHz PCI",  /* 0x00 */
 "66 MHz PCI",  /* 0x01 */
 "66 MHz PCIX",   /* 0x02 */
 "100 MHz PCIX",  /* 0x03 */
 "133 MHz PCIX",  /* 0x04 */
 NULL,   /* 0x05 */
 NULL,   /* 0x06 */
 NULL,   /* 0x07 */
 NULL,   /* 0x08 */
 "66 MHz PCIX 266", /* 0x09 */
 "100 MHz PCIX 266", /* 0x0a */
 "133 MHz PCIX 266", /* 0x0b */
 NULL,   /* 0x0c */
 NULL,   /* 0x0d */
 NULL,   /* 0x0e */
 NULL,   /* 0x0f */
 NULL,   /* 0x10 */
 "66 MHz PCIX 533", /* 0x11 */
 "100 MHz PCIX 533", /* 0x12 */
 "133 MHz PCIX 533", /* 0x13 */
 "25 GBps PCI-E", /* 0x14 */
};



 ///////////////////fakeBSD.c
/////////////////////////////////////////////////

////////change of the header/////////////
/////////////from PCIexample////////////////
#include <sys/param.h>  /* defines used in kernel.h */
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/kernel.h> /* types used in module initialization */
#include <sys/conf.h>   /* cdevsw struct */
#include <sys/uio.h>    /* uio struct */
#include <sys/malloc.h>
#include <sys/bus.h>  /* structs, prototypes for pci bus stuff */
//for TAILQ_FOREACH
//#include <sys/queue.h>
//
#include <sys/bus.h>  //1129
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>

#include <sys/pciio.h>//1129 sizeof
#include <dev/pci/pcivar.h> /* For get_pci macros! */
#include <dev/pci/pcireg.h>
#include <dev/pci/pci_private.h>//1129
////////////////////////////////////
#include<dev/drm/drm_linux_list.h>  //for list_head
//#include "pci_hotplug.h"  put the unrealated functions out

//#include "../pci.h"

//this is created on compiling.so leave it to makefile
//#include "pcib_if.h" //#include "pci_if.h"

/*
//COMMENT
//devinfo struct for devinfo
//addtodevice_list for pciconf
COPY the NIC device content to the wallace0 fake device
*/
#define MY_NAME "fakephp"

#define dbg(fmt, arg...) do { if (debug) printf( fmt , ## arg); } while (0)
#define err(format, arg...) printf( format, MY_NAME , ## arg)
#define info(format, arg...) printf(format, MY_NAME , ## arg)



#define DRIVER_AUTHOR "Wallace <avalonwallace@gmail.com>"
#define DRIVER_DESC "Fake PCI Hot Plug Controller Driver"


 /*
  * This function is called by the kld[un]load(2) system calls to
  * determine what actions to take when a module is loaded or unloaded.
  */
  /* vars */

 static struct pci_devinfo *dinfo;
 static device_t bus; //refer to pci bus


 size_t dinfo_size;
static int
fake_loader(struct module *m, int what, void *arg)
{
 int erro=3D0;
        device_t *devlist;
 int count=3D0; int numdevs;
 devclass_t class1;
        char * Dtarget=3D"pci",Dname=3D"wallace";
        struct devlist *devlist_head;
 devlist_head =3D &pci_devq;
    switch (what) {
    case MOD_LOAD:                /* kldload */
        printf("Module loaded.\n,with bootverbose=3D%i",bootverbose);
        //find pci devclass and device
        if ((class1 =3D devclass_find(Dtarget)) =3D=3D NULL) {
  printf("unable to get the class");
  return ENXIO;
  }
  printf("\n//////////////my name is
%s////////////\n",devclass_get_name(class1));
  // show the nameof the device,or store them into another TAILQ
  printf("maxunit under class pci
is%i\n",devclass_get_maxunit(class1)); //WB does unit =3D=3D count
  if((bus =3D devclass_get_device(class1,count))!=3DNULL)//WB why not use t=
he
loop over count?
  {
   printf("my device name is %s,my unit is %i, DESC: %s,with number:%i\n",
   device_get_name(bus),device_get_unit(bus),device_get_desc(bus),pcib_get_=
bus(bus));
  }
    //else? return (NULL)
        dinfo_size=3Dsizeof(struct pci_devinfo);
        dinfo=3DNULL;   //initialized
        dinfo=3D malloc(dinfo_size, M_DEVBUF, M_WAITOK | M_ZERO);
        if (dinfo =3D=3D NULL)
   return (NULL);
 if (device_get_children(bus, &devlist, &numdevs)=3D=3D0)
  //get ivar from de0,thus 6 of devlist ,hardcoded ,this need specific
platform characteristic , waiting for modification
      *dinfo=3D* ((struct pci_devinfo *)  device_get_ivars(devlist[6])  );

        if ((dinfo->cfg.dev =3D device_add_child(bus, "wallace", -1)) =3D=
=3D NULL)
{//change the name
   device_printf(device_get_parent(bus), "couldn't attach pci bus\n");

     }
     device_sysctl_init(dinfo->cfg.dev);
     strncpy ((dinfo->conf.pd_name),device_get_name(dinfo->cfg.dev
),8);//sizeof(device_get_name(dinfo->cfg.dev)));
     STAILQ_INSERT_TAIL(devlist_head, dinfo, pci_links);
     pci_numdevs++;
 pci_generation++;
     device_set_ivars(dinfo->cfg.dev, dinfo);


        //show result
        if (device_get_children(bus, &devlist, &numdevs)=3D=3D0)
  while (numdevs--){
   printf("%i",numdevs);
   device_print_prettyname(devlist[numdevs]);
   if (device_get_devclass(devlist[numdevs])!=3DNULL )

printf("devclass=3D%s\n",devclass_get_name(device_get_devclass(devlist[numd=
evs])
));

  }

        break;
    case MOD_UNLOAD:
        printf("Module unloaded.\n");

    //still dinfo point to the fake device i point to . it is static !!!:)
        if (dinfo->cfg.dev !=3D NULL) {
         printf("dinfo->cfg.dev exist,deleting it.\n");
   device_delete_child(device_get_parent(dinfo->cfg.dev), dinfo->cfg.dev);
   printf("dinfo->cfg.dev exist,deleted .\n");
  }else printf("dinfo->cfg.dev=3DNULL\n");

  if (device_get_children(bus, &devlist, &numdevs)=3D=3D0)
  //demostrating the result
  while (numdevs--){
   printf("%i",numdevs);
   device_print_prettyname(devlist[numdevs]);
   if (device_get_devclass(devlist[numdevs])!=3DNULL )

printf("devclass=3D%s\n",devclass_get_name(device_get_devclass(devlist[numd=
evs])
));

  }

  printf("freeing(dinfo,M_DEVBUF)\n");
  //1
  device_sysctl_fini(dinfo->cfg.dev);//WB finish sysctl structure
  devlist_head =3D &pci_devq;
  STAILQ_REMOVE(devlist_head, dinfo, pci_devinfo, pci_links);
  free(dinfo, M_DEVBUF);
  /* increment the generation count */
  //WB inrease or decreas?
  pci_generation++;
  /* we're losing one device */
  pci_numdevs--;

  dinfo=3DNULL;
  //2
  printf("freed  dinfo,\n");  //WB ,n->,/n
  //erro=3D0;
        break;
    default:
        printf("Module default.\n");
        erro =3D EINVAL;
        break;
    }
    return(erro);
}



//DEV_MODULE(echo,echo_loader,NULL);
//#define DEV_MODULE(name, evh, arg)
static moduledata_t fake_mod =3D {
    "fakeBSD",
     fake_loader,
     NULL
};
DECLARE_MODULE(fake, fake_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);


//////////////////////pci_hotplug.h ///////////////////////

#include <sys/types.h> //WB//
#ifndef _PCI_HOTPLUG_H
#define _PCI_HOTPLUG_H


/* These values come from the PCI Hotplug Spec */
enum pci_bus_speed {
 PCI_SPEED_33MHz   =3D 0x00,
 PCI_SPEED_66MHz   =3D 0x01,
 PCI_SPEED_66MHz_PCIX  =3D 0x02,
 PCI_SPEED_100MHz_PCIX  =3D 0x03,
 PCI_SPEED_133MHz_PCIX  =3D 0x04,
 PCI_SPEED_66MHz_PCIX_ECC =3D 0x05,
 PCI_SPEED_100MHz_PCIX_ECC =3D 0x06,
 PCI_SPEED_133MHz_PCIX_ECC =3D 0x07,
 PCI_SPEED_66MHz_PCIX_266 =3D 0x09,
 PCI_SPEED_100MHz_PCIX_266 =3D 0x0a,
 PCI_SPEED_133MHz_PCIX_266 =3D 0x0b,
 PCI_SPEED_66MHz_PCIX_533 =3D 0x11,
 PCI_SPEED_100MHz_PCIX_533 =3D 0x12,
 PCI_SPEED_133MHz_PCIX_533 =3D 0x13,
 PCI_SPEED_UNKNOWN  =3D 0xff,
};

/* These values come from the PCI Express Spec */
enum pcie_link_width {
 PCIE_LNK_WIDTH_RESRV =3D 0x00,
 PCIE_LNK_X1  =3D 0x01,
 PCIE_LNK_X2  =3D 0x02,
 PCIE_LNK_X4  =3D 0x04,
 PCIE_LNK_X8  =3D 0x08,
 PCIE_LNK_X12  =3D 0x0C,
 PCIE_LNK_X16  =3D 0x10,
 PCIE_LNK_X32  =3D 0x20,
 PCIE_LNK_WIDTH_UNKNOWN  =3D 0xFF,
};

enum pcie_link_speed {
 PCIE_2PT5GB  =3D 0x14,
 PCIE_LNK_SPEED_UNKNOWN =3D 0xFF,
};

struct hotplug_slot;
/*//WB//
struct hotplug_slot_attribute {
 struct attribute attr;
 ssize_t (*show)(struct hotplug_slot *, char *);
 ssize_t (*store)(struct hotplug_slot *, const char *, size_t);
};
//WB//
#define to_hotplug_attr(n) container_of(n, struct hotplug_slot_attribute,
attr);


 * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use
 * @owner: The module owner of this structure
 * @enable_slot: Called when the user wants to enable a specific pci slot
 * @disable_slot: Called when the user wants to disable a specific pci slot
 * @set_attention_status: Called to set the specific slot's attention LED t=
o
 * the specified value
 * @hardware_test: Called to run a specified hardware test on the specified
 * slot.
 * @get_power_status: Called to get the current power status of a slot.
 *  If this field is NULL, the value passed in the struct hotplug_slot_info
 *  will be used when this value is requested by a user.
 * @get_attention_status: Called to get the current attention status of a
slot.
 * If this field is NULL, the value passed in the struct hotplug_slot_info
 * will be used when this value is requested by a user.
 * @get_latch_status: Called to get the current latch status of a slot.
 * If this field is NULL, the value passed in the struct hotplug_slot_info
 * will be used when this value is requested by a user.
 * @get_adapter_status: Called to get see if an adapter is present in the
slot or not.
 * If this field is NULL, the value passed in the struct hotplug_slot_info
 * will be used when this value is requested by a user.
 * @get_address: Called to get pci address of a slot.
 * If this field is NULL, the value passed in the struct hotplug_slot_info
 * will be used when this value is requested by a user.
 * @get_max_bus_speed: Called to get the max bus speed for a slot.
 * If this field is NULL, the value passed in the struct hotplug_slot_info
 * will be used when this value is requested by a user.
 * @get_cur_bus_speed: Called to get the current bus speed for a slot.
 * If this field is NULL, the value passed in the struct hotplug_slot_info
 * will be used when this value is requested by a user.
 *
 * The table of function pointers that is passed to the hotplug pci core by
a
 * hotplug pci driver.  These functions are called by the hotplug pci core
when
 * the user wants to do something to a specific slot (query it for
information,
 * set an LED, enable / disable power, etc.)
 */
 //the freebsd WAY of function call back
 typedef int enable_slot_t  (struct hotplug_slot *slot);
 typedef int disable_slot_t  (struct hotplug_slot *slot);
typedef int set_attention_status_t (struct hotplug_slot *slot, u_int8_t
value);
typedef int hardware_test_t  (struct hotplug_slot *slot, u_int32_t value);
typedef int get_power_status_t  (struct hotplug_slot *slot, u_int8_t
*value);
typedef int get_attention_status_t (struct hotplug_slot *slot, u_int8_t
*value);
typedef int get_latch_status_t  (struct hotplug_slot *slot, u_int8_t
*value);
typedef int get_adapter_status_t (struct hotplug_slot *slot, u_int8_t
*value);
typedef int get_address_t  (struct hotplug_slot *slot, u_int32_t *value);
typedef int get_max_bus_speed_t (struct hotplug_slot *slot, enum
pci_bus_speed *value);
typedef int get_cur_bus_speed_t (struct hotplug_slot *slot, enum
pci_bus_speed *value);


struct hotplug_slot_ops {
 //struct module *owner;
 enable_slot_t  * enable_slot;
 disable_slot_t  *disable_slot;
 set_attention_status_t *set_attention_status;
 hardware_test_t *hardware_test;
 get_power_status_t *get_power_status;
 get_attention_status_t *get_attention_status;
 get_latch_status_t  *get_latch_status;
 get_adapter_status_t *get_adapter_status;
 get_address_t  *get_address;
 get_max_bus_speed_t *get_max_bus_speed;
 get_cur_bus_speed_t *get_cur_bus_speed;
};

/**
 * struct hotplug_slot_info - used to notify the hotplug pci core of the
state of the slot
 * @power: if power is enabled or not (1/0)
 * @attention_status: if the attention light is enabled or not (1/0)
 * @latch_status: if the latch (if any) is open or closed (1/0)
 * @adapter_present: if there is a pci board present in the slot or not
(1/0)
 * @address: (domain << 16 | bus << 8 | dev)
 *
 * Used to notify the hotplug pci core of the status of a specific slot.
 */

struct hotplug_slot_info {
 u_int8_t power_status;
 u_int8_t attention_status;
 u_int8_t latch_status;
 u_int8_t adapter_status;
 u_int32_t address;
 enum pci_bus_speed max_bus_speed;
 enum pci_bus_speed cur_bus_speed;
};

/**
 * struct hotplug_slot - used to register a physical slot with the hotplug
pci core
 * @name: the name of the slot being registered.  This string must
 * be unique amoung slots registered on this system.
 * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot
 * @info: pointer to the &struct hotplug_slot_info for the inital values fo=
r
 * this slot.
 * @private: used by the hotplug pci controller driver to store whatever it
 * needs.
 */
typedef void release_t (struct hotplug_slot *slot);
struct  hotplug_slot {
 char    *name;
 int     unit;
 struct hotplug_slot_ops  *ops;
 struct hotplug_slot_info *info;
 release_t * release;
 void   *private;
 /* Variables below this are for use only by the hotplug pci core.
 for example :pci_hotplug_slot_list
 */
 struct list_head  slot_list;
 //WB//struct kobject   kobj;
};
//WB//#define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj)

#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
 struct list_head name =3D LIST_HEAD_INIT(name)

 /* list_entry - get the struct for this entry
 * @ptr:     the &struct list_head pointer.
 * @type:    the type of the struct this is embedded in.
 * @member:    the name of the list_struct within the struct.
 entry2 inorder to differ from the vm one
 */
#define list_entry2(ptr, type, member) \
 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

 /**
  * list_for_each_safe - iterate over a list safe against removal of list
entry
  * @pos: the &struct list_head to use as a loop counter.
  * @n:  another &struct list_head to use as temporary storage
  * @head: the head for your list.
  */
#define list_for_each_safe2(pos, n, head) \
  for (pos =3D (head)->next, n =3D pos->next; pos !=3D (head); \
   pos =3D n, n =3D pos->next)



extern int pci_hp_register  (struct hotplug_slot *slot);
extern int pci_hp_deregister  (struct hotplug_slot *slot);
extern int pci_hp_change_slot_info (struct hotplug_slot *slot,
      struct hotplug_slot_info *info);
//WB//extern struct subsystem pci_hotplug_slots_subsys;

#endif


///////////////////Makefile/////////////////////////////


.PATH: /usr/src/devdrv/

KMOD=3D fakeBSD
SRCS=3D fakeBSD.c pci_hotplug_core.c
SRCS+=3D  device_if.h bus_if.h pci_if.h
.include <bsd.kmod.mk>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3a60de0b0605060421l708d8c06y29006c2c3cd75519>