File indexing completed on 2025-05-11 08:24:07
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 #include <bsp.h>
0031 #include <rtems/libio.h>
0032 #include <stdlib.h>
0033 #include <stdio.h>
0034 #include <string.h>
0035 #include <assert.h>
0036 #include <ctype.h>
0037 #include <rtems/bspIo.h>
0038
0039 #include <drvmgr/drvmgr.h>
0040 #include <grlib/ambapp.h>
0041 #include <grlib/ambapp_bus.h>
0042 #include <grlib/grtm.h>
0043
0044 #include <grlib/grlib_impl.h>
0045
0046
0047
0048
0049
0050
0051 #include <grlib/debug_defs.h>
0052
0053
0054 struct grtm_regs {
0055 volatile unsigned int dma_ctrl;
0056 volatile unsigned int dma_status;
0057 volatile unsigned int dma_len;
0058 volatile unsigned int dma_bd;
0059
0060 volatile unsigned int dma_cfg;
0061 volatile unsigned int revision;
0062
0063 int unused0[(0x80-0x18)/4];
0064
0065 volatile unsigned int ctrl;
0066 volatile unsigned int status;
0067 volatile unsigned int cfg;
0068 volatile unsigned int size;
0069
0070 volatile unsigned int phy;
0071 volatile unsigned int code;
0072 volatile unsigned int asmr;
0073
0074 int unused1;
0075
0076 volatile unsigned int all_frm;
0077 volatile unsigned int mst_frm;
0078 volatile unsigned int idle_frm;
0079
0080 int unused2[(0xc0-0xac)/4];
0081
0082 volatile unsigned int fsh[4];
0083
0084 volatile unsigned int ocf;
0085 };
0086
0087
0088 #define GRTM_DMA_CTRL_EN_BIT 0
0089 #define GRTM_DMA_CTRL_IE_BIT 1
0090 #define GRTM_DMA_CTRL_TXRST_BIT 2
0091 #define GRTM_DMA_CTRL_RST_BIT 3
0092 #define GRTM_DMA_CTRL_TFIE_BIT 4
0093
0094 #define GRTM_DMA_CTRL_EN (1<<GRTM_DMA_CTRL_EN_BIT)
0095 #define GRTM_DMA_CTRL_IE (1<<GRTM_DMA_CTRL_IE_BIT)
0096 #define GRTM_DMA_CTRL_TXRST (1<<GRTM_DMA_CTRL_TXRST_BIT)
0097 #define GRTM_DMA_CTRL_RST (1<<GRTM_DMA_CTRL_RST_BIT)
0098 #define GRTM_DMA_CTRL_TFIE (1<<GRTM_DMA_CTRL_TFIE_BIT)
0099
0100
0101 #define GRTM_DMA_STS_TE_BIT 0
0102 #define GRTM_DMA_STS_TI_BIT 1
0103 #define GRTM_DMA_STS_TA_BIT 2
0104 #define GRTM_DMA_STS_TFF_BIT 3
0105 #define GRTM_DMA_STS_TFS_BIT 4
0106
0107 #define GRTM_DMA_STS_TE (1<<GRTM_DMA_STS_TE_BIT)
0108 #define GRTM_DMA_STS_TI (1<<GRTM_DMA_STS_TI_BIT)
0109 #define GRTM_DMA_STS_TA (1<<GRTM_DMA_STS_TA_BIT)
0110 #define GRTM_DMA_STS_TFF (1<<GRTM_DMA_STS_TFF_BIT)
0111 #define GRTM_DMA_STS_TFS (1<<GRTM_DMA_STS_TFS_BIT)
0112 #define GRTM_DMA_STS_ALL 0x1f
0113
0114
0115 #define GRTM_DMA_LEN_LEN_BIT 0
0116 #define GRTM_DMA_LEN_LIM_BIT 16
0117
0118 #define GRTM_DMA_LEN_LEN (0x7ff<<GRTM_DMA_LEN_LEN_BIT)
0119 #define GRTM_DMA_LEN_LIM (0x3ff<<GRTM_DMA_LEN_LIM_BIT)
0120
0121
0122 #define GRTM_DMA_BD_INDEX_BIT 0
0123 #define GRTM_DMA_BD_BASE_BIT 10
0124
0125 #define GRTM_DMA_BD_INDEX (0x3ff<<GRTM_DMA_BD_INDEX_BIT)
0126 #define GRTM_DMA_BD_BASE (0xfffffc<<GRTM_DMA_BD_BASE_BIT)
0127
0128
0129 #define GRTM_DMA_CFG_BLKSZ_BIT 0
0130 #define GRTM_DMA_CFG_FIFOSZ_BIT 16
0131
0132 #define GRTM_DMA_CFG_BLKSZ (0xffff<<GRTM_DMA_CFG_BLKSZ_BIT)
0133 #define GRTM_DMA_CFG_FIFOSZ (0xffff<<GRTM_DMA_CFG_FIFOSZ_BIT)
0134
0135
0136 #define GRTM_CTRL_EN_BIT 0
0137
0138 #define GRTM_CTRL_EN (1<<GRTM_CTRL_EN_BIT)
0139
0140
0141
0142
0143 #define GRTM_CFG_SC_BIT 0
0144 #define GRTM_CFG_SP_BIT 1
0145 #define GRTM_CFG_CE_BIT 2
0146 #define GRTM_CFG_NRZ_BIT 3
0147 #define GRTM_CFG_PSR_BIT 4
0148 #define GRTM_CFG_TE_BIT 5
0149 #define GRTM_CFG_RSDEP_BIT 6
0150 #define GRTM_CFG_RS_BIT 9
0151 #define GRTM_CFG_AASM_BIT 11
0152 #define GRTM_CFG_FECF_BIT 12
0153 #define GRTM_CFG_OCF_BIT 13
0154 #define GRTM_CFG_EVC_BIT 14
0155 #define GRTM_CFG_IDLE_BIT 15
0156 #define GRTM_CFG_FSH_BIT 16
0157 #define GRTM_CFG_MCG_BIT 17
0158 #define GRTM_CFG_IZ_BIT 18
0159 #define GRTM_CFG_FHEC_BIT 19
0160 #define GRTM_CFG_AOS_BIT 20
0161 #define GRTM_CFG_CIF_BIT 21
0162 #define GRTM_CFG_OCFB_BIT 22
0163
0164 #define GRTM_CFG_SC (1<<GRTM_CFG_SC_BIT)
0165 #define GRTM_CFG_SP (1<<GRTM_CFG_SP_BIT)
0166 #define GRTM_CFG_CE (1<<GRTM_CFG_CE_BIT)
0167 #define GRTM_CFG_NRZ (1<<GRTM_CFG_NRZ_BIT)
0168 #define GRTM_CFG_PSR (1<<GRTM_CFG_PSR_BIT)
0169 #define GRTM_CFG_TE (1<<GRTM_CFG_TE_BIT)
0170 #define GRTM_CFG_RSDEP (0x7<<GRTM_CFG_RSDEP_BIT)
0171 #define GRTM_CFG_RS (0x3<<GRTM_CFG_RS_BIT)
0172 #define GRTM_CFG_AASM (1<<GRTM_CFG_AASM_BIT)
0173 #define GRTM_CFG_FECF (1<<GRTM_CFG_FECF_BIT)
0174 #define GRTM_CFG_OCF (1<<GRTM_CFG_OCF_BIT)
0175 #define GRTM_CFG_EVC (1<<GRTM_CFG_EVC_BIT)
0176 #define GRTM_CFG_IDLE (1<<GRTM_CFG_IDLE_BIT)
0177 #define GRTM_CFG_FSH (1<<GRTM_CFG_FSH_BIT)
0178 #define GRTM_CFG_MCG (1<<GRTM_CFG_MCG_BIT)
0179 #define GRTM_CFG_IZ (1<<GRTM_CFG_IZ_BIT)
0180 #define GRTM_CFG_FHEC (1<<GRTM_CFG_FHEC_BIT)
0181 #define GRTM_CFG_AOS (1<<GRTM_CFG_AOS_BIT)
0182 #define GRTM_CFG_CIF (1<<GRTM_CFG_CIF_BIT)
0183 #define GRTM_CFG_OCFB (1<<GRTM_CFG_OCFB_BIT)
0184
0185
0186 #define GRTM_SIZE_BLKSZ_BIT 0
0187 #define GRTM_SIZE_FIFOSZ_BIT 8
0188 #define GRTM_SIZE_LEN_BIT 20
0189
0190 #define GRTM_SIZE_BLKSZ (0xff<<GRTM_SIZE_BLKSZ_BIT)
0191 #define GRTM_SIZE_FIFOSZ (0xfff<<GRTM_SIZE_FIFOSZ_BIT)
0192 #define GRTM_SIZE_LEN (0xfff<<GRTM_SIZE_LEN_BIT)
0193
0194
0195 #define GRTM_PHY_SUB_BIT 0
0196 #define GRTM_PHY_SCF_BIT 15
0197 #define GRTM_PHY_SYM_BIT 16
0198 #define GRTM_PHY_SF_BIT 31
0199
0200 #define GRTM_PHY_SUB (0x7fff<<GRTM_PHY_SUB_BIT)
0201 #define GRTM_PHY_SCF (1<<GRTM_PHY_SCF_BIT)
0202 #define GRTM_PHY_SYM (0x7fff<<GRTM_PHY_SYM_BIT)
0203 #define GRTM_PHY_SF (1<<GRTM_PHY_SF_BIT)
0204
0205
0206 #define GRTM_CODE_SC_BIT 0
0207 #define GRTM_CODE_SP_BIT 1
0208 #define GRTM_CODE_CERATE_BIT 2
0209 #define GRTM_CODE_CE_BIT 5
0210 #define GRTM_CODE_NRZ_BIT 6
0211 #define GRTM_CODE_PSR_BIT 7
0212 #define GRTM_CODE_RS8_BIT 11
0213 #define GRTM_CODE_RSDEP_BIT 12
0214 #define GRTM_CODE_RS_BIT 15
0215 #define GRTM_CODE_AASM_BIT 16
0216 #define GRTM_CODE_CSEL_BIT 17
0217
0218 #define GRTM_CODE_SC (1<<GRTM_CODE_SC_BIT)
0219 #define GRTM_CODE_SP (1<<GRTM_CODE_SP_BIT)
0220 #define GRTM_CODE_CERATE (0x7<<GRTM_CODE_CERATE_BIT)
0221 #define GRTM_CODE_CE (1<<GRTM_CODE_CE_BIT)
0222 #define GRTM_CODE_NRZ (1<<GRTM_CODE_NRZ_BIT)
0223 #define GRTM_CODE_PSR (1<<GRTM_CODE_PSR_BIT)
0224 #define GRTM_CODE_RS8 (1<<GRTM_CODE_RS8_BIT)
0225 #define GRTM_CODE_RSDEP (0x7<<GRTM_CODE_RSDEP_BIT)
0226 #define GRTM_CODE_RS (1<<GRTM_CODE_RS_BIT)
0227 #define GRTM_CODE_AASM (1<<GRTM_CODE_AASM_BIT)
0228 #define GRTM_CODE_CSEL (0x3<<GRTM_CODE_CSEL_BIT)
0229
0230
0231 #define GRTM_ASM_BIT 0
0232
0233 #define GRTM_ASM 0xffffffff
0234
0235
0236 #define GRTM_ALL_LEN_BIT 0
0237 #define GRTM_ALL_VER_BIT 12
0238 #define GRTM_ALL_FHEC_BIT 14
0239 #define GRTM_ALL_FECF_BIT 15
0240 #define GRTM_ALL_IZ_BIT 16
0241 #define GRTM_ALL_IZLEN_BIT 17
0242
0243 #define GRTM_ALL_LEN (0x7ff<<GRTM_ALL_LEN_BIT)
0244 #define GRTM_ALL_VER (0x3<<GRTM_ALL_VER_BIT)
0245 #define GRTM_ALL_FHEC (1<<GRTM_ALL_FHEC_BIT)
0246 #define GRTM_ALL_FECF (1<<GRTM_ALL_FECF_BIT)
0247 #define GRTM_ALL_IZ (1<<GRTM_ALL_IZ_BIT)
0248 #define GRTM_ALL_IZLEN (0x1f<<GRTM_ALL_IZLEN_BIT)
0249
0250
0251 #define GRTM_MST_OW_BIT 0
0252 #define GRTM_MST_OCF_BIT 1
0253 #define GRTM_MST_FSH_BIT 2
0254 #define GRTM_MST_MC_BIT 3
0255 #define GRTM_MST_MCCNTR_BIT 24
0256
0257 #define GRTM_MST_OW (1<<GRTM_MST_OW_BIT)
0258 #define GRTM_MST_OCF (1<<GRTM_MST_OCF_BIT)
0259 #define GRTM_MST_FSH (1<<GRTM_MST_FSH_BIT)
0260 #define GRTM_MST_MC (0xff<<GRTM_MST_MC_BIT)
0261
0262
0263 #define GRTM_IDLE_SCID_BIT 0
0264 #define GRTM_IDLE_VCID_BIT 10
0265 #define GRTM_IDLE_MC_BIT 16
0266 #define GRTM_IDLE_VCC_BIT 17
0267 #define GRTM_IDLE_FSH_BIT 18
0268 #define GRTM_IDLE_EVC_BIT 19
0269 #define GRTM_IDLE_OCF_BIT 20
0270 #define GRTM_IDLE_IDLE_BIT 21
0271 #define GRTM_IDLE_MCCNTR_BIT 24
0272
0273 #define GRTM_IDLE_SCID (0x3ff<<GRTM_IDLE_SCID_BIT)
0274 #define GRTM_IDLE_VCID (0x3f<<GRTM_IDLE_VCID_BIT)
0275 #define GRTM_IDLE_MC (1<<GRTM_IDLE_MC_BIT)
0276 #define GRTM_IDLE_VCC (1<<GRTM_IDLE_VCC_BIT)
0277 #define GRTM_IDLE_FSH (1<<GRTM_IDLE_FSH_BIT)
0278 #define GRTM_IDLE_EVC (1<<GRTM_IDLE_EVC_BIT)
0279 #define GRTM_IDLE_OCF (1<<GRTM_IDLE_OCF_BIT)
0280 #define GRTM_IDLE_IDLE (1<<GRTM_IDLE_IDLE_BIT)
0281 #define GRTM_IDLE_MCCNTR (0xff<<GRTM_IDLE_MCCNTR_BIT)
0282
0283
0284 #define GRTM_FSH_DATA_BIT 0
0285
0286 #define GRTM_FSH_DATA 0xffffffff
0287
0288
0289
0290 #define GRTM_OCF_CLCW_BIT 0
0291
0292 #define GRTM_OCF_CLCW 0xffffffff
0293
0294
0295
0296 #define GRTM_REV0_DMA_CTRL_TXRDY_BIT 5
0297 #define GRTM_REV0_DMA_CTRL_TXRDY (1<<GRTM_REV0_DMA_CTRL_TXRDY_BIT)
0298
0299
0300 #define GRTM_REV1_DMA_STS_TXRDY_BIT 6
0301 #define GRTM_REV1_DMA_STS_TXSTAT_BIT 7
0302 #define GRTM_REV1_DMA_STS_TXRDY (1<<GRTM_REV1_DMA_STS_TXRDY_BIT)
0303 #define GRTM_REV1_DMA_STS_TXSTAT (1<<GRTM_REV1_DMA_STS_TXSTAT_BIT)
0304
0305 #define GRTM_REV1_REV_SREV_BIT 0
0306 #define GRTM_REV1_REV_MREV_BIT 8
0307 #define GRTM_REV1_REV_TIRQ_BIT 16
0308 #define GRTM_REV1_REV_SREV (0xff<<GRTM_REV1_REV_SREV_BIT)
0309 #define GRTM_REV1_REV_MREV (0xff<<GRTM_REV1_REV_MREV_BIT)
0310 #define GRTM_REV1_REV_TIRQ (1<<GRTM_REV1_REV_TIRQ_BIT)
0311
0312
0313
0314 struct grtm_bd {
0315 volatile unsigned int ctrl;
0316 unsigned int address;
0317 };
0318
0319 #define GRTM_BD_EN_BIT 0
0320 #define GRTM_BD_WR_BIT 1
0321 #define GRTM_BD_IE_BIT 2
0322 #define GRTM_BD_FECFB_BIT 3
0323 #define GRTM_BD_IZB_BIT 4
0324 #define GRTM_BD_FHECB_BIT 5
0325 #define GRTM_BD_OCFB_BIT 6
0326 #define GRTM_BD_FSHB_BIT 7
0327 #define GRTM_BD_MCB_BIT 8
0328 #define GRTM_BD_VCE_BIT 9
0329 #define GRTM_BD_TS_BIT 14
0330 #define GRTM_BD_UE_BIT 15
0331
0332 #define GRTM_BD_EN (1<<GRTM_BD_EN_BIT)
0333 #define GRTM_BD_WR (1<<GRTM_BD_WR_BIT)
0334 #define GRTM_BD_IE (1<<GRTM_BD_IE_BIT)
0335 #define GRTM_BD_FECFB (1<<GRTM_BD_FECFB_BIT)
0336 #define GRTM_BD_IZB (1<<GRTM_BD_IZB_BIT)
0337 #define GRTM_BD_FHECB (1<<GRTM_BD_FHECB_BIT)
0338 #define GRTM_BD_OCFB (1<<GRTM_BD_OCFB_BIT)
0339 #define GRTM_BD_FSHB (1<<GRTM_BD_FSHB_BIT)
0340 #define GRTM_BD_MCB (1<<GRTM_BD_MCB_BIT)
0341 #define GRTM_BD_VCE (1<<GRTM_BD_VCE_BIT)
0342 #define GRTM_BD_TS (1<<GRTM_BD_TS_BIT)
0343 #define GRTM_BD_UE (1<<GRTM_BD_UE_BIT)
0344
0345
0346
0347 #define READ_REG(address) (*(volatile unsigned int *)address)
0348
0349
0350 static rtems_device_driver grtm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0351 static rtems_device_driver grtm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0352 static rtems_device_driver grtm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0353 static rtems_device_driver grtm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0354 static rtems_device_driver grtm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0355 static rtems_device_driver grtm_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0356
0357 #define GRTM_DRIVER_TABLE_ENTRY { grtm_initialize, grtm_open, grtm_close, grtm_read, grtm_write, grtm_ioctl }
0358
0359 static rtems_driver_address_table grtm_driver = GRTM_DRIVER_TABLE_ENTRY;
0360
0361
0362 struct grtm_ring {
0363 struct grtm_ring *next;
0364 struct grtm_bd *bd;
0365 struct grtm_frame *frm;
0366 };
0367
0368 struct grtm_priv {
0369 struct drvmgr_dev *dev;
0370 char devName[52];
0371 struct grtm_regs *regs;
0372 int irq;
0373 int minor;
0374 int subrev;
0375 SPIN_DECLARE(devlock);
0376
0377 int open;
0378 int running;
0379
0380 struct grtm_bd *bds;
0381 void *_bds;
0382
0383
0384 int enable_cnt_curr;
0385 volatile int handling_transmission;
0386
0387 struct grtm_ring *_ring;
0388 struct grtm_ring *ring;
0389 struct grtm_ring *ring_end;
0390
0391
0392
0393
0394 struct grtm_list ready;
0395 struct grtm_list scheduled;
0396 struct grtm_list sent;
0397
0398
0399 int ready_cnt;
0400 int scheduled_cnt;
0401 int sent_cnt;
0402
0403 struct grtm_ioc_hw hw_avail;
0404 struct grtm_ioc_config config;
0405 struct grtm_ioc_stats stats;
0406
0407 rtems_id sem_tx;
0408 };
0409
0410
0411 static void *grtm_memalign(unsigned int boundary, unsigned int length, void *realbuf);
0412 static void grtm_hw_reset(struct grtm_priv *pDev);
0413 static void grtm_interrupt(void *arg);
0414
0415
0416 static rtems_id grtm_dev_sem;
0417 static int grtm_driver_io_registered = 0;
0418 static rtems_device_major_number grtm_driver_io_major = 0;
0419
0420
0421
0422
0423 static int grtm_register_io(rtems_device_major_number *m);
0424 static int grtm_device_init(struct grtm_priv *pDev);
0425
0426 static int grtm_init2(struct drvmgr_dev *dev);
0427 static int grtm_init3(struct drvmgr_dev *dev);
0428
0429 static struct drvmgr_drv_ops grtm_ops =
0430 {
0431 {NULL, grtm_init2, grtm_init3, NULL},
0432 NULL,
0433 NULL
0434 };
0435
0436 static struct amba_dev_id grtm_ids[] =
0437 {
0438 {VENDOR_GAISLER, GAISLER_GRTM},
0439 {0, 0}
0440 };
0441
0442 static struct amba_drv_info grtm_drv_info =
0443 {
0444 {
0445 DRVMGR_OBJ_DRV,
0446 NULL,
0447 NULL,
0448 DRIVER_AMBAPP_GAISLER_GRTM_ID,
0449 "GRTM_DRV",
0450 DRVMGR_BUS_TYPE_AMBAPP,
0451 &grtm_ops,
0452 NULL,
0453 0,
0454 0,
0455 },
0456 &grtm_ids[0]
0457 };
0458
0459 void grtm_register_drv (void)
0460 {
0461 DBG("Registering GRTM driver\n");
0462 drvmgr_drv_register(&grtm_drv_info.general);
0463 }
0464
0465 static int grtm_init2(struct drvmgr_dev *dev)
0466 {
0467 struct grtm_priv *priv;
0468
0469 DBG("GRTM[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0470 priv = dev->priv = grlib_calloc(1, sizeof(*priv));
0471 if ( !priv )
0472 return DRVMGR_NOMEM;
0473 priv->dev = dev;
0474
0475
0476
0477 return DRVMGR_OK;
0478 }
0479
0480 static int grtm_init3(struct drvmgr_dev *dev)
0481 {
0482 struct grtm_priv *priv;
0483 char prefix[32];
0484 rtems_status_code status;
0485
0486 priv = dev->priv;
0487
0488
0489
0490 if ( grtm_driver_io_registered == 0) {
0491
0492 if ( grtm_register_io(&grtm_driver_io_major) ) {
0493
0494 dev->priv = NULL;
0495 return DRVMGR_FAIL;
0496 }
0497
0498 grtm_driver_io_registered = 1;
0499 }
0500
0501
0502
0503
0504 if ( grtm_device_init(priv) ) {
0505 return DRVMGR_FAIL;
0506 }
0507
0508
0509 prefix[0] = '\0';
0510 if ( drvmgr_get_dev_prefix(dev, prefix) ) {
0511
0512
0513
0514 sprintf(priv->devName, "/dev/grtm%d", dev->minor_drv);
0515 } else {
0516
0517
0518
0519 sprintf(priv->devName, "/dev/%sgrtm%d", prefix, dev->minor_bus);
0520 }
0521
0522 SPIN_INIT(&priv->devlock, priv->devName);
0523
0524
0525 status = rtems_io_register_name(priv->devName, grtm_driver_io_major, dev->minor_drv);
0526 if (status != RTEMS_SUCCESSFUL) {
0527 return DRVMGR_FAIL;
0528 }
0529
0530 return DRVMGR_OK;
0531 }
0532
0533
0534
0535 static int grtm_register_io(rtems_device_major_number *m)
0536 {
0537 rtems_status_code r;
0538
0539 if ((r = rtems_io_register_driver(0, &grtm_driver, m)) == RTEMS_SUCCESSFUL) {
0540 DBG("GRTM driver successfully registered, major: %d\n", *m);
0541 } else {
0542 switch(r) {
0543 case RTEMS_TOO_MANY:
0544 printk("GRTM rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
0545 return -1;
0546 case RTEMS_INVALID_NUMBER:
0547 printk("GRTM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
0548 return -1;
0549 case RTEMS_RESOURCE_IN_USE:
0550 printk("GRTM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
0551 return -1;
0552 default:
0553 printk("GRTM rtems_io_register_driver failed\n");
0554 return -1;
0555 }
0556 }
0557 return 0;
0558 }
0559
0560 static int grtm_device_init(struct grtm_priv *pDev)
0561 {
0562 struct amba_dev_info *ambadev;
0563 struct ambapp_core *pnpinfo;
0564 union drvmgr_key_value *value;
0565
0566
0567 ambadev = (struct amba_dev_info *)pDev->dev->businfo;
0568 if ( ambadev == NULL ) {
0569 return -1;
0570 }
0571 pnpinfo = &ambadev->info;
0572 pDev->irq = pnpinfo->irq;
0573 pDev->regs = (struct grtm_regs *)pnpinfo->apb_slv->start;
0574 pDev->minor = pDev->dev->minor_drv;
0575 pDev->open = 0;
0576 pDev->running = 0;
0577
0578
0579 if ( rtems_semaphore_create(rtems_build_name('G', 'R', 'M', '0' + pDev->minor),
0580 0,
0581 RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
0582 RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
0583 0,
0584 &pDev->sem_tx) != RTEMS_SUCCESSFUL ) {
0585 return -1;
0586 }
0587
0588
0589
0590
0591 value = drvmgr_dev_key_get(pDev->dev, "bdTabAdr", DRVMGR_KT_POINTER);
0592 if ( value ) {
0593 pDev->bds = (struct grtm_bd *)value->ptr;
0594 pDev->_bds = (void *)value->ptr;
0595 } else {
0596 pDev->bds = (struct grtm_bd *)grtm_memalign(0x400, 0x400, &pDev->_bds);
0597 }
0598 if ( !pDev->bds ) {
0599 DBG("GRTM: Failed to allocate descriptor table\n");
0600 return -1;
0601 }
0602 memset(pDev->bds, 0, 0x400);
0603
0604 pDev->_ring = grlib_malloc(sizeof(*pDev->_ring) * 128);
0605 if ( !pDev->_ring ) {
0606 return -1;
0607 }
0608
0609
0610 grtm_hw_reset(pDev);
0611
0612
0613 pDev->subrev = (READ_REG(&pDev->regs->revision) & GRTM_REV1_REV_SREV)
0614 >> GRTM_REV1_REV_SREV_BIT;
0615
0616 return 0;
0617 }
0618
0619
0620 static inline void grtm_list_clr(struct grtm_list *list)
0621 {
0622 list->head = NULL;
0623 list->tail = NULL;
0624 }
0625
0626 static void grtm_hw_reset(struct grtm_priv *pDev)
0627 {
0628
0629 pDev->regs->dma_ctrl = GRTM_DMA_CTRL_RST;
0630 }
0631
0632 static void grtm_hw_get_implementation(struct grtm_priv *pDev, struct grtm_ioc_hw *hwcfg)
0633 {
0634 unsigned int cfg = READ_REG(&pDev->regs->cfg);
0635
0636 hwcfg->cs = (cfg & GRTM_CFG_SC) ? 1:0;
0637 hwcfg->sp = (cfg & GRTM_CFG_SP) ? 1:0;
0638 hwcfg->ce = (cfg & GRTM_CFG_CE) ? 1:0;
0639 hwcfg->nrz = (cfg & GRTM_CFG_NRZ) ? 1:0;
0640 hwcfg->psr = (cfg & GRTM_CFG_PSR) ? 1:0;
0641 hwcfg->te = (cfg & GRTM_CFG_TE) ? 1:0;
0642 hwcfg->rsdep = (cfg & GRTM_CFG_RSDEP)>>GRTM_CFG_RSDEP_BIT;
0643 hwcfg->rs = (cfg & GRTM_CFG_RS)>>GRTM_CFG_RS_BIT;
0644 hwcfg->aasm = (cfg & GRTM_CFG_AASM) ? 1:0;
0645 hwcfg->fecf = (cfg & GRTM_CFG_FECF) ? 1:0;
0646 hwcfg->ocf = (cfg & GRTM_CFG_OCF) ? 1:0;
0647 hwcfg->evc = (cfg & GRTM_CFG_EVC) ? 1:0;
0648 hwcfg->idle = (cfg & GRTM_CFG_IDLE) ? 1:0;
0649 hwcfg->fsh = (cfg & GRTM_CFG_FSH) ? 1:0;
0650 hwcfg->mcg = (cfg & GRTM_CFG_MCG) ? 1:0;
0651 hwcfg->iz = (cfg & GRTM_CFG_IZ) ? 1:0;
0652 hwcfg->fhec = (cfg & GRTM_CFG_FHEC) ? 1:0;
0653 hwcfg->aos = (cfg & GRTM_CFG_AOS) ? 1:0;
0654 hwcfg->cif = (cfg & GRTM_CFG_CIF) ? 1:0;
0655 hwcfg->ocfb = (cfg & GRTM_CFG_OCFB) ? 1:0;
0656
0657 cfg = READ_REG(&pDev->regs->dma_cfg);
0658 hwcfg->blk_size = (cfg & GRTM_DMA_CFG_BLKSZ) >> GRTM_DMA_CFG_BLKSZ_BIT;
0659 hwcfg->fifo_size= (cfg & GRTM_DMA_CFG_FIFOSZ) >> GRTM_DMA_CFG_FIFOSZ_BIT;
0660 }
0661
0662
0663
0664 static void grtm_hw_get_default_modes(struct grtm_ioc_config *cfg, struct grtm_ioc_hw *hwcfg)
0665 {
0666 cfg->mode = GRTM_MODE_TM;
0667 cfg->frame_length = 223;
0668 cfg->limit = 0;
0669 cfg->as_marker = 0x1ACFFC1D;
0670
0671
0672 cfg->phy_subrate = 1;
0673 cfg->phy_symbolrate = 1;
0674 cfg->phy_opts = 0;
0675
0676
0677 cfg->code_rsdep = 1;
0678 cfg->code_ce_rate = 0;
0679 cfg->code_csel = 0;
0680 cfg->code_opts = 0;
0681
0682
0683 cfg->all_izlen = 0;
0684 cfg->all_opts = GRTM_IOC_ALL_FECF;
0685
0686
0687 if ( hwcfg->mcg ) {
0688 cfg->mf_opts = GRTM_IOC_MF_MC;
0689 } else {
0690 cfg->mf_opts = 0;
0691 }
0692
0693
0694 cfg->idle_scid = 0;
0695 cfg->idle_vcid = 0;
0696 if ( hwcfg->idle ) {
0697 cfg->idle_opts = GRTM_IOC_IDLE_EN;
0698 } else {
0699 cfg->idle_opts = 0;
0700 }
0701
0702
0703 cfg->blocking = 0;
0704 cfg->enable_cnt = 16;
0705 cfg->isr_desc_proc = 1;
0706 cfg->timeout = RTEMS_NO_TIMEOUT;
0707
0708 }
0709
0710 static void *grtm_memalign(unsigned int boundary, unsigned int length, void *realbuf)
0711 {
0712 *(int *)realbuf = (int)grlib_malloc(length+boundary);
0713 DBG("GRTM: Alloced %d (0x%x) bytes, requested: %d\n",length+boundary,length+boundary,length);
0714 return (void *)(((*(unsigned int *)realbuf)+boundary) & ~(boundary-1));
0715 }
0716
0717 static int grtm_hw_set_config(struct grtm_priv *pDev, struct grtm_ioc_config *cfg, struct grtm_ioc_hw *hwcfg)
0718 {
0719 struct grtm_regs *regs = pDev->regs;
0720 unsigned int tmp;
0721 unsigned int limit;
0722
0723 if ( cfg->limit == 0 ) {
0724
0725 if ( cfg->frame_length > hwcfg->blk_size ) {
0726 limit = hwcfg->blk_size*2;
0727 } else {
0728 limit = cfg->frame_length;
0729 }
0730 } else {
0731
0732 limit = cfg->limit;
0733 }
0734
0735
0736 regs->dma_len = (((limit-1) << GRTM_DMA_LEN_LIM_BIT) & GRTM_DMA_LEN_LIM)|
0737 (((cfg->frame_length-1) << GRTM_DMA_LEN_LEN_BIT) & GRTM_DMA_LEN_LEN);
0738
0739
0740 tmp = (cfg->phy_opts & (GRTM_IOC_PHY_SCF|GRTM_IOC_PHY_SF)) |
0741 (((cfg->phy_symbolrate-1)<<GRTM_PHY_SYM_BIT) & GRTM_PHY_SYM) | (((cfg->phy_subrate-1)<<GRTM_PHY_SUB_BIT) & GRTM_PHY_SUB);
0742 regs->phy = tmp;
0743
0744
0745 tmp = (cfg->code_opts & GRTM_IOC_CODE_ALL) | ((cfg->code_csel<<GRTM_CODE_CSEL_BIT) & GRTM_CODE_CSEL) |
0746 (((cfg->code_rsdep-1)<<GRTM_CODE_RSDEP_BIT) & GRTM_CODE_RSDEP) | ((cfg->code_ce_rate<<GRTM_CODE_CERATE_BIT) & GRTM_CODE_CERATE);
0747 regs->code = tmp;
0748
0749
0750 regs->asmr = cfg->as_marker;
0751
0752
0753 tmp = ((cfg->all_opts & GRTM_IOC_ALL_ALL)<<14) |
0754 ((cfg->all_izlen<<GRTM_ALL_IZLEN_BIT) & GRTM_ALL_IZLEN) |
0755 ((cfg->mode<<GRTM_ALL_VER_BIT) & GRTM_ALL_VER);
0756 regs->all_frm = tmp;
0757
0758
0759 regs->mst_frm = cfg->mf_opts & GRTM_IOC_MF_ALL;
0760
0761
0762 tmp = ((cfg->idle_opts & GRTM_IOC_IDLE_ALL) << 16) |
0763 ((cfg->idle_vcid << GRTM_IDLE_VCID_BIT) & GRTM_IDLE_VCID) |
0764 ((cfg->idle_scid << GRTM_IDLE_SCID_BIT) & GRTM_IDLE_SCID);
0765 regs->idle_frm = tmp;
0766
0767 return 0;
0768 }
0769
0770 static int grtm_start(struct grtm_priv *pDev)
0771 {
0772 struct grtm_regs *regs = pDev->regs;
0773 int i;
0774 struct grtm_ioc_config *cfg = &pDev->config;
0775 unsigned int txrdy;
0776
0777
0778 memset(pDev->bds,0,0x400);
0779
0780
0781 memset(&pDev->stats,0,sizeof(struct grtm_ioc_stats));
0782
0783
0784 memset(pDev->_ring,0,sizeof(struct grtm_ring)*128);
0785 for(i=0;i<127;i++){
0786 pDev->_ring[i].next = &pDev->_ring[i+1];
0787 pDev->_ring[i].bd = &pDev->bds[i];
0788 pDev->_ring[i].frm = NULL;
0789 }
0790 pDev->_ring[127].next = &pDev->_ring[0];
0791 pDev->_ring[127].bd = &pDev->bds[127];
0792 pDev->_ring[127].frm = NULL;
0793
0794 pDev->ring = &pDev->_ring[0];
0795 pDev->ring_end = &pDev->_ring[0];
0796
0797
0798 grtm_list_clr(&pDev->ready);
0799 grtm_list_clr(&pDev->scheduled);
0800 grtm_list_clr(&pDev->sent);
0801
0802
0803 pDev->handling_transmission = 0;
0804
0805
0806 regs->dma_ctrl = GRTM_DMA_CTRL_TXRST;
0807 regs->dma_ctrl = 0;
0808
0809
0810 regs->dma_status = GRTM_DMA_STS_ALL;
0811
0812
0813 drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA, (void *)pDev->bds,
0814 (void **)®s->dma_bd, 0x400);
0815
0816
0817 if ( grtm_hw_set_config(pDev, cfg, &pDev->hw_avail) ) {
0818 return RTEMS_IO_ERROR;
0819 }
0820
0821
0822 regs->ctrl = GRTM_CTRL_EN;
0823
0824
0825 i=1000;
0826 while( i > 0 ) {
0827 asm volatile ("nop"::);
0828 i--;
0829 }
0830
0831
0832 i = 1000000;
0833 do {
0834
0835 if ( pDev->subrev == 0 ) {
0836 txrdy = READ_REG(®s->dma_ctrl) &
0837 GRTM_REV0_DMA_CTRL_TXRDY;
0838 } else {
0839 txrdy = READ_REG(®s->dma_status) &
0840 GRTM_REV1_DMA_STS_TXRDY;
0841 }
0842 if (txrdy != 0)
0843 break;
0844
0845 asm volatile ("nop"::);
0846 } while ( --i > 0 );
0847 if ( i == 0 ) {
0848
0849 DBG("GRTM: start: Reseting transmitter failed (%d)\n",i);
0850 return RTEMS_IO_ERROR;
0851 }
0852 DBG("GRTM: reset time %d\n",i);
0853
0854
0855
0856
0857
0858
0859 pDev->running = 1;
0860
0861
0862 regs->dma_ctrl = GRTM_DMA_CTRL_IE;
0863
0864 DBG("GRTM: STARTED\n");
0865
0866 return RTEMS_SUCCESSFUL;
0867 }
0868
0869 static void grtm_stop(struct grtm_priv *pDev)
0870 {
0871 struct grtm_regs *regs = pDev->regs;
0872
0873
0874 regs->dma_ctrl = 0;
0875
0876
0877 regs->dma_status = GRTM_DMA_STS_ALL;
0878
0879 DBG("GRTM: STOPPED\n");
0880
0881
0882 rtems_semaphore_flush(pDev->sem_tx);
0883 }
0884
0885 static rtems_device_driver grtm_open(
0886 rtems_device_major_number major,
0887 rtems_device_minor_number minor,
0888 void *arg)
0889 {
0890 struct grtm_priv *pDev;
0891 struct drvmgr_dev *dev;
0892
0893 FUNCDBG();
0894
0895 if ( drvmgr_get_dev(&grtm_drv_info.general, minor, &dev) ) {
0896 DBG("Wrong minor %d\n", minor);
0897 return RTEMS_INVALID_NUMBER;
0898 }
0899 pDev = (struct grtm_priv *)dev->priv;
0900
0901
0902 if ( rtems_semaphore_obtain(grtm_dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL ){
0903 return RTEMS_INTERNAL_ERROR;
0904 }
0905
0906
0907 if ( pDev->open ){
0908 rtems_semaphore_release(grtm_dev_sem);
0909 return RTEMS_RESOURCE_IN_USE;
0910 }
0911
0912
0913 pDev->open = 1;
0914
0915 rtems_semaphore_release(grtm_dev_sem);
0916
0917 DBG("grtm_open: OPENED minor %d (pDev: 0x%x)\n",pDev->minor,(unsigned int)pDev);
0918
0919
0920 pDev->config.timeout = RTEMS_NO_TIMEOUT;
0921 pDev->config.blocking = 0;
0922
0923 pDev->running = 0;
0924
0925 memset(&pDev->config,0,sizeof(pDev->config));
0926
0927
0928
0929
0930 grtm_hw_get_implementation(pDev, &pDev->hw_avail);
0931
0932
0933 grtm_hw_get_default_modes(&pDev->config,&pDev->hw_avail);
0934
0935 return RTEMS_SUCCESSFUL;
0936 }
0937
0938 static rtems_device_driver grtm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0939 {
0940 struct grtm_priv *pDev;
0941 struct drvmgr_dev *dev;
0942
0943 FUNCDBG();
0944
0945 if ( drvmgr_get_dev(&grtm_drv_info.general, minor, &dev) ) {
0946 return RTEMS_INVALID_NUMBER;
0947 }
0948 pDev = (struct grtm_priv *)dev->priv;
0949
0950 if ( pDev->running ){
0951 drvmgr_interrupt_unregister(dev, 0, grtm_interrupt, pDev);
0952 grtm_stop(pDev);
0953 pDev->running = 0;
0954 }
0955
0956
0957 grtm_hw_reset(pDev);
0958
0959
0960 memset(pDev->bds, 0, 0x400);
0961
0962
0963 pDev->open = 0;
0964
0965 return RTEMS_SUCCESSFUL;
0966 }
0967
0968 static rtems_device_driver grtm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0969 {
0970 FUNCDBG();
0971 return RTEMS_NOT_IMPLEMENTED;
0972 }
0973
0974 static rtems_device_driver grtm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0975 {
0976 FUNCDBG();
0977 return RTEMS_NOT_IMPLEMENTED;
0978 }
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989 static int grtm_free_sent(struct grtm_priv *pDev)
0990 {
0991 struct grtm_ring *curr;
0992 struct grtm_frame *last_frm, *first_frm;
0993 int freed_frame_cnt=0;
0994 unsigned int ctrl;
0995
0996 curr = pDev->ring_end;
0997
0998
0999 if ( !curr->frm ){
1000
1001 return 0;
1002 }
1003
1004
1005
1006
1007
1008 first_frm = curr->frm;
1009
1010
1011
1012
1013 while ( curr->frm && !((ctrl=READ_REG(&curr->bd->ctrl)) & GRTM_BD_EN) ){
1014
1015
1016
1017
1018
1019 last_frm = curr->frm;
1020
1021
1022 last_frm->flags |= GRTM_FLAGS_SENT;
1023
1024
1025 pDev->stats.frames_sent++;
1026
1027
1028 if ( ctrl & GRTM_BD_UE ) {
1029 pDev->stats.err_underrun++;
1030 last_frm->flags |= GRRM_FLAGS_ERR;
1031 }
1032
1033 curr->frm = NULL;
1034
1035
1036 curr = curr->next;
1037 freed_frame_cnt++;
1038 }
1039
1040
1041
1042
1043 if ( freed_frame_cnt > 0 ){
1044
1045
1046 pDev->ring_end = curr;
1047
1048
1049 if ( pDev->scheduled.tail == last_frm ){
1050
1051 pDev->scheduled.head = NULL;
1052 pDev->scheduled.tail = NULL;
1053 }else{
1054 pDev->scheduled.head = last_frm->next;
1055 }
1056 last_frm->next = NULL;
1057
1058
1059
1060
1061 if ( !pDev->sent.head ){
1062
1063 pDev->sent.head = first_frm;
1064 pDev->sent.tail = last_frm;
1065 }else{
1066 pDev->sent.tail->next = first_frm;
1067 pDev->sent.tail = last_frm;
1068 }
1069 }
1070 return freed_frame_cnt;
1071 }
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081 static int grtm_schedule_ready(struct grtm_priv *pDev)
1082 {
1083 int cnt;
1084 unsigned int ctrl, dmactrl;
1085 struct grtm_ring *curr_bd;
1086 struct grtm_frame *curr_frm, *last_frm;
1087
1088 if ( !pDev->ready.head ){
1089 return 0;
1090 }
1091
1092 cnt=0;
1093 curr_frm = pDev->ready.head;
1094 curr_bd = pDev->ring;
1095 while( !curr_bd->frm ){
1096
1097 curr_bd->frm = curr_frm;
1098
1099
1100
1101
1102
1103
1104 if ( curr_frm->flags & (GRTM_FLAGS_TRANSLATE|GRTM_FLAGS_TRANSLATE_AND_REMEMBER) ) {
1105
1106 drvmgr_translate(pDev->dev, CPUMEM_TO_DMA, (void *)curr_frm->payload, (void **)&curr_bd->bd->address);
1107 if ( curr_frm->flags & GRTM_FLAGS_TRANSLATE_AND_REMEMBER ) {
1108 if ( curr_frm->payload != (unsigned int *)curr_bd->bd->address ) {
1109
1110 curr_frm->flags &= ~GRTM_FLAGS_TRANSLATE_AND_REMEMBER;
1111 curr_frm->flags |= GRTM_FLAGS_TRANSLATE;
1112 } else {
1113
1114 curr_frm->flags &= ~(GRTM_FLAGS_TRANSLATE|GRTM_FLAGS_TRANSLATE_AND_REMEMBER);
1115 }
1116 }
1117 } else {
1118
1119 curr_bd->bd->address = (unsigned int)curr_frm->payload;
1120 }
1121
1122 ctrl = GRTM_BD_EN;
1123 if ( curr_bd->next == pDev->_ring ){
1124 ctrl |= GRTM_BD_WR;
1125 }
1126
1127 ctrl |= (curr_frm->flags & GRTM_FLAGS_MASK);
1128
1129
1130 if ( (--pDev->enable_cnt_curr) <= 0 ){
1131 if ( pDev->config.enable_cnt == 0 ){
1132 pDev->enable_cnt_curr = 0x3fffffff;
1133 }else{
1134 pDev->enable_cnt_curr = pDev->config.enable_cnt;
1135 ctrl |= GRTM_BD_IE;
1136 }
1137 }
1138
1139
1140 curr_bd->bd->ctrl = ctrl;
1141
1142 last_frm = curr_frm;
1143 curr_bd = curr_bd->next;
1144 cnt++;
1145
1146
1147 if ( curr_frm == pDev->ready.tail ){
1148
1149 curr_frm = NULL;
1150 break;
1151 }
1152 curr_frm = curr_frm->next;
1153 }
1154
1155
1156 if ( cnt > 0 ){
1157
1158 last_frm->next = NULL;
1159
1160
1161 if ( !pDev->scheduled.head ){
1162
1163 pDev->scheduled.head = pDev->ready.head;
1164 pDev->scheduled.tail = last_frm;
1165 }else{
1166 pDev->scheduled.tail->next = pDev->ready.head;
1167 pDev->scheduled.tail = last_frm;
1168 }
1169
1170
1171 pDev->ready.head = curr_frm;
1172 if ( !curr_frm ){
1173 pDev->ready.tail = NULL;
1174 }
1175
1176
1177 pDev->ring = curr_bd;
1178
1179
1180 dmactrl = READ_REG(&pDev->regs->dma_ctrl);
1181 dmactrl &= ~(GRTM_DMA_CTRL_TXRST | GRTM_DMA_CTRL_RST);
1182 dmactrl |= GRTM_DMA_CTRL_EN;
1183 pDev->regs->dma_ctrl = dmactrl;
1184 }
1185
1186 return cnt;
1187 }
1188
1189 static void grtm_tx_process(struct grtm_priv *pDev)
1190 {
1191 int num;
1192
1193
1194
1195
1196 num = grtm_free_sent(pDev);
1197 pDev->scheduled_cnt -= num;
1198 pDev->sent_cnt += num;
1199
1200
1201
1202
1203
1204 if (pDev->running) {
1205 num = grtm_schedule_ready(pDev);
1206 pDev->ready_cnt -= num;
1207 pDev->scheduled_cnt += num;
1208 }
1209 }
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219 static int grtm_request_txlock(struct grtm_priv *pDev, int block)
1220 {
1221 SPIN_IRQFLAGS(irqflags);
1222 int got_lock = 0;
1223
1224 do {
1225 SPIN_LOCK_IRQ(&pDev->devlock, irqflags);
1226 if (pDev->handling_transmission == 0) {
1227 pDev->handling_transmission = 1;
1228 got_lock = 1;
1229 }
1230 SPIN_UNLOCK_IRQ(&pDev->devlock, irqflags);
1231 } while (!got_lock && block);
1232
1233 return got_lock;
1234 }
1235
1236 static inline int grtm_request_txlock_isr(struct grtm_priv *pDev)
1237 {
1238 SPIN_ISR_IRQFLAGS(irqflags);
1239 int got_lock = 0;
1240
1241 SPIN_LOCK(&pDev->devlock, irqflags);
1242 if (pDev->handling_transmission == 0) {
1243 pDev->handling_transmission = 1;
1244 got_lock = 1;
1245 }
1246 SPIN_UNLOCK(&pDev->devlock, irqflags);
1247
1248 return got_lock;
1249 }
1250
1251 static inline void grtm_release_txlock(struct grtm_priv *pDev)
1252 {
1253 pDev->handling_transmission = 0;
1254 }
1255
1256 static rtems_device_driver grtm_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1257 {
1258 struct grtm_priv *pDev;
1259 struct drvmgr_dev *dev;
1260 rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *)arg;
1261 unsigned int *data;
1262 int status;
1263 struct grtm_ioc_config *cfg;
1264 struct grtm_ioc_hw_status *hwregs;
1265 struct grtm_list *chain;
1266 struct grtm_frame *curr;
1267 struct grtm_ioc_hw *hwimpl;
1268 struct grtm_ioc_stats *stats;
1269 int num,ret;
1270
1271 FUNCDBG();
1272
1273 if ( drvmgr_get_dev(&grtm_drv_info.general, minor, &dev) ) {
1274 return RTEMS_INVALID_NUMBER;
1275 }
1276 pDev = (struct grtm_priv *)dev->priv;
1277
1278 if (!ioarg)
1279 return RTEMS_INVALID_NAME;
1280
1281 data = ioarg->buffer;
1282 ioarg->ioctl_return = 0;
1283 switch(ioarg->command) {
1284 case GRTM_IOC_START:
1285 if ( pDev->running ) {
1286 return RTEMS_RESOURCE_IN_USE;
1287 }
1288 if ( (status=grtm_start(pDev)) != RTEMS_SUCCESSFUL ){
1289 return status;
1290 }
1291
1292 drvmgr_interrupt_register(dev, 0, "grtm", grtm_interrupt, pDev);
1293
1294
1295 break;
1296
1297 case GRTM_IOC_STOP:
1298 if ( !pDev->running ) {
1299 return RTEMS_RESOURCE_IN_USE;
1300 }
1301
1302
1303 drvmgr_interrupt_unregister(dev, 0, grtm_interrupt, pDev);
1304 grtm_stop(pDev);
1305 pDev->running = 0;
1306 break;
1307
1308 case GRTM_IOC_ISSTARTED:
1309 if ( !pDev->running ) {
1310 return RTEMS_RESOURCE_IN_USE;
1311 }
1312 break;
1313
1314 case GRTM_IOC_SET_BLOCKING_MODE:
1315 if ( (unsigned int)data > GRTM_BLKMODE_BLK ) {
1316 return RTEMS_INVALID_NAME;
1317 }
1318 DBG("GRTM: Set blocking mode: %d\n",(unsigned int)data);
1319 pDev->config.blocking = (unsigned int)data;
1320 break;
1321
1322 case GRTM_IOC_SET_TIMEOUT:
1323 DBG("GRTM: Timeout: %d\n",(unsigned int)data);
1324 pDev->config.timeout = (rtems_interval)data;
1325 break;
1326
1327 case GRTM_IOC_SET_CONFIG:
1328 cfg = (struct grtm_ioc_config *)data;
1329 if ( !cfg ) {
1330 return RTEMS_INVALID_NAME;
1331 }
1332
1333 if ( pDev->running ) {
1334 return RTEMS_RESOURCE_IN_USE;
1335 }
1336
1337 pDev->config = *cfg;
1338 break;
1339
1340 case GRTM_IOC_GET_STATS:
1341 stats = (struct grtm_ioc_stats *)data;
1342 if ( !stats ) {
1343 return RTEMS_INVALID_NAME;
1344 }
1345 memcpy(stats,&pDev->stats,sizeof(struct grtm_ioc_stats));
1346 break;
1347
1348 case GRTM_IOC_CLR_STATS:
1349 memset(&pDev->stats,0,sizeof(struct grtm_ioc_stats));
1350 break;
1351
1352 case GRTM_IOC_GET_CONFIG:
1353 cfg = (struct grtm_ioc_config *)data;
1354 if ( !cfg ) {
1355 return RTEMS_INVALID_NAME;
1356 }
1357
1358 *cfg = pDev->config;
1359 break;
1360
1361 case GRTM_IOC_GET_OCFREG:
1362 if ( !pDev->hw_avail.ocf ) {
1363
1364 return RTEMS_NOT_DEFINED;
1365 }
1366 if ( !data ) {
1367 return RTEMS_INVALID_NAME;
1368 }
1369 *(unsigned int **)data = (unsigned int *)&pDev->regs->ocf;
1370 break;
1371
1372 case GRTM_IOC_GET_HW_IMPL:
1373 hwimpl = (struct grtm_ioc_hw *)data;
1374 if ( !hwimpl ) {
1375 return RTEMS_INVALID_NAME;
1376 }
1377 *hwimpl = pDev->hw_avail;
1378 break;
1379
1380 case GRTM_IOC_GET_HW_STATUS:
1381 hwregs = (struct grtm_ioc_hw_status *)data;
1382 if ( !hwregs ) {
1383 return RTEMS_INVALID_NAME;
1384 }
1385
1386
1387 break;
1388
1389
1390
1391
1392
1393
1394 case GRTM_IOC_SEND:
1395 if ( !pDev->running ){
1396 return RTEMS_RESOURCE_IN_USE;
1397 }
1398
1399
1400 chain = (struct grtm_list *)ioarg->buffer;
1401 if ( !chain ){
1402
1403
1404
1405
1406
1407 if (grtm_request_txlock(pDev, 0)) {
1408 grtm_tx_process(pDev);
1409 grtm_release_txlock(pDev);
1410 }
1411 break;
1412 }
1413 if ( !chain->tail || !chain->head ){
1414 return RTEMS_INVALID_NAME;
1415 }
1416
1417 DBG("GRTM_SEND: head: 0x%x, tail: 0x%x\n",chain->head,chain->tail);
1418
1419
1420
1421 num = 0;
1422 curr = chain->head;
1423 while(curr != chain->tail){
1424 curr->flags = curr->flags & ~(GRTM_FLAGS_SENT|GRRM_FLAGS_ERR);
1425 curr = curr->next;
1426 num++;
1427 }
1428 curr->flags = curr->flags & ~(GRTM_FLAGS_SENT|GRRM_FLAGS_ERR);
1429 num++;
1430
1431
1432 grtm_request_txlock(pDev, 1);
1433
1434
1435
1436
1437 if ( pDev->ready.head ){
1438
1439
1440
1441 pDev->ready.tail->next = chain->head;
1442 pDev->ready.tail = chain->tail;
1443 chain->tail->next = NULL;
1444 }else{
1445
1446 pDev->ready.head = chain->head;
1447 pDev->ready.tail = chain->tail;
1448 chain->tail->next = NULL;
1449 }
1450 pDev->ready_cnt += num;
1451
1452
1453
1454
1455 grtm_tx_process(pDev);
1456 grtm_release_txlock(pDev);
1457 break;
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471 case GRTM_IOC_RECLAIM:
1472
1473 chain = (struct grtm_list *)ioarg->buffer;
1474 if ( !chain ){
1475 return RTEMS_INVALID_NAME;
1476 }
1477
1478
1479 grtm_request_txlock(pDev, 1);
1480
1481 do {
1482
1483
1484
1485
1486
1487 grtm_tx_process(pDev);
1488
1489
1490
1491
1492
1493 if ( !pDev->sent.head ){
1494
1495
1496
1497
1498 if ( pDev->running && pDev->config.blocking ){
1499 ret = rtems_semaphore_obtain(pDev->sem_tx,RTEMS_WAIT,pDev->config.timeout);
1500 if ( ret == RTEMS_TIMEOUT ) {
1501 grtm_release_txlock(pDev);
1502 return RTEMS_TIMEOUT;
1503 } else if ( ret == RTEMS_SUCCESSFUL ) {
1504
1505 continue;
1506 } else {
1507
1508 grtm_release_txlock(pDev);
1509 return RTEMS_UNSATISFIED;
1510 }
1511
1512 }else{
1513
1514 chain->head = NULL;
1515 chain->tail = NULL;
1516
1517 grtm_release_txlock(pDev);
1518 return RTEMS_TIMEOUT;
1519 }
1520 }else{
1521
1522 chain->head = pDev->sent.head;
1523 chain->tail = pDev->sent.tail;
1524 chain->tail->next = NULL;
1525
1526
1527 grtm_list_clr(&pDev->sent);
1528 pDev->sent_cnt = 0;
1529
1530 DBG("TX_RECLAIM: head: 0x%x, tail: 0x%x\n",chain->head,chain->tail);
1531 break;
1532 }
1533
1534 }while(1);
1535
1536
1537 grtm_release_txlock(pDev);
1538 break;
1539
1540 default:
1541 return RTEMS_NOT_DEFINED;
1542 }
1543 return RTEMS_SUCCESSFUL;
1544 }
1545
1546 static void grtm_interrupt(void *arg)
1547 {
1548 struct grtm_priv *pDev = arg;
1549 struct grtm_regs *regs = pDev->regs;
1550 unsigned int status;
1551
1552
1553 status = READ_REG(®s->dma_status);
1554
1555
1556 if ( !pDev->running || !status)
1557 return;
1558
1559 regs->dma_status = status;
1560
1561 if ( status & GRTM_DMA_STS_TFF ){
1562 pDev->stats.err_transfer_frame++;
1563 }
1564
1565 if ( status & GRTM_DMA_STS_TA ){
1566 pDev->stats.err_ahb++;
1567 }
1568
1569 if ( status & GRTM_DMA_STS_TE ){
1570 pDev->stats.err_tx++;
1571 }
1572
1573 if ( status & GRTM_DMA_STS_TI ){
1574
1575 if ( pDev->config.isr_desc_proc) {
1576 if (grtm_request_txlock_isr(pDev)) {
1577 grtm_tx_process(pDev);
1578 grtm_release_txlock(pDev);
1579 }
1580
1581 #if 0
1582 if ( (pDev->config.blocking==GRTM_BLKMODE_COMPLETE) && pDev->timeout ){
1583
1584 if ( pDev->wait_for_frames > grtm_data_avail(pDev) ){
1585
1586 goto procceed_processing_interrupts;
1587 }
1588
1589
1590
1591
1592 rtems_semaphore_release(pDev->sem_tx);
1593 }
1594 #endif
1595 }
1596
1597 if ( pDev->config.blocking == GRTM_BLKMODE_BLK ) {
1598
1599
1600 #if 0
1601
1602 regs->dma_ctrl = READ_REG(®s->dma_ctrl) & ~GRTM_DMA_CTRL_IE;
1603 #endif
1604
1605
1606 rtems_semaphore_release(pDev->sem_tx);
1607 }
1608
1609 }
1610 #if 0
1611 procceed_processing_interrupts:
1612 ;
1613 #endif
1614 }
1615
1616 static rtems_device_driver grtm_initialize(
1617 rtems_device_major_number major,
1618 rtems_device_minor_number unused,
1619 void *arg
1620 )
1621 {
1622
1623 if ( rtems_semaphore_create(rtems_build_name('G', 'R', 'T', 'M'),
1624 1,
1625 RTEMS_FIFO|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
1626 0,
1627 &grtm_dev_sem) != RTEMS_SUCCESSFUL ) {
1628 return RTEMS_INTERNAL_ERROR;
1629 }
1630
1631 return RTEMS_SUCCESSFUL;
1632 }