Garrett, I'm trying to port xenbus drivers onto Solaris HVM and hence I need to get to the register space of the platform PCI device which xen emulates for each VM. So any help in this regard would be very helpful. I'm attaching the sample code which I picked up from http://dsc.sun.com/solaris/developer/support/driver/faqs.html#QA3.17 and then modified.
In the attach routine I tried doing the ddi_regs_map_setup on BAR1 of the platform device but I keep getting 0xc000 as its virtual address. If I try writing anything to it the driver crashes the system. Then I decided to switch to devmap_devmem_setup but then on calling it the driver crashes the system. Regards, Bhaskar. -----Original Message----- From: Garrett D'Amore [mailto:garr...@damore.org] Sent: Wednesday, September 16, 2009 7:13 PM To: Jayaraman, Bhaskar Cc: opensolaris-code@opensolaris.org Subject: Re: [osol-code] Doubt in ddi_regs_map_setup! Jayaraman, Bhaskar wrote: > Ok I changed the call to devmap_devmem_setup() but my driver is crashing. Any > idea why this could be happening? I'm calling it from the 'attach' routine > which I hope is allowed. Also all my callbacks do nothing and return 0 unless > they're void i.e. I'm not setting the pvtp pointers in the callbacks or > anything. > Regards, > Bhaskar. > It doesn't sound like conceptually you are doing anything wrong. I think we'd need to look at the crash dump and source code in order to understand why you're experiencing these crashes. - Garrett > -----Original Message----- > From: Garrett D'Amore [mailto:garr...@damore.org] > Sent: Tuesday, September 15, 2009 7:35 PM > To: Jayaraman, Bhaskar > Cc: opensolaris-code@opensolaris.org > Subject: Re: [osol-code] Doubt in ddi_regs_map_setup! > > Jayaraman, Bhaskar wrote: > >> Hi, I'm making this call on my driver's BAR1 which has a physical >> address 0xf2000008 written on it. So I'm assuming that when I call a >> hat_getpfnum(kas.a_hat, returned_address), I should get the physical >> page frame number. >> >> Instead I get 0xffffffff as its return value (which is definitely some >> error). Also the virtual address that ddi_regs_map_setup is returning >> 0xc000 as the virtual address for the physical address in the BAR1. >> >> Please note that hat_getpfnum returns proper values for other virtual >> addresses. Can someone help me understand what is going on in my case? >> >> > > I'm not sure exactly why this is failing, but you do know that > hat_getkpfnum() is an obsolete interface, right? Its been obsolete for > quite a long time now. (I think maybe as far back as Solaris 8.) > > If you're using this for mmap(), you should try implementing a > devmap(9e) routine instead. > > -- Garrett > >> Regards, >> >> Bhaskar. >> >> ------------------------------------------------------------------------ >> >> _______________________________________________ >> opensolaris-code mailing list >> opensolaris-code@opensolaris.org >> http://mail.opensolaris.org/mailman/listinfo/opensolaris-code >> >> > >
#include <sys/types.h> #include <sys/param.h> #include <sys/file.h> #include <sys/errno.h> #include <sys/open.h> #include <sys/cred.h> #include <sys/modctl.h> #include <sys/conf.h> #include <sys/devops.h> #include <sys/cmn_err.h> #include <sys/kmem.h> #include <sys/stat.h> #include <sys/mkdev.h> #include <sys/pci.h> #include <sys/scsi/scsi.h> #include <sys/ddi.h> #include <sys/sunddi.h> #include <sys/atomic.h> #ifndef USE_GENERIC_AEN_FRAMEWORK #include <sys/signal.h> #endif #define FALSE 0 #define TRUE (!FALSE) #define PLATFORM_NAME "platform" #define PLATFORM_DIDNODES 0x04 #define PLATFORM_DIDZALLOC 0x08 static int platform_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); static int platform_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); static int platform_open(dev_t *devp, int flag, int otyp, cred_t *cred); static int platform_close(dev_t dev, int flag, int otyp, cred_t *cred); static int platform_read(dev_t dev, struct uio *uiop, cred_t *credp); static int platform_write(dev_t dev, struct uio *uiop, cred_t *credp); static int platform_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp); static int platform_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp); static unsigned int platform_handler(char *ctx); /* ----- Device Access cb_ops Structure [start] ----- * * The data structure (cb_ops(9S)) MUST be provided and initialized * correctly. * * */ static struct cb_ops platform_cb_ops = { platform_open, platform_close, nodev, nodev, nodev, platform_read, platform_write, platform_ioctl, nodev, nodev, nodev, nochpoll, ddi_prop_op, NULL, D_NEW | D_MP }; /* ----- Device Access cb_ops Structure [end] ----- */ /* ----- Autoconfiguration Structure [start] ----- * * The data structures (modlinkage(9S),modldrv(9S),mod_driverops * and * dev_ops(9S)) MUST be provided and initialized correctly. * * */ static struct dev_ops platform_ops = { DEVO_REV, 0, /* reference count */ platform_getinfo, nulldev, nulldev, platform_attach, platform_detach, nodev, &platform_cb_ops, (struct bus_ops *)NULL }; extern struct mod_ops mod_driverops; static struct modldrv md = { &mod_driverops, /* Type of module. This is a driver */ "platform driver", /* Name of the module */ &platform_ops, }; static struct modlinkage ml = { MODREV_1, &md, NULL }; /* ----- Autoconfiguration Structure [end] ----- */ /* ----- State Pointer [start] ----- * * The driver MUST provide a state pointer, which is used by the * soft * state system to create the list of memory items. * */ struct platform_state { int instance; /* instance number */ dev_info_t *dip; /* dev_info structure */ }; ddi_acc_handle_t pci_handle; static void *statep; ddi_iblock_cookie_t plat_iblock_cookie; int plat_devmap_map(devmap_cookie_t dhp, dev_t dev, unsigned int flags, offset_t off, size_t len, void **pvtp) { return 0; } int plat_devmap_access(devmap_cookie_t dhp, void *pvtp, offset_t off, size_t len, unsigned int type, unsigned int rw) { return 0; } int plat_devmap_dup(devmap_cookie_t dhp, void *pvtp, devmap_cookie_t new_dhp, void **new_pvtp) { return 0; } void plat_devmap_unmap(devmap_cookie_t dhp, void *pvtp, offset_t off, size_t len, devmap_cookie_t new_dhp1, void **new_pvtp1, devmap_cookie_t new_dhp2, void **new_pvtp2) { ; } devmap_cookie_t devmap_cook; struct devmap_callback_ctl devmap_cb = { DEVMAP_OPS_REV, plat_devmap_map, plat_devmap_access, plat_devmap_dup, plat_devmap_unmap, }; unsigned int devmap_flags = 0; static struct ddi_device_acc_attr endian_attr = { DDI_DEVICE_ATTR_V0, DDI_STRUCTURE_LE_ACC, DDI_STRICTORDER_ACC }; /* ----- State Pointer [end] ----- */ /* ----- Loadable Module Routines [start] ----- * * All drivers MUST implement the _init(9E),_fini(9E) and _info(9E) * entry points to load,unload and report information about the * driver module. * */ static int _init(void) { int error; error = ddi_soft_state_init(&statep, sizeof(struct platform_state), 1); if (error) return error; error = mod_install(&ml); if (error) { ddi_soft_state_fini(&statep); return error; } return 0; } static int _info(struct modinfo *modinfop) { return mod_info(&ml, modinfop); } static int _fini(void) { int error; error = mod_remove(&ml); if (error) return error; ddi_soft_state_fini(&statep); return 0; } /* ----- Loadable Module Routines [end] ----- */ /* ----- Autoconfiguration Entry Point [start] ----- */ static int platform_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { int instance, status; struct platform_state *bs; char *ourmem; int flags, intNum, vendor_id, device_id, subsysid, subsysvid, base0, base1; switch(cmd) { case DDI_ATTACH: instance= ddi_get_instance(dip); /* Setup the PCI configuration space handles */ if (pci_config_setup(dip, &pci_handle) != DDI_SUCCESS) { cmn_err(CE_WARN, "platform%d: pci config setup failed ", instance); pci_config_teardown(&pci_handle); return DDI_FAILURE; } vendor_id = pci_config_get16(pci_handle, PCI_CONF_VENID); device_id = pci_config_get16(pci_handle, PCI_CONF_DEVID); subsysvid = pci_config_get16(pci_handle, PCI_CONF_SUBVENID); subsysid = pci_config_get16(pci_handle, PCI_CONF_SUBSYSID); base0 = pci_config_get32(pci_handle, PCI_CONF_BASE0); base1 = pci_config_get32(pci_handle, PCI_CONF_BASE1); cmn_err(CE_NOTE, "platform: vendor %x, device %x, subsysid %x, subsysvid %x, base0 %x, base1 %x\n", vendor_id, device_id, subsysid, subsysvid, base0, base1); #if 0 pci_config_put32(pci_handle, PCI_CONF_BASE0, 0x3fffd000); pci_config_put32(pci_handle, PCI_CONF_BASE1, 0x3fffd000); ddi_regs_map_setup(dip, 1, &ourmem, 0, 0, &endian_attr, &pci_handle); ourmem[0xffd000] = 0xa; ourmem[0xffd001] = 0xb; ourmem[0xffd002] = 0xc; ourmem[0xffd003] = 0xd; ourmem[0xffd004] = 0xe; ourmem[0xffd005] = 0xf; #endif if (devmap_devmem_setup(devmap_cook, dip, &devmap_cb, 1, 0, 4096, PROT_ALL, IOMEM_DATA_CACHED, &endian_attr) < 0) { cmn_err(CE_NOTE, "platform: couldn't map base1 reg"); } base0 = pci_config_get32(pci_handle, PCI_CONF_BASE0); base1 = pci_config_get32(pci_handle, PCI_CONF_BASE1); cmn_err(CE_NOTE, "platform: vendor %x, device %x, subsysid %x, subsysvid %x, base0 %x, base1 %x\n", vendor_id, device_id, subsysid, subsysvid, base0, base1); cmn_err(CE_NOTE, "platform: The address mapped at pfn %x virtual address %x\n", (unsigned long)hat_getpfnum(kas.a_hat, ourmem), ourmem); if (ddi_soft_state_zalloc(statep, instance) != DDI_SUCCESS) { pci_config_teardown(&pci_handle); return DDI_FAILURE; } flags = 0; bs = ddi_get_soft_state(statep, instance); if (bs == NULL) { goto out; } flags |= PLATFORM_DIDZALLOC; if (ddi_create_minor_node(dip, "0", S_IFCHR, instance, DDI_PSEUDO,0) != DDI_SUCCESS) { goto out; } flags |= PLATFORM_DIDNODES; ddi_set_driver_private(dip, (caddr_t)flags); ddi_dev_nintrs(dip, &intNum); ddi_get_iblock_cookie(dip, intNum, &plat_iblock_cookie); #if 0 status = ddi_add_intr(dip, intNum, &plat_iblock_cookie, NULL, platform_handler, NULL); if (status != DDI_SUCCESS) { cmn_err(CE_WARN, "ddi_add_intr() is not successful, Error: %d\n", status); } #endif ddi_report_dev(dip); return DDI_SUCCESS; default: return DDI_FAILURE; } out: /* Undo */ ddi_set_driver_private(dip, (caddr_t)flags); cmn_err(CE_WARN, "Platform: ddi_dev_nintrs(): %d\n", intNum); platform_detach(dip, DDI_DETACH); return DDI_FAILURE; } static unsigned int platform_handler(char *ctx) { cmn_err(CE_WARN, "Dummy handler"); return(DDI_INTR_CLAIMED); } static int platform_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) { int instance, flags, intNum; struct platform_state *bs; switch(cmd) { case DDI_DETACH: instance = ddi_get_instance(dip); bs = ddi_get_soft_state(statep, instance); if (bs == NULL) { return DDI_FAILURE; } flags = (int)ddi_get_driver_private(dip); if (flags & PLATFORM_DIDNODES) ddi_remove_minor_node(dip, NULL); if (flags & PLATFORM_DIDZALLOC) ddi_soft_state_free(statep, instance); #if 0 ddi_dev_nintrs(dip, &intNum); ddi_remove_intr(dip, intNum, plat_iblock_cookie); #endif pci_config_teardown(&pci_handle); return DDI_SUCCESS; default: return DDI_FAILURE; } } static int platform_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp) { dev_t dev; int instance, rval = DDI_FAILURE; struct platform_state *bs; switch(cmd) { case DDI_INFO_DEVT2DEVINFO: /* seek device's dev_info pointer */ dev = (dev_t)arg; instance = getminor(dev); bs = ddi_get_soft_state(statep, instance); if (bs != NULL) { *resultp = bs->dip; rval = DDI_SUCCESS; } else { *resultp = NULL; } break; case DDI_INFO_DEVT2INSTANCE: /* seek device's instance number */ dev = (dev_t)arg; instance = getminor(dev); *resultp = (void *)instance; rval = DDI_SUCCESS; break; default: break; } return rval; } /* ----- Autoconfiguration Entry Point [end] ----- */ /* ----- Character Driver Entry Point [start] ----- */ static int platform_open(dev_t *devp, int flag, int otyp, cred_t *cred) { return 0; } static int platform_close(dev_t dev, int flag, int otyp, cred_t *cred) { return 0; } static int platform_read(dev_t dev, struct uio *uiop, cred_t *credp) { return 0; } static int platform_write(dev_t dev, struct uio *uiop, cred_t *credp) { return 0; } static int platform_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) { return 0; } /* ----- Character Driver Entry Point [end] ----- */
_______________________________________________ opensolaris-code mailing list opensolaris-code@opensolaris.org http://mail.opensolaris.org/mailman/listinfo/opensolaris-code