File indexing completed on 2025-05-11 08:24:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <inttypes.h>
0036 #include <stdio.h>
0037 #include <stdlib.h>
0038 #include <string.h>
0039 #include <sys/types.h>
0040 #include <sys/stat.h>
0041
0042 #include <bsp.h>
0043 #include <rtems/bspIo.h>
0044 #include <pci.h>
0045
0046 #include <grlib/ambapp.h>
0047 #include <grlib/grlib.h>
0048 #include <drvmgr/drvmgr.h>
0049 #include <grlib/ambapp_bus.h>
0050 #include <drvmgr/pci_bus.h>
0051 #include <grlib/bspcommon.h>
0052 #include <grlib/genirq.h>
0053 #include <grlib/gr_rasta_spw_router.h>
0054
0055 #include <grlib/grlib_impl.h>
0056
0057
0058
0059
0060
0061 extern unsigned int _RAM_START;
0062 #define AHBMST2PCIADR (((unsigned int)&_RAM_START) & 0xf0000000)
0063
0064
0065 #define AHB1_BASE_ADDR 0x80000000
0066 #define AHB1_IOAREA_BASE_ADDR 0x80100000
0067
0068 #define GRPCI2_BAR0_TO_AHB_MAP 0x04
0069 #define GRPCI2_PCI_CONFIG 0x20
0070
0071
0072
0073 #ifdef DEBUG
0074 #define DBG(x...) printk(x)
0075 #else
0076 #define DBG(x...)
0077 #endif
0078
0079
0080 #define PCIID_VENDOR_GAISLER 0x1AC8
0081
0082 int gr_rasta_spw_router_init1(struct drvmgr_dev *dev);
0083 int gr_rasta_spw_router_init2(struct drvmgr_dev *dev);
0084 void gr_rasta_spw_router_isr(void *arg);
0085
0086 struct grpci2_regs {
0087 volatile unsigned int ctrl;
0088 volatile unsigned int statcap;
0089 volatile unsigned int pcimstprefetch;
0090 volatile unsigned int ahbtopciiomap;
0091 volatile unsigned int dmactrl;
0092 volatile unsigned int dmadesc;
0093 volatile unsigned int dmachanact;
0094 volatile unsigned int reserved;
0095 volatile unsigned int pcibartoahb[6];
0096 volatile unsigned int reserved2[2];
0097 volatile unsigned int ahbtopcimemmap[16];
0098 volatile unsigned int trcctrl;
0099 volatile unsigned int trccntmode;
0100 volatile unsigned int trcadpat;
0101 volatile unsigned int trcadmask;
0102 volatile unsigned int trcctrlsigpat;
0103 volatile unsigned int trcctrlsigmask;
0104 volatile unsigned int trcadstate;
0105 volatile unsigned int trcctrlsigstate;
0106 };
0107
0108 struct gr_rasta_spw_router_ver {
0109 const unsigned int amba_freq_hz;
0110 const unsigned int amba_ioarea;
0111 };
0112
0113
0114 struct gr_rasta_spw_router_priv {
0115
0116 struct drvmgr_dev *dev;
0117 char prefix[20];
0118 SPIN_DECLARE(devlock);
0119
0120
0121 pci_dev_t pcidev;
0122 struct pci_dev_info *devinfo;
0123 uint32_t ahbmst2pci_map;
0124
0125
0126 genirq_t genirq;
0127
0128
0129 struct gr_rasta_spw_router_ver *version;
0130 struct irqmp_regs *irq;
0131 struct grpci2_regs *grpci2;
0132 struct drvmgr_map_entry bus_maps_up[2];
0133 struct drvmgr_map_entry bus_maps_down[2];
0134
0135
0136 struct ambapp_bus abus;
0137 struct ambapp_mmap amba_maps[3];
0138 struct ambapp_config config;
0139 };
0140
0141 struct gr_rasta_spw_router_ver gr_rasta_spw_router_ver0 = {
0142 .amba_freq_hz = 50000000,
0143 .amba_ioarea = 0xfff00000,
0144 };
0145
0146 int ambapp_rasta_spw_router_int_register(
0147 struct drvmgr_dev *dev,
0148 int irq,
0149 const char *info,
0150 drvmgr_isr handler,
0151 void *arg);
0152 int ambapp_rasta_spw_router_int_unregister(
0153 struct drvmgr_dev *dev,
0154 int irq,
0155 drvmgr_isr handler,
0156 void *arg);
0157 int ambapp_rasta_spw_router_int_unmask(
0158 struct drvmgr_dev *dev,
0159 int irq);
0160 int ambapp_rasta_spw_router_int_mask(
0161 struct drvmgr_dev *dev,
0162 int irq);
0163 int ambapp_rasta_spw_router_int_clear(
0164 struct drvmgr_dev *dev,
0165 int irq);
0166 int ambapp_rasta_spw_router_get_params(
0167 struct drvmgr_dev *dev,
0168 struct drvmgr_bus_params *params);
0169
0170 struct ambapp_ops ambapp_rasta_spw_router_ops = {
0171 .int_register = ambapp_rasta_spw_router_int_register,
0172 .int_unregister = ambapp_rasta_spw_router_int_unregister,
0173 .int_unmask = ambapp_rasta_spw_router_int_unmask,
0174 .int_mask = ambapp_rasta_spw_router_int_mask,
0175 .int_clear = ambapp_rasta_spw_router_int_clear,
0176 .get_params = ambapp_rasta_spw_router_get_params
0177 };
0178
0179 struct drvmgr_drv_ops gr_rasta_spw_router_ops =
0180 {
0181 .init = {gr_rasta_spw_router_init1, gr_rasta_spw_router_init2, NULL, NULL},
0182 .remove = NULL,
0183 .info = NULL
0184 };
0185
0186 struct pci_dev_id_match gr_rasta_spw_router_ids[] =
0187 {
0188 PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_SPW_RTR),
0189 PCIID_END_TABLE
0190 };
0191
0192 struct pci_drv_info gr_rasta_spw_router_info =
0193 {
0194 {
0195 DRVMGR_OBJ_DRV,
0196 NULL,
0197 NULL,
0198 DRIVER_PCI_GAISLER_RASTA_SPW_ROUTER_ID,
0199 "GR-RASTA-SPW_ROUTER_DRV",
0200 DRVMGR_BUS_TYPE_PCI,
0201 &gr_rasta_spw_router_ops,
0202 NULL,
0203 0,
0204 sizeof(struct gr_rasta_spw_router_priv),
0205 },
0206 &gr_rasta_spw_router_ids[0]
0207 };
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219 struct drvmgr_bus_res *gr_rasta_spw_router_resources[] __attribute__((weak)) =
0220 {
0221 NULL
0222 };
0223
0224 void gr_rasta_spw_router_register_drv(void)
0225 {
0226 DBG("Registering GR-RASTA-SPW-ROUTER PCI driver\n");
0227 drvmgr_drv_register(&gr_rasta_spw_router_info.general);
0228 }
0229
0230 void gr_rasta_spw_router_isr(void *arg)
0231 {
0232 struct gr_rasta_spw_router_priv *priv = arg;
0233 unsigned int status, tmp;
0234 int irq;
0235 SPIN_ISR_IRQFLAGS(irqflags);
0236
0237 tmp = status = priv->irq->ipend;
0238
0239
0240
0241 SPIN_LOCK(&priv->devlock, irqflags);
0242 for(irq=0; irq<16; irq++) {
0243 if ( status & (1<<irq) ) {
0244 genirq_doirq(priv->genirq, irq);
0245 priv->irq->iclear = (1<<irq);
0246 status &= ~(1<<irq);
0247 if ( status == 0 )
0248 break;
0249 }
0250 }
0251 SPIN_UNLOCK(&priv->devlock, irqflags);
0252
0253
0254
0255
0256 if ( tmp )
0257 drvmgr_interrupt_clear(priv->dev, 0);
0258
0259 DBG("RASTA-SPW_ROUTER-IRQ: 0x%x\n", tmp);
0260 }
0261
0262 static int gr_rasta_spw_router_hw_init(struct gr_rasta_spw_router_priv *priv)
0263 {
0264 int i;
0265 uint32_t data;
0266 unsigned int ctrl;
0267 uint8_t tmp2;
0268 struct ambapp_dev *tmp;
0269 struct ambapp_ahb_info *ahb;
0270 uint8_t cap_ptr;
0271 pci_dev_t pcidev = priv->pcidev;
0272 struct pci_dev_info *devinfo = priv->devinfo;
0273
0274
0275
0276
0277 switch (devinfo->rev) {
0278 case 0:
0279 priv->version = &gr_rasta_spw_router_ver0;
0280 break;
0281 default:
0282 return -2;
0283 }
0284
0285
0286 pci_cfg_r8(pcidev, PCIR_STATUS, &tmp2);
0287
0288 if (!((tmp2 >> 4) & 1)) {
0289
0290 return -3;
0291 }
0292
0293
0294 pci_cfg_r8(pcidev, PCIR_CAP_PTR, &cap_ptr);
0295
0296
0297 pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR0_TO_AHB_MAP, 0xffe00000);
0298
0299
0300 pci_cfg_r32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, &data);
0301 data = data & 0xFFFFFFFE;
0302 pci_cfg_w32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, data);
0303
0304 #if 0
0305
0306 pci_cfg_r32(pcidev, PCIR_COMMAND, &data);
0307 pci_cfg_w32(pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN));
0308 #endif
0309
0310
0311
0312
0313 priv->amba_maps[0].size = devinfo->resources[0].size;
0314 priv->amba_maps[0].local_adr = devinfo->resources[0].address;
0315 priv->amba_maps[0].remote_adr = 0xffe00000;
0316
0317
0318 priv->amba_maps[1].size = 0xfffffff0;
0319 priv->amba_maps[1].local_adr = 0;
0320 priv->amba_maps[1].remote_adr = 0;
0321
0322
0323 priv->amba_maps[2].size=0;
0324
0325
0326 ambapp_scan(
0327 &priv->abus,
0328 devinfo->resources[0].address + 0x100000,
0329 NULL,
0330 &priv->amba_maps[0]);
0331
0332
0333 ambapp_freq_init(&priv->abus, NULL, priv->version->amba_freq_hz);
0334
0335
0336 tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
0337 (OPTIONS_ALL|OPTIONS_APB_SLVS),
0338 VENDOR_GAISLER, GAISLER_IRQMP,
0339 ambapp_find_by_idx, NULL);
0340 if ( !tmp ) {
0341 return -4;
0342 }
0343 priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start;
0344
0345 priv->irq->mask[0] = 0;
0346 priv->irq->iclear = 0xffff;
0347 priv->irq->ilevel = 0;
0348
0349 priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA";
0350 priv->bus_maps_down[0].size = priv->amba_maps[0].size;
0351 priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr;
0352 priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr;
0353 priv->bus_maps_down[1].size = 0;
0354
0355
0356 tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
0357 (OPTIONS_ALL|OPTIONS_AHB_SLVS),
0358 VENDOR_GAISLER, GAISLER_GRPCI2,
0359 ambapp_find_by_idx, NULL);
0360 if ( !tmp ) {
0361 return -5;
0362 }
0363 ahb = (struct ambapp_ahb_info *)tmp->devinfo;
0364 priv->bus_maps_up[0].name = "AMBA GRPCI2 Window";
0365 priv->bus_maps_up[0].size = ahb->mask[0];
0366 priv->bus_maps_up[0].from_adr = (void *)ahb->start[0];
0367 priv->bus_maps_up[0].to_adr = (void *)
0368 (priv->ahbmst2pci_map & ~(ahb->mask[0]-1));
0369 priv->bus_maps_up[1].size = 0;
0370
0371
0372 tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
0373 (OPTIONS_ALL|OPTIONS_APB_SLVS),
0374 VENDOR_GAISLER, GAISLER_GRPCI2,
0375 ambapp_find_by_idx, NULL);
0376 if ( !tmp ) {
0377 return -6;
0378 }
0379 priv->grpci2 = (struct grpci2_regs *)
0380 ((struct ambapp_apb_info *)tmp->devinfo)->start;
0381
0382
0383 for(i = 0; i < 16; i++) {
0384 priv->grpci2->ahbtopcimemmap[i] = priv->ahbmst2pci_map &
0385 ~(ahb->mask[0]-1);
0386 }
0387
0388
0389 ctrl = priv->grpci2->ctrl;
0390 ctrl = (ctrl & 0xFFFFFF0F) | (1 << 4);
0391 priv->grpci2->ctrl = ctrl;
0392
0393
0394 return 0;
0395 }
0396
0397 static int gr_rasta_spw_router_hw_init2(struct gr_rasta_spw_router_priv *priv)
0398 {
0399
0400 pci_master_enable(priv->pcidev);
0401
0402 return DRVMGR_OK;
0403 }
0404
0405
0406
0407
0408 int gr_rasta_spw_router_init1(struct drvmgr_dev *dev)
0409 {
0410 struct gr_rasta_spw_router_priv *priv;
0411 struct pci_dev_info *devinfo;
0412 int status;
0413 uint32_t bar0, bar0_size;
0414 union drvmgr_key_value *value;
0415 int resources_cnt;
0416 int sc;
0417
0418 priv = dev->priv;
0419 if (!priv)
0420 return DRVMGR_NOMEM;
0421
0422 memset(priv, 0, sizeof(*priv));
0423 dev->priv = priv;
0424 priv->dev = dev;
0425
0426
0427 resources_cnt = get_resarray_count(gr_rasta_spw_router_resources);
0428
0429
0430
0431 strcpy(priv->prefix, "/dev/spwrouter0");
0432 priv->prefix[14] += dev->minor_drv;
0433 sc = mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO);
0434 _Assert_Unused_variable_equals(sc, 0);
0435 priv->prefix[15] = '/';
0436 priv->prefix[16] = '\0';
0437
0438 priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo;
0439 priv->pcidev = devinfo->pcidev;
0440 bar0 = devinfo->resources[0].address;
0441 bar0_size = devinfo->resources[0].size;
0442 printk("\n\n--- GR-RASTA-SPW-ROUTER[%d] ---\n", dev->minor_drv);
0443 printk(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n",
0444 PCI_DEV_EXPAND(priv->pcidev));
0445 printk(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n",
0446 devinfo->id.vendor, devinfo->id.device);
0447 printk(" PCI BAR[0]: 0x%08" PRIx32 " - 0x%08" PRIx32 "\n",
0448 bar0, bar0 + bar0_size - 1);
0449 printk(" IRQ: %d\n\n\n", devinfo->irq);
0450
0451
0452 if (bar0_size == 0)
0453 return DRVMGR_ENORES;
0454
0455
0456
0457
0458
0459 SPIN_INIT(&priv->devlock, priv->prefix);
0460
0461
0462
0463
0464
0465
0466
0467
0468 value = drvmgr_dev_key_get(priv->dev, "ahbmst2pci", DRVMGR_KT_INT);
0469 if (value)
0470 priv->ahbmst2pci_map = value->i;
0471 else
0472 priv->ahbmst2pci_map = AHBMST2PCIADR;
0473
0474 priv->genirq = genirq_init(16);
0475 if ( priv->genirq == NULL )
0476 return DRVMGR_FAIL;
0477
0478 if ((status = gr_rasta_spw_router_hw_init(priv)) != 0) {
0479 genirq_destroy(priv->genirq);
0480 printk(" Failed to initialize GR-RASTA-SPW-ROUTER HW: %d\n", status);
0481 return DRVMGR_FAIL;
0482 }
0483
0484
0485 priv->config.abus = &priv->abus;
0486 priv->config.ops = &ambapp_rasta_spw_router_ops;
0487 priv->config.maps_up = &priv->bus_maps_up[0];
0488 priv->config.maps_down = &priv->bus_maps_down[0];
0489 if ( priv->dev->minor_drv < resources_cnt ) {
0490 priv->config.resources = gr_rasta_spw_router_resources[priv->dev->minor_drv];
0491 } else {
0492 priv->config.resources = NULL;
0493 }
0494
0495
0496 return ambapp_bus_register(dev, &priv->config);
0497 }
0498
0499 int gr_rasta_spw_router_init2(struct drvmgr_dev *dev)
0500 {
0501 struct gr_rasta_spw_router_priv *priv = dev->priv;
0502
0503
0504 drvmgr_interrupt_clear(dev, 0);
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515 drvmgr_interrupt_register(
0516 dev,
0517 0,
0518 "gr_rasta_spw_router",
0519 gr_rasta_spw_router_isr,
0520 (void *)priv);
0521
0522 return gr_rasta_spw_router_hw_init2(priv);
0523 }
0524
0525 int ambapp_rasta_spw_router_int_register(
0526 struct drvmgr_dev *dev,
0527 int irq,
0528 const char *info,
0529 drvmgr_isr handler,
0530 void *arg)
0531 {
0532 struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv;
0533 SPIN_IRQFLAGS(irqflags);
0534 int status;
0535 void *h;
0536
0537 h = genirq_alloc_handler(handler, arg);
0538 if ( h == NULL )
0539 return DRVMGR_FAIL;
0540
0541 SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0542
0543 status = genirq_register(priv->genirq, irq, h);
0544 if (status == 0) {
0545
0546 priv->irq->iclear = (1<<irq);
0547 } else if (status == 1)
0548 status = 0;
0549
0550 if (status != 0) {
0551 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0552 genirq_free_handler(h);
0553 return DRVMGR_FAIL;
0554 }
0555
0556 status = genirq_enable(priv->genirq, irq, handler, arg);
0557 if ( status == 0 ) {
0558
0559 priv->irq->mask[0] |= (1<<irq);
0560 } else if ( status == 1 )
0561 status = 0;
0562
0563 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0564
0565 return status;
0566 }
0567
0568 int ambapp_rasta_spw_router_int_unregister(
0569 struct drvmgr_dev *dev,
0570 int irq,
0571 drvmgr_isr isr,
0572 void *arg)
0573 {
0574 struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv;
0575 SPIN_IRQFLAGS(irqflags);
0576 int status;
0577 void *handler;
0578
0579 SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0580
0581 status = genirq_disable(priv->genirq, irq, isr, arg);
0582 if ( status == 0 ) {
0583
0584 priv->irq->mask[0] &= ~(1<<irq);
0585 }
0586
0587 handler = genirq_unregister(priv->genirq, irq, isr, arg);
0588 if ( handler == NULL )
0589 status = DRVMGR_FAIL;
0590 else
0591 status = DRVMGR_OK;
0592
0593 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0594
0595 if (handler)
0596 genirq_free_handler(handler);
0597
0598 return status;
0599 }
0600
0601 int ambapp_rasta_spw_router_int_unmask(
0602 struct drvmgr_dev *dev,
0603 int irq)
0604 {
0605 struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv;
0606 SPIN_IRQFLAGS(irqflags);
0607
0608 DBG("RASTA-SPW-ROUTER IRQ %d: unmask\n", irq);
0609
0610 if ( genirq_check(priv->genirq, irq) )
0611 return DRVMGR_EINVAL;
0612
0613 SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0614
0615
0616 priv->irq->mask[0] |= (1<<irq);
0617
0618 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0619
0620 return DRVMGR_OK;
0621 }
0622
0623 int ambapp_rasta_spw_router_int_mask(
0624 struct drvmgr_dev *dev,
0625 int irq)
0626 {
0627 struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv;
0628 SPIN_IRQFLAGS(irqflags);
0629
0630 DBG("RASTA-SPW-ROUTER IRQ %d: mask\n", irq);
0631
0632 if ( genirq_check(priv->genirq, irq) )
0633 return DRVMGR_EINVAL;
0634
0635 SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0636
0637
0638 priv->irq->mask[0] &= ~(1<<irq);
0639
0640 SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0641
0642 return DRVMGR_OK;
0643 }
0644
0645 int ambapp_rasta_spw_router_int_clear(
0646 struct drvmgr_dev *dev,
0647 int irq)
0648 {
0649 struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv;
0650
0651 if ( genirq_check(priv->genirq, irq) )
0652 return DRVMGR_EINVAL;
0653
0654 priv->irq->iclear = (1<<irq);
0655
0656 return DRVMGR_OK;
0657 }
0658
0659 int ambapp_rasta_spw_router_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
0660 {
0661 struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv;
0662
0663
0664 params->dev_prefix = &priv->prefix[5];
0665
0666 return 0;
0667 }
0668
0669 void gr_rasta_spw_router_print_dev(struct drvmgr_dev *dev, int options)
0670 {
0671 struct gr_rasta_spw_router_priv *priv = dev->priv;
0672 struct pci_dev_info *devinfo = priv->devinfo;
0673 uint32_t bar0, bar0_size;
0674
0675
0676 printf("--- GR-RASTA-SPW-ROUTER [bus 0x%x, dev 0x%x, fun 0x%x] ---\n",
0677 PCI_DEV_EXPAND(priv->pcidev));
0678
0679 bar0 = devinfo->resources[0].address;
0680 bar0_size = devinfo->resources[0].size;
0681 printf(" PCI BAR[0]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
0682 bar0, bar0 + bar0_size - 1);
0683 printf(" IRQ REGS: 0x%" PRIxPTR "\n", (uintptr_t)priv->irq);
0684 printf(" IRQ: %d\n", devinfo->irq);
0685 printf(" PCI REVISION: %d\n", devinfo->rev);
0686 printf(" FREQ: %d Hz\n", priv->version->amba_freq_hz);
0687 printf(" IMASK: 0x%08x\n", priv->irq->mask[0]);
0688 printf(" IPEND: 0x%08x\n", priv->irq->ipend);
0689
0690
0691 if (options & RASTA_SPW_ROUTER_OPTIONS_AMBA)
0692 ambapp_print(&priv->abus, 10);
0693
0694 #if 0
0695
0696 if (options & RASTA_SPW_ROUTER_OPTIONS_IRQ) {
0697 int i;
0698 for(i = 0; i < 16; i++) {
0699 printf(" IRQ[%02d]: 0x%x, arg: 0x%x\n",
0700 i, (unsigned int)priv->isrs[i].handler,
0701 (unsigned int)priv->isrs[i].arg);
0702 }
0703 }
0704 #endif
0705 }
0706
0707 void gr_rasta_spw_router_print(int options)
0708 {
0709 struct pci_drv_info *drv = &gr_rasta_spw_router_info;
0710 struct drvmgr_dev *dev;
0711
0712 dev = drv->general.dev;
0713 while(dev) {
0714 gr_rasta_spw_router_print_dev(dev, options);
0715 dev = dev->next_in_drv;
0716 }
0717 }