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