From owner-freebsd-arch@FreeBSD.ORG Sat May 6 11:21:37 2006 Return-Path: X-Original-To: freebsd-arch@freebsd.org Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 4A7DB16A403 for ; Sat, 6 May 2006 11:21:37 +0000 (UTC) (envelope-from avalonwallace@gmail.com) Received: from py-out-1112.google.com (py-out-1112.google.com [64.233.166.176]) by mx1.FreeBSD.org (Postfix) with ESMTP id 17ED643D45 for ; Sat, 6 May 2006 11:21:36 +0000 (GMT) (envelope-from avalonwallace@gmail.com) Received: by py-out-1112.google.com with SMTP id e30so993926pya for ; Sat, 06 May 2006 04:21:35 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:message-id:date:from:to:subject:mime-version:content-type; b=j7KbTruVa18FYHkMfCFfb8gr2PbvJ5IyReRQc72AACLdSkTIhOucc6NUv9T7jm8mkn3i2kSeNmbN2kMkomBYedfJXu8Pi2He5GusilpmtnSviQ529WEWn+EVwtiiFq/X6Q2WnzXeefL27kFsGy7MxFG4tv8xY9rN4ec9lndDTAI= Received: by 10.35.36.13 with SMTP id o13mr92115pyj; Sat, 06 May 2006 04:21:35 -0700 (PDT) Received: by 10.35.105.6 with HTTP; Sat, 6 May 2006 04:21:35 -0700 (PDT) Message-ID: <3a60de0b0605060421l708d8c06y29006c2c3cd75519@mail.gmail.com> Date: Sat, 6 May 2006 19:21:35 +0800 From: "Wallace William" To: freebsd-arch@freebsd.org, freebsd-hackers@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Content-Disposition: inline X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Cc: Subject: fakedevice hotplug Demo with sourcecode X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 06 May 2006 11:21:37 -0000 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 /* defines used in kernel.h */ #include #include #include #include /* types used in module initialization */ #include /* cdevsw struct */ #include /* uio struct */ #include #include /* structs, prototypes for pci bus stuff */ #include #include #include #include /* For get_pci macros! */ #include //////////////////////////////////// #include #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 /* defines used in kernel.h */ #include #include #include #include /* types used in module initialization */ #include /* cdevsw struct */ #include /* uio struct */ #include #include /* structs, prototypes for pci bus stuff */ //for TAILQ_FOREACH //#include // #include //1129 #include #include #include #include //1129 sizeof #include /* For get_pci macros! */ #include #include //1129 //////////////////////////////////// #include //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 " #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 //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