Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:06

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  GR-TMTC-1553 PCI Target driver.
0004  * 
0005  *  COPYRIGHT (c) 2008.
0006  *  Cobham Gaisler AB.
0007  *
0008  *  Configures the GR-TMTC-1553 interface PCI board.
0009  *  This driver provides a AMBA PnP bus by using the general part
0010  *  of the AMBA PnP bus driver (ambapp_bus.c).
0011  *
0012  *  Driver resources for the AMBA PnP bus provided can be set using
0013  *  gr_tmtc_1553_set_resources().
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #include <inttypes.h>
0038 #include <stdio.h>
0039 #include <stdlib.h>
0040 #include <string.h>
0041 #include <sys/types.h>
0042 #include <sys/stat.h>
0043 
0044 #include <bsp.h>
0045 #include <rtems/bspIo.h>
0046 #include <pci.h>
0047 #include <pci/access.h>
0048 
0049 #include <grlib/ambapp.h>
0050 #include <grlib/grlib.h>
0051 #include <drvmgr/drvmgr.h>
0052 #include <grlib/ambapp_bus.h>
0053 #include <drvmgr/pci_bus.h>
0054 #include <grlib/bspcommon.h>
0055 #include <grlib/genirq.h>
0056 
0057 #include <grlib/gr_tmtc_1553.h>
0058 
0059 #include <grlib/grlib_impl.h>
0060 
0061 /*#define DEBUG 1 */
0062 
0063 #ifdef DEBUG
0064 #define DBG(x...) printk(x)
0065 #else
0066 #define DBG(x...) 
0067 #endif
0068 
0069 /* PCI ID */
0070 #define PCIID_VENDOR_GAISLER        0x1AC8
0071 
0072 int gr_tmtc_1553_init1(struct drvmgr_dev *dev);
0073 int gr_tmtc_1553_init2(struct drvmgr_dev *dev);
0074 void gr_tmtc_1553_isr (void *arg);
0075 
0076 struct gr_tmtc_1553_ver {
0077     const unsigned int  amba_freq_hz;   /* The frequency */
0078     const unsigned int  amba_ioarea;    /* The address where the PnP IOAREA starts at */
0079 };
0080 
0081 /* Private data structure for driver */
0082 struct gr_tmtc_1553_priv {
0083     /* Driver management */
0084     struct drvmgr_dev       *dev;
0085     char                prefix[32];
0086     SPIN_DECLARE(devlock);
0087 
0088     /* PCI */
0089     pci_dev_t           pcidev;
0090     struct pci_dev_info     *devinfo;
0091 
0092     /* IRQ */
0093     genirq_t            genirq;
0094 
0095     struct gr_tmtc_1553_ver         *version;
0096     struct irqmp_regs       *irq;
0097     struct drvmgr_map_entry     bus_maps_down[2];
0098 
0099     struct ambapp_bus       abus;
0100     struct ambapp_mmap      amba_maps[4];
0101         struct ambapp_config        config;
0102 };
0103 
0104 struct gr_tmtc_1553_ver gr_tmtc_1553_ver0 = {
0105     .amba_freq_hz       = 33333333,
0106     .amba_ioarea        = 0xfff00000,
0107 };
0108 
0109 
0110 int ambapp_tmtc_1553_int_register(
0111     struct drvmgr_dev *dev,
0112     int irq,
0113     const char *info,
0114     drvmgr_isr handler,
0115     void *arg);
0116 int ambapp_tmtc_1553_int_unregister(
0117     struct drvmgr_dev *dev,
0118     int irq,
0119     drvmgr_isr handler,
0120     void *arg);
0121 int ambapp_tmtc_1553_int_unmask(
0122     struct drvmgr_dev *dev,
0123     int irq);
0124 int ambapp_tmtc_1553_int_mask(
0125     struct drvmgr_dev *dev,
0126     int irq);
0127 int ambapp_tmtc_1553_int_clear(
0128     struct drvmgr_dev *dev,
0129     int irq);
0130 int ambapp_tmtc_1553_get_params(
0131     struct drvmgr_dev *dev,
0132     struct drvmgr_bus_params *params);
0133 
0134 struct ambapp_ops ambapp_tmtc_1553_ops = {
0135     .int_register = ambapp_tmtc_1553_int_register,
0136     .int_unregister = ambapp_tmtc_1553_int_unregister,
0137     .int_unmask = ambapp_tmtc_1553_int_unmask,
0138     .int_mask = ambapp_tmtc_1553_int_mask,
0139     .int_clear = ambapp_tmtc_1553_int_clear,
0140     .get_params = ambapp_tmtc_1553_get_params
0141 };
0142 
0143 struct drvmgr_drv_ops gr_tmtc_1553_ops = 
0144 {
0145     {gr_tmtc_1553_init1, gr_tmtc_1553_init2, NULL, NULL},
0146     NULL,
0147     NULL
0148 };
0149 
0150 struct pci_dev_id_match gr_tmtc_1553_ids[] = 
0151 {
0152     PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_TMTC_1553),
0153     PCIID_END_TABLE /* Mark end of table */
0154 };
0155 
0156 struct pci_drv_info gr_tmtc_1553_info =
0157 {
0158     {
0159         DRVMGR_OBJ_DRV,         /* Driver */
0160         NULL,               /* Next driver */
0161         NULL,               /* Device list */
0162         DRIVER_PCI_GAISLER_TMTC_1553_ID, /* Driver ID */
0163         "GR-TMTC-1553_DRV",     /* Driver Name */
0164         DRVMGR_BUS_TYPE_PCI,        /* Bus Type */
0165         &gr_tmtc_1553_ops,
0166         NULL,               /* Funcs */
0167         0,              /* No devices yet */
0168         0,
0169     },
0170     &gr_tmtc_1553_ids[0]
0171 };
0172 
0173 /* Driver resources configuration for the AMBA bus on the GR-RASTA-IO board.
0174  * It is declared weak so that the user may override it from the project file,
0175  * if the default settings are not enough.
0176  *
0177  * The configuration consists of an array of configuration pointers, each
0178  * pointer determine the configuration of one GR-RASTA-IO board. Pointer
0179  * zero is for board0, pointer 1 for board1 and so on.
0180  *
0181  * The array must end with a NULL pointer.
0182  */
0183 struct drvmgr_bus_res *gr_tmtc_1553_resources[] __attribute__((weak)) =
0184 {
0185     NULL
0186 };
0187 
0188 void gr_tmtc_1553_register_drv(void)
0189 {
0190     DBG("Registering GR-TMTC-1553 PCI driver\n");
0191     drvmgr_drv_register(&gr_tmtc_1553_info.general);
0192 }
0193 
0194 void gr_tmtc_1553_isr (void *arg)
0195 {
0196     struct gr_tmtc_1553_priv *priv = arg;
0197     unsigned int status, tmp;
0198     int irq;
0199     SPIN_ISR_IRQFLAGS(irqflags);
0200 
0201     tmp = status = priv->irq->ipend;
0202 
0203     /* DBG("GR-RASTA-IO: IRQ 0x%x\n",status); */
0204 
0205     SPIN_LOCK(&priv->devlock, irqflags);
0206     for(irq=0; irq<16; irq++) {
0207         if ( status & (1<<irq) ) {
0208             genirq_doirq(priv->genirq, irq);
0209             priv->irq->iclear = (1<<irq);
0210             status &= ~(1<<irq);
0211             if ( status == 0 )
0212                 break;
0213         }
0214     }
0215     SPIN_UNLOCK(&priv->devlock, irqflags);
0216 
0217     /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */
0218     if ( tmp ) 
0219         drvmgr_interrupt_clear(priv->dev, 0);
0220 
0221     DBG("GR-TMTC-1553-IRQ: 0x%x\n", tmp);
0222 }
0223 
0224 static int gr_tmtc_1553_hw_init(struct gr_tmtc_1553_priv *priv)
0225 {
0226     unsigned int *page0 = NULL;
0227     struct ambapp_dev *tmp;
0228     unsigned int pci_freq_hz;
0229     struct pci_dev_info *devinfo = priv->devinfo;
0230     uint32_t bar0, bar0_size;
0231 
0232     /* Select version of GR-TMTC-1553 board */
0233     switch (devinfo->rev) {
0234         case 0:
0235             priv->version = &gr_tmtc_1553_ver0;
0236             break;
0237         default:
0238             return -2;
0239     }
0240 
0241     bar0 = devinfo->resources[0].address;
0242     bar0_size = devinfo->resources[0].size;
0243     page0 = (unsigned int *)(bar0 + bar0_size/2); 
0244 
0245     /* Point PAGE0 to start of board address map. RAM at 0xff000000, APB at 0xffc00000, IOAREA at 0xfff000000 */
0246     /* XXX We assume little endian host with byte twisting enabled here */
0247     *page0 = 0x010000ff;    /* Set little endian mode on peripheral. */
0248 
0249     /* Scan AMBA Plug&Play */
0250 
0251     /* AMBA MAP bar0 (in CPU) ==> 0x80000000(remote amba address) */
0252     priv->amba_maps[0].size = 0x1000000;
0253     priv->amba_maps[0].local_adr = bar0;
0254     priv->amba_maps[0].remote_adr = 0xff000000;
0255     
0256     /* Addresses not matching with map be untouched */
0257     priv->amba_maps[2].size = 0xfffffff0;
0258     priv->amba_maps[2].local_adr = 0;
0259     priv->amba_maps[2].remote_adr = 0;
0260 
0261     /* Mark end of table */
0262     priv->amba_maps[3].size=0;
0263     priv->amba_maps[3].local_adr = 0;
0264     priv->amba_maps[3].remote_adr = 0;
0265 
0266     /* Start AMBA PnP scan at first AHB bus */
0267     ambapp_scan(&priv->abus,
0268         bar0 + (priv->version->amba_ioarea & ~0xff000000),
0269         NULL, &priv->amba_maps[0]);
0270 
0271     /* Frequency is the hsame as the PCI bus frequency */
0272     drvmgr_freq_get(priv->dev, 0, &pci_freq_hz);
0273 
0274     ambapp_freq_init(&priv->abus, NULL, pci_freq_hz);
0275 
0276     /* Find IRQ controller */
0277     tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
0278                     (OPTIONS_ALL|OPTIONS_APB_SLVS),
0279                     VENDOR_GAISLER, GAISLER_IRQMP,
0280                     ambapp_find_by_idx, NULL);
0281     if ( !tmp ) {
0282         return -4;
0283     }
0284     priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start;
0285     /* Set up irq controller */
0286     priv->irq->mask[0] = 0;
0287     priv->irq->iclear = 0xffff;
0288     priv->irq->ilevel = 0;
0289 
0290     /* DOWN streams translation table */
0291     priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA";
0292     priv->bus_maps_down[0].size = priv->amba_maps[0].size;
0293     priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr;
0294     priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr;
0295     /* Mark end of translation table */
0296     priv->bus_maps_down[1].size = 0;
0297 
0298     /* Successfully registered the board */
0299     return 0;
0300 }
0301 
0302 
0303 /* Called when a PCI target is found with the PCI device and vendor ID 
0304  * given in gr_tmtc_1553_ids[].
0305  */
0306 int gr_tmtc_1553_init1(struct drvmgr_dev *dev)
0307 {
0308     struct gr_tmtc_1553_priv *priv;
0309     struct pci_dev_info *devinfo;
0310     int status;
0311     uint32_t bar0, bar0_size;
0312     int resources_cnt;
0313     int sc;
0314 
0315     /* PCI device does not have the IRQ line register, when PCI autoconf configures it the configuration
0316      * is forgotten. We take the IRQ number from the PCI Host device (AMBA device), this works as long
0317      * as PCI-IRQs are ored together on the bus.
0318      *
0319      * Note that this only works on LEON.
0320      */
0321     ((struct pci_dev_info *)dev->businfo)->irq = ((struct amba_dev_info *)dev->parent->dev->businfo)->info.irq; 
0322 
0323     priv = grlib_calloc(1, sizeof(*priv));
0324     if ( !priv )
0325         return DRVMGR_NOMEM;
0326 
0327     dev->priv = priv;
0328     priv->dev = dev;
0329 
0330     /* Determine number of configurations */
0331     resources_cnt = get_resarray_count(gr_tmtc_1553_resources);
0332 
0333     /* Generate Device prefix */
0334 
0335     strcpy(priv->prefix, "/dev/tmtc1553_0");
0336     priv->prefix[14] += dev->minor_drv;
0337     sc = mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO);
0338     _Assert_Unused_variable_equals(sc, 0);
0339     priv->prefix[15] = '/';
0340     priv->prefix[16] = '\0';
0341 
0342     priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo;
0343     priv->pcidev = devinfo->pcidev;
0344     bar0 = devinfo->resources[0].address;
0345     bar0_size = devinfo->resources[0].size;
0346     printk("\n\n--- GR-TMTC-1553[%d] ---\n", dev->minor_drv);
0347     printk(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n",
0348         PCI_DEV_EXPAND(priv->pcidev));
0349     printk(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n",
0350         devinfo->id.vendor, devinfo->id.device);
0351     printk(" PCI BAR[0]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
0352         bar0, bar0 + bar0_size - 1);
0353     printk(" IRQ: %d\n\n\n", devinfo->irq);
0354 
0355     /* all neccessary space assigned to GR-TMTC-1553 target? */
0356     if (bar0_size == 0)
0357         return DRVMGR_ENORES;
0358 
0359     /* Initialize spin-lock for this PCI peripheral device. This is to
0360      * protect the Interrupt Controller Registers. The genirq layer is
0361          * protecting its own internals and ISR dispatching.
0362          */
0363     SPIN_INIT(&priv->devlock, priv->prefix);
0364 
0365     priv->genirq = genirq_init(16);
0366     if ( priv->genirq == NULL ) {
0367         free(priv);
0368         dev->priv = NULL;
0369         return DRVMGR_FAIL;
0370     }
0371 
0372     status = gr_tmtc_1553_hw_init(priv);
0373     if ( status != 0 ) {
0374         genirq_destroy(priv->genirq);
0375         free(priv);
0376         dev->priv = NULL;
0377         printk(" Failed to initialize GR-TMTC-1553 HW: %d\n", status);
0378         return DRVMGR_FAIL;
0379     }
0380 
0381     /* Init amba bus */
0382     priv->config.abus = &priv->abus;
0383     priv->config.ops = &ambapp_tmtc_1553_ops;
0384     priv->config.maps_down = &priv->bus_maps_down[0];
0385     /* This PCI device has only target interface so DMA is not supported,
0386      * which means that translation from AMBA->PCI should fail if attempted.
0387      */
0388     priv->config.maps_up = DRVMGR_TRANSLATE_NO_BRIDGE;
0389     if ( priv->dev->minor_drv < resources_cnt ) {
0390         priv->config.resources = gr_tmtc_1553_resources[priv->dev->minor_drv];
0391     } else {
0392         priv->config.resources = NULL;
0393     }
0394 
0395     /* Create And Register AMBA PnP Bus */
0396     return ambapp_bus_register(dev, &priv->config);
0397 }
0398 
0399 int gr_tmtc_1553_init2(struct drvmgr_dev *dev)
0400 {
0401     struct gr_tmtc_1553_priv *priv = dev->priv;
0402 
0403     /* Clear any old interrupt requests */
0404     drvmgr_interrupt_clear(dev, 0);
0405 
0406     /* Enable System IRQ so that GR-TMTC-1553 PCI target interrupt goes through.
0407      *
0408      * It is important to enable it in stage init2. If interrupts were enabled in init1
0409      * this might hang the system when more than one PCI target is connected, this is
0410      * because PCI interrupts might be shared and PCI target 2 have not initialized and
0411      * might therefore drive interrupt already when entering init1().
0412      */
0413     drvmgr_interrupt_register(
0414         dev,
0415         0,
0416         "gr_tmtc_1553",
0417         gr_tmtc_1553_isr,
0418         (void *)priv);
0419 
0420     return DRVMGR_OK;
0421 }
0422 
0423 int ambapp_tmtc_1553_int_register(
0424     struct drvmgr_dev *dev,
0425     int irq,
0426     const char *info,
0427     drvmgr_isr handler,
0428     void *arg)
0429 {
0430     struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
0431     SPIN_IRQFLAGS(irqflags);
0432     int status;
0433     void *h;
0434 
0435     h = genirq_alloc_handler(handler, arg);
0436     if ( h == NULL )
0437         return DRVMGR_FAIL;
0438 
0439     SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0440 
0441     status = genirq_register(priv->genirq, irq, h);
0442     if ( status == 0 ) {
0443         /* Disable and clear IRQ for first registered handler */
0444         priv->irq->iclear = (1<<irq);
0445         priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
0446     } else if ( status == 1 )
0447         status = 0;
0448 
0449     if (status != 0) {
0450         SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0451         genirq_free_handler(h);
0452         return DRVMGR_FAIL;
0453     }
0454 
0455     status = genirq_enable(priv->genirq, irq, handler, arg);
0456     if ( status == 0 ) {
0457         /* Enable IRQ for first enabled handler only */
0458         priv->irq->mask[0] |= (1<<irq); /* unmask interrupt source */
0459     } else if ( status == 1 )
0460         status = 0;
0461 
0462     SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0463 
0464     return status;
0465 }
0466 
0467 int ambapp_tmtc_1553_int_unregister(
0468     struct drvmgr_dev *dev,
0469     int irq,
0470     drvmgr_isr isr,
0471     void *arg)
0472 {
0473     struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
0474     SPIN_IRQFLAGS(irqflags);
0475     int status;
0476     void *handler;
0477 
0478     SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0479 
0480     status = genirq_disable(priv->genirq, irq, isr, arg);
0481     if ( status == 0 ) {
0482         /* Disable IRQ only when no enabled handler exists */
0483         priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
0484     } else if ( status == 1 )
0485         status = 0;
0486 
0487     handler = genirq_unregister(priv->genirq, irq, isr, arg);
0488     if ( handler == NULL )
0489         status = DRVMGR_FAIL;
0490     else
0491         status = DRVMGR_OK;
0492 
0493     SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0494 
0495     if (handler)
0496         genirq_free_handler(handler);
0497 
0498     return status;
0499 }
0500 
0501 int ambapp_tmtc_1553_int_unmask(
0502     struct drvmgr_dev *dev,
0503     int irq)
0504 {
0505     struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
0506     SPIN_IRQFLAGS(irqflags);
0507 
0508     DBG("TMTC-1553 IRQ %d: enable\n", irq);
0509     
0510     if ( genirq_check(priv->genirq, irq) )
0511         return DRVMGR_FAIL;
0512 
0513     SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0514 
0515     /* Enable IRQ */
0516     priv->irq->mask[0] |= (1<<irq); /* unmask interrupt source */
0517 
0518     SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0519 
0520     return DRVMGR_OK;
0521 }
0522 
0523 int ambapp_tmtc_1553_int_mask(
0524     struct drvmgr_dev *dev,
0525     int irq)
0526 {
0527     struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
0528     SPIN_IRQFLAGS(irqflags);
0529 
0530     DBG("TMTC-1553 IRQ %d: disable\n", irq);
0531 
0532     if ( genirq_check(priv->genirq, irq) )
0533         return DRVMGR_FAIL;
0534 
0535     SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0536 
0537     /* Disable IRQ */
0538     priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
0539 
0540     SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0541 
0542     return DRVMGR_OK;
0543 }
0544 
0545 int ambapp_tmtc_1553_int_clear(
0546     struct drvmgr_dev *dev,
0547     int irq)
0548 {
0549     struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
0550 
0551     if ( genirq_check(priv->genirq, irq) )
0552         return DRVMGR_FAIL;
0553 
0554     priv->irq->iclear = (1<<irq);
0555 
0556     return DRVMGR_OK;
0557 }
0558 
0559 int ambapp_tmtc_1553_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
0560 {
0561     struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
0562 
0563     /* Device name prefix pointer, skip /dev */
0564     params->dev_prefix = &priv->prefix[5];
0565 
0566     return 0;
0567 }
0568 
0569 void gr_tmtc_1553_print_dev(struct drvmgr_dev *dev, int options)
0570 {
0571     struct gr_tmtc_1553_priv *priv = dev->priv;
0572     struct pci_dev_info *devinfo = priv->devinfo;
0573     uint32_t bar0, bar0_size;
0574 
0575     /* Print */
0576     printf("--- GR-TMTC-1553 [bus 0x%x, dev 0x%x, fun 0x%x] ---\n",
0577         PCI_DEV_EXPAND(priv->pcidev));
0578 
0579     bar0 = devinfo->resources[0].address;
0580     bar0_size = devinfo->resources[0].size;
0581 
0582     printf(" PCI BAR[0]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
0583         bar0, bar0 + bar0_size - 1);
0584     printf(" IRQ REGS:        0x%" PRIxPTR "\n", (uintptr_t)priv->irq);
0585     printf(" IRQ:             %d\n", devinfo->irq);
0586     printf(" FREQ:            %d Hz\n", priv->version->amba_freq_hz);
0587     printf(" IMASK:           0x%08x\n", priv->irq->mask[0]);
0588     printf(" IPEND:           0x%08x\n", priv->irq->ipend);
0589 
0590     /* Print amba config */
0591     if ( options & TMTC_1553_OPTIONS_AMBA ) {
0592         ambapp_print(&priv->abus, 10);
0593     }
0594 #if 0
0595     /* Print IRQ handlers and their arguments */
0596     if ( options & TMTC_1553_OPTIONS_IRQ ) {
0597         int i;
0598         for(i=0; i<16; i++) {
0599             printf(" IRQ[%02d]:         0x%x, arg: 0x%x\n", 
0600                 i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg);
0601         }
0602     }
0603 #endif
0604 }
0605 
0606 void gr_tmtc_1553_print(int options)
0607 {
0608     struct pci_drv_info *drv = &gr_tmtc_1553_info;
0609     struct drvmgr_dev *dev;
0610 
0611     dev = drv->general.dev;
0612     while(dev) {
0613         gr_tmtc_1553_print_dev(dev, options);
0614         dev = dev->next_in_drv;
0615     }
0616 }