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 #include <rtems/libio.h>
0032 #include <stdlib.h>
0033 #include <stdio.h>
0034 #include <string.h>
0035 #include <bsp.h>
0036 #include <rtems/bspIo.h> /* printk */
0037
0038 #include <grlib/satcan.h>
0039 #include <grlib/ambapp.h>
0040
0041 #include <grlib/grlib_impl.h>
0042
0043 #ifndef GAISLER_SATCAN
0044 #define GAISLER_SATCAN 0x080
0045 #endif
0046
0047 #if !defined(SATCAN_DEVNAME)
0048 #undef SATCAN_DEVNAME
0049 #define SATCAN_DEVNAME "/dev/satcan"
0050 #endif
0051
0052
0053
0054
0055 #ifdef DEBUG
0056 #define DBG(x...) printk(x)
0057 #else
0058 #define DBG(x...)
0059 #endif
0060
0061
0062
0063 #define ALIGN_2KMEM 32*1024
0064 #define ALIGN_8KMEM 128*1024
0065
0066 #define OFFSET_2K_LOW_POS 15
0067 #define OFFSET_8K_LOW_POS 17
0068
0069 #define DMA_2K_DATA_SELECT (1 << 14)
0070 #define DMA_8K_DATA_SELECT (1 << 16)
0071
0072 #define DMA_2K_DATA_OFFSET 16*1024
0073 #define DMA_8K_DATA_OFFSET 64*1024
0074
0075
0076
0077
0078
0079
0080
0081 #define CAN_TODn_Int_sel (1 << 5)
0082
0083
0084 #define Sel_2k_8kN (1 << 0)
0085
0086
0087 #define FIFO_Full (1 << 8)
0088 #define FIFO_Empty (1 << 9)
0089
0090
0091 #define DMA_AutoInitDmaTx (1 << 3)
0092 #define DMA_EnTx2 (1 << 2)
0093 #define DMA_EnTx1 (1 << 1)
0094 #define DMA_EnRx (1 << 0)
0095
0096
0097 #define CTRL_BT_P 9
0098 #define CTRL_NODENO_P 5
0099 #define CTRL_DIS (1 << 2)
0100 #define CTRL_DPS_P 1
0101 #define CTRL_RST (1 << 0)
0102
0103 #define IRQ_AHB (1 << 8)
0104 #define IRQ_PPS (1 << 7)
0105 #define IRQ_M5 (1 << 6)
0106 #define IRQ_M4 (1 << 5)
0107 #define IRQ_M3 (1 << 4)
0108 #define IRQ_M2 (1 << 3)
0109 #define IRQ_M1 (1 << 2)
0110 #define IRQ_SYNC (1 << 1)
0111 #define IRQ_CAN (1 << 0)
0112
0113 #define MSK_AHB (1 << 8)
0114 #define MSK_PPS (1 << 7)
0115 #define MSK_M5 (1 << 6)
0116 #define MSK_M4 (1 << 5)
0117 #define MSK_M3 (1 << 4)
0118 #define MSK_M2 (1 << 3)
0119 #define MSK_M1 (1 << 2)
0120 #define MSK_SYNC (1 << 1)
0121 #define MSK_CAN (1 << 0)
0122
0123
0124
0125 struct satcan_regs {
0126 volatile unsigned int satcan[32];
0127 volatile unsigned int ctrl;
0128 volatile unsigned int irqpend;
0129 volatile unsigned int irqmask;
0130 volatile unsigned int membase;
0131 };
0132
0133
0134 struct satcan_priv {
0135
0136 void *dmaptr;
0137 unsigned char *alptr;
0138 satcan_config *cfg;
0139
0140
0141 rtems_id devsem;
0142 rtems_id txsem;
0143 int open;
0144 int txactive;
0145 int dmaen;
0146 int doff;
0147 rtems_interval timeout;
0148 int dmamode;
0149 };
0150
0151 static struct satcan_regs *regs;
0152 static struct satcan_priv *priv;
0153
0154 static rtems_device_driver satcan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0155 static rtems_device_driver satcan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0156 static rtems_device_driver satcan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0157 static rtems_device_driver satcan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0158 static rtems_device_driver satcan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0159 static rtems_device_driver satcan_initialize(rtems_device_major_number major, rtems_device_minor_number unused, void *arg);
0160
0161
0162
0163
0164
0165
0166
0167
0168 static void almalloc(unsigned char **alptr, void **ptr, int sz)
0169 {
0170 *ptr = rtems_calloc(1,2*sz);
0171 *alptr = (unsigned char *) (((int)*ptr+sz) & ~(sz-1));
0172 }
0173
0174 static rtems_isr satcan_interrupt_handler(void *v)
0175 {
0176 unsigned int irq;
0177 unsigned int fifo;
0178
0179 irq = regs->irqpend;
0180
0181 if (irq & IRQ_AHB && priv->cfg->ahb_irq_callback) {
0182 priv->cfg->ahb_irq_callback();
0183 }
0184 if (irq & IRQ_PPS && priv->cfg->pps_irq_callback) {
0185 priv->cfg->pps_irq_callback();
0186 }
0187 if (irq & IRQ_M5 && priv->cfg->m5_irq_callback) {
0188 priv->cfg->m5_irq_callback();
0189 }
0190 if (irq & IRQ_M4 && priv->cfg->m4_irq_callback) {
0191 priv->cfg->m4_irq_callback();
0192 }
0193 if (irq & IRQ_M3 && priv->cfg->m3_irq_callback) {
0194 priv->cfg->m3_irq_callback();
0195 }
0196 if (irq & IRQ_M2 && priv->cfg->m2_irq_callback) {
0197 priv->cfg->m2_irq_callback();
0198 }
0199 if (irq & IRQ_M1 && priv->cfg->m1_irq_callback) {
0200 priv->cfg->m1_irq_callback();
0201 }
0202 if (irq & IRQ_SYNC && priv->cfg->sync_irq_callback) {
0203 priv->cfg->sync_irq_callback();
0204 }
0205 if (irq & IRQ_CAN) {
0206 fifo = regs->satcan[SATCAN_FIFO];
0207 if (!(fifo & FIFO_Empty) && priv->txactive &&
0208 (((fifo & 0xff) == SATCAN_IRQ_EOD1) || ((fifo & 0xff) == SATCAN_IRQ_EOD2))) {
0209 rtems_semaphore_release(priv->txsem);
0210 }
0211 if (priv->cfg->can_irq_callback)
0212 priv->cfg->can_irq_callback(fifo);
0213 }
0214 }
0215
0216
0217
0218 static rtems_device_driver satcan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0219 {
0220 rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t*)arg;
0221 int *value;
0222 rtems_interval *timeout;
0223 satcan_regmod *regmod;
0224
0225 DBG("SatCAN: IOCTL %d\n\r", ioarg->command);
0226
0227 ioarg->ioctl_return = 0;
0228 switch(ioarg->command) {
0229 case SATCAN_IOC_DMA_2K:
0230 DBG("SatCAN: ioctl: setting 2K DMA mode\n\r");
0231 free(priv->dmaptr);
0232 almalloc(&priv->alptr, &priv->dmaptr, ALIGN_2KMEM);
0233 if (priv->dmaptr == NULL) {
0234 printk("SatCAN: Failed to allocate DMA memory\n\r");
0235 return RTEMS_NO_MEMORY;
0236 }
0237
0238 regs->membase = (unsigned int)priv->alptr;
0239 regs->satcan[SATCAN_RAM_BASE] = (unsigned int)priv->alptr >> OFFSET_2K_LOW_POS;
0240 regs->satcan[SATCAN_CMD1] = regs->satcan[SATCAN_CMD1] | Sel_2k_8kN;
0241 break;
0242
0243 case SATCAN_IOC_DMA_8K:
0244 DBG("SatCAN: ioctl: setting 8K DMA mode\n\r");
0245 free(priv->dmaptr);
0246 almalloc(&priv->alptr, &priv->dmaptr, ALIGN_8KMEM);
0247 if (priv->dmaptr == NULL) {
0248 printk("SatCAN: Failed to allocate DMA memory\n\r");
0249 return RTEMS_NO_MEMORY;
0250 }
0251
0252 regs->membase = (unsigned int)priv->alptr;
0253 regs->satcan[SATCAN_RAM_BASE] = (unsigned int)priv->alptr >> OFFSET_8K_LOW_POS;
0254 regs->satcan[SATCAN_CMD1] = regs->satcan[SATCAN_CMD1] & ~Sel_2k_8kN;
0255 break;
0256
0257 case SATCAN_IOC_GET_REG:
0258
0259 regmod = (satcan_regmod*)ioarg->buffer;
0260 DBG("SatCAN: ioctl: getting register %d\n\r", regmod->reg);
0261 if (regmod->reg <= SATCAN_FILTER_STOP)
0262 regmod->val = regs->satcan[regmod->reg];
0263 else if (regmod->reg == SATCAN_WCTRL)
0264 regmod->val = regs->ctrl;
0265 else if (regmod->reg == SATCAN_WIPEND)
0266 regmod->val = regs->irqpend;
0267 else if (regmod->reg == SATCAN_WIMASK)
0268 regmod->val = regs->irqmask;
0269 else if (regmod->reg == SATCAN_WAHBADDR)
0270 regmod->val = regs->membase;
0271 else
0272 return RTEMS_INVALID_NAME;
0273 break;
0274
0275 case SATCAN_IOC_SET_REG:
0276
0277 regmod = (satcan_regmod*)ioarg->buffer;
0278 DBG("SatCAN: ioctl: setting register %d, value %x\n\r",
0279 regmod->reg, regmod->val);
0280 if (regmod->reg <= SATCAN_FILTER_STOP)
0281 regs->satcan[regmod->reg] = regmod->val;
0282 else if (regmod->reg == SATCAN_WCTRL)
0283 regs->ctrl = regmod->val;
0284 else if (regmod->reg == SATCAN_WIPEND)
0285 regs->irqpend = regmod->val;
0286 else if (regmod->reg == SATCAN_WIMASK)
0287 regs->irqmask = regmod->val;
0288 else if (regmod->reg == SATCAN_WAHBADDR)
0289 regs->membase = regmod->val;
0290 else
0291 return RTEMS_INVALID_NAME;
0292 break;
0293
0294 case SATCAN_IOC_OR_REG:
0295
0296 regmod = (satcan_regmod*)ioarg->buffer;
0297 DBG("SatCAN: ioctl: or:ing register %d, with value %x\n\r",
0298 regmod->reg, regmod->val);
0299 if (regmod->reg <= SATCAN_FILTER_STOP)
0300 regs->satcan[regmod->reg] |= regmod->val;
0301 else if (regmod->reg == SATCAN_WCTRL)
0302 regs->ctrl |= regmod->val;
0303 else if (regmod->reg == SATCAN_WIPEND)
0304 regs->irqpend |= regmod->val;
0305 else if (regmod->reg == SATCAN_WIMASK)
0306 regs->irqmask |= regmod->val;
0307 else if (regmod->reg == SATCAN_WAHBADDR)
0308 regs->membase |= regmod->val;
0309 else
0310 return RTEMS_INVALID_NAME;
0311 break;
0312
0313 case SATCAN_IOC_AND_REG:
0314
0315 regmod = (satcan_regmod*)ioarg->buffer;
0316 DBG("SatCAN: ioctl: masking register %d, with value %x\n\r",
0317 regmod->reg, regmod->val);
0318 if (regmod->reg <= SATCAN_FILTER_STOP)
0319 regs->satcan[regmod->reg] &= regmod->val;
0320 else if (regmod->reg == SATCAN_WCTRL)
0321 regs->ctrl &= regmod->val;
0322 else if (regmod->reg == SATCAN_WIPEND)
0323 regs->irqpend &= regmod->val;
0324 else if (regmod->reg == SATCAN_WIMASK)
0325 regs->irqmask &= regmod->val;
0326 else if (regmod->reg == SATCAN_WAHBADDR)
0327 regs->membase &= regmod->val;
0328 else
0329 return RTEMS_INVALID_NAME;
0330 break;
0331
0332 case SATCAN_IOC_EN_TX1_DIS_TX2:
0333 priv->dmaen = SATCAN_DMA_ENABLE_TX1;
0334 break;
0335
0336 case SATCAN_IOC_EN_TX2_DIS_TX1:
0337 priv->dmaen = SATCAN_DMA_ENABLE_TX2;
0338 break;
0339
0340 case SATCAN_IOC_GET_DMA_MODE:
0341 value = (int*)ioarg->buffer;
0342 *value = priv->dmamode;
0343 break;
0344
0345 case SATCAN_IOC_SET_DMA_MODE:
0346 value = (int*)ioarg->buffer;
0347 if (*value != SATCAN_DMA_MODE_USER && *value != SATCAN_DMA_MODE_SYSTEM) {
0348 DBG("SatCAN: ioctl: invalid DMA mode\n\r");
0349 return RTEMS_INVALID_NAME;
0350 }
0351 priv->dmamode = *value;
0352 break;
0353
0354 case SATCAN_IOC_ACTIVATE_DMA:
0355 if (priv->dmamode != SATCAN_DMA_MODE_USER) {
0356 DBG("SatCAN: ioctl: ACTIVATE_DMA: not in user mode\n\r");
0357 return RTEMS_INVALID_NAME;
0358 }
0359 value = (int*)ioarg->buffer;
0360 if (*value != SATCAN_DMA_ENABLE_TX1 && *value != SATCAN_DMA_ENABLE_TX2) {
0361 DBG("SatCAN: ioctl: ACTIVATE_DMA: Illegal channel\n\r");
0362 return RTEMS_INVALID_NAME;
0363 }
0364 regs->satcan[SATCAN_DMA] |= *value << 1;
0365 break;
0366
0367 case SATCAN_IOC_DEACTIVATE_DMA:
0368 if (priv->dmamode != SATCAN_DMA_MODE_USER) {
0369 DBG("SatCAN: ioctl: DEACTIVATE_DMA: not in user mode\n\r");
0370 return RTEMS_INVALID_NAME;
0371 }
0372 value = (int*)ioarg->buffer;
0373 if (*value != SATCAN_DMA_ENABLE_TX1 && *value != SATCAN_DMA_ENABLE_TX2) {
0374 DBG("SatCAN: ioctl: DEACTIVATE_DMA: Illegal channel\n\r");
0375 return RTEMS_INVALID_NAME;
0376 }
0377 regs->satcan[SATCAN_DMA] &= ~(*value << 1);
0378 break;
0379
0380 case SATCAN_IOC_GET_DOFFSET:
0381 value = (int*)ioarg->buffer;
0382 *value = priv->doff;
0383 break;
0384
0385 case SATCAN_IOC_SET_DOFFSET:
0386 value = (int*)ioarg->buffer;
0387 priv->doff = *value;
0388 break;
0389
0390 case SATCAN_IOC_GET_TIMEOUT:
0391 timeout = (rtems_interval*)ioarg->buffer;
0392 *timeout = priv->timeout;
0393 break;
0394
0395 case SATCAN_IOC_SET_TIMEOUT:
0396 timeout = (rtems_interval*)ioarg->buffer;
0397 priv->timeout = *timeout;
0398 break;
0399
0400 default:
0401 return RTEMS_NOT_DEFINED;
0402 }
0403
0404 return RTEMS_SUCCESSFUL;
0405 }
0406
0407 static rtems_device_driver satcan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0408 {
0409 int i;
0410 int doff;
0411 int msgindex;
0412 int messages;
0413 rtems_libio_rw_args_t *rw_args=(rtems_libio_rw_args_t *) arg;
0414 satcan_msg *msgs;
0415 rtems_status_code status;
0416
0417 DBG("SatCAN: Writing %d bytes from %p\n\r",rw_args->count,rw_args->buffer);
0418
0419 if ((rw_args->count < sizeof(satcan_msg)) || (!rw_args->buffer)) {
0420 DBG("SatCAN: write: returning EINVAL\n\r");
0421 return RTEMS_INVALID_NAME;
0422 }
0423
0424 messages = rw_args->count / sizeof(satcan_msg);
0425 msgs = (satcan_msg*)rw_args->buffer;
0426
0427
0428 if (rw_args->count % sizeof(satcan_msg)) {
0429 DBG("SatCAN: write: count can not be evenly divided with satcan_msg size\n\r");
0430 return RTEMS_INVALID_NAME;
0431 }
0432
0433
0434
0435 DBG("SatCAN: write: dma channel select is %x\n\r", priv->dmaen);
0436 if (!priv->dmaen && priv->dmamode == SATCAN_DMA_MODE_SYSTEM)
0437 return RTEMS_INVALID_NAME;
0438
0439
0440 if (regs->satcan[SATCAN_DMA] & (DMA_EnTx1 | DMA_EnTx2 | DMA_AutoInitDmaTx)) {
0441 DBG("SatCAN: write: DMA was active\n\r");
0442 rw_args->bytes_moved = 0;
0443 return RTEMS_IO_ERROR;
0444 }
0445
0446 doff = regs->satcan[SATCAN_CMD1] & Sel_2k_8kN ? DMA_2K_DATA_OFFSET : DMA_8K_DATA_OFFSET;
0447
0448 for (msgindex = 0; msgindex < messages; msgindex++) {
0449
0450 for (i = 0; i < SATCAN_HEADER_SIZE; i++) {
0451 priv->alptr[priv->doff+8*msgindex+i] = msgs[msgindex].header[i];
0452 }
0453
0454
0455 for (i = 0; i < SATCAN_PAYLOAD_SIZE; i++)
0456 priv->alptr[priv->doff+doff+8*msgindex+i] = msgs[msgindex].payload[i];
0457 }
0458
0459 if ((priv->dmaen & SATCAN_DMA_ENABLE_TX1) || priv->dmamode == SATCAN_DMA_MODE_USER) {
0460 regs->satcan[SATCAN_DMA_TX_1_CUR] = 0;
0461 regs->satcan[SATCAN_DMA_TX_1_END] = messages<<3;
0462 }
0463
0464 if ((priv->dmaen & SATCAN_DMA_ENABLE_TX2) || priv->dmamode == SATCAN_DMA_MODE_USER) {
0465 regs->satcan[SATCAN_DMA_TX_2_CUR] = 0;
0466 regs->satcan[SATCAN_DMA_TX_2_END] = messages<<3;
0467 }
0468
0469
0470 if (priv->dmamode == SATCAN_DMA_MODE_SYSTEM) {
0471 priv->txactive = 1;
0472
0473
0474 regs->satcan[SATCAN_DMA] |= priv->dmaen << 1;
0475
0476
0477 status = rtems_semaphore_obtain(priv->txsem, RTEMS_WAIT, priv->timeout);
0478
0479 priv->txactive = 0;
0480
0481
0482 regs->satcan[SATCAN_DMA] &= ~(priv->dmaen << 1);
0483
0484 if (status != RTEMS_SUCCESSFUL) {
0485 rw_args->bytes_moved = 0;
0486 return status;
0487 }
0488 }
0489
0490 rw_args->bytes_moved = rw_args->count;
0491
0492 return RTEMS_SUCCESSFUL;
0493 }
0494
0495 static rtems_device_driver satcan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0496 {
0497 char *buf;
0498 int i;
0499 int canid;
0500 int messages;
0501 rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t*)arg;
0502 satcan_msg *ret;
0503
0504
0505 if (rw_args->count < sizeof(satcan_msg)) {
0506 DBG("SatCAN: read: length of buffer must be at least %d, current is %d\n\r",
0507 sizeof(satcan_msg) + sizeof(int), rw_args->count);
0508 return RTEMS_INVALID_NAME;
0509 }
0510
0511
0512 if (rw_args->count % sizeof(satcan_msg)) {
0513 DBG("SatCAN: read: count can not be evenly divided with satcan_msg size\n\r");
0514 return RTEMS_INVALID_NAME;
0515 }
0516
0517 messages = rw_args->count / sizeof(satcan_msg);
0518 ret = (satcan_msg*)rw_args->buffer;
0519
0520 DBG("SatCAN: read: reading %d messages to %p\n\r", messages, ret);
0521
0522 for (i = 0; i < messages; i++) {
0523 canid = (ret[i].header[1] << 8) | ret[i].header[0];
0524
0525
0526 buf = (char*)((int)priv->alptr | (canid << 3));
0527 memcpy(ret[i].header, buf, SATCAN_HEADER_SIZE);
0528
0529 DBG("SatCAN: read: copied header from %p to %p\n\r", buf, ret[i].header);
0530
0531
0532 buf[SATCAN_HEADER_NMM_POS] = 0;
0533
0534
0535 buf = (char*)((int)buf |
0536 (regs->satcan[SATCAN_CMD1] & Sel_2k_8kN ? DMA_2K_DATA_SELECT : DMA_8K_DATA_SELECT));
0537 memcpy(ret[i].payload, buf, SATCAN_PAYLOAD_SIZE);
0538
0539 DBG("SatCAN: read: copied payload from %p to %p\n\r", buf, ret[i].payload);
0540 }
0541 rw_args->bytes_moved = rw_args->count;
0542
0543 return RTEMS_SUCCESSFUL;
0544 }
0545
0546
0547 static rtems_device_driver satcan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0548 {
0549 DBG("SatCAN: Closing %d\n\r",minor);
0550
0551 if (priv->open) {
0552 regs->irqmask = 0;
0553 regs->satcan[SATCAN_INT_EN] = 0;
0554 regs->satcan[SATCAN_RX] = 0;
0555 regs->satcan[SATCAN_DMA] = 0;
0556 priv->open = 0;
0557 priv->dmaen = 0;
0558 priv->doff = 0;
0559 priv->timeout = RTEMS_NO_TIMEOUT;
0560 priv->dmamode = SATCAN_DMA_MODE_SYSTEM;
0561 }
0562
0563 return RTEMS_SUCCESSFUL;
0564 }
0565
0566
0567 static rtems_device_driver satcan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0568 {
0569 DBG("SatCAN: Opening %d\n\r",minor);
0570
0571 rtems_semaphore_obtain(priv->devsem,RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0572 if (priv->open) {
0573 rtems_semaphore_release(priv->devsem);
0574 return RTEMS_RESOURCE_IN_USE;
0575 }
0576 priv->open = 1;
0577 rtems_semaphore_release(priv->devsem);
0578
0579
0580 regs->irqmask = MSK_AHB | MSK_CAN;
0581 regs->satcan[SATCAN_INT_EN] = ((1 << SATCAN_IRQ_EOD1) | (1 << SATCAN_IRQ_EOD2) |
0582 (1 << SATCAN_IRQ_CRITICAL));
0583
0584
0585 regs->satcan[SATCAN_CMD0] = CAN_TODn_Int_sel;
0586
0587 regs->satcan[SATCAN_DMA] = 1;
0588
0589 regs->satcan[SATCAN_RX] = 1;
0590
0591 DBG("SatCAN: Opening %d success\n\r",minor);
0592
0593 return RTEMS_SUCCESSFUL;
0594 }
0595
0596 static rtems_device_driver satcan_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0597 {
0598 struct ambapp_ahb_info d;
0599 char fs_name[20];
0600 rtems_status_code status;
0601
0602 DBG("SatCAN: Initialize..\n\r");
0603
0604 strcpy(fs_name, SATCAN_DEVNAME);
0605
0606
0607 if (!ambapp_find_ahbslv(ambapp_plb(), VENDOR_GAISLER, GAISLER_SATCAN, &d)) {
0608 printk("SatCAN: Failed to find SatCAN core\n\r");
0609 return -1;
0610 }
0611
0612 status = rtems_io_register_name(fs_name, major, minor);
0613 if (RTEMS_SUCCESSFUL != status)
0614 rtems_fatal_error_occurred(status);
0615
0616 regs = (struct satcan_regs*)d.start[0];
0617
0618
0619 regs->ctrl |= ((priv->cfg->nodeno & 0xf) << 5) | (priv->cfg->dps << 1);
0620
0621
0622 regs->ctrl |= CTRL_RST;
0623
0624
0625 almalloc(&priv->alptr, &priv->dmaptr, ALIGN_2KMEM);
0626 if (priv->dmaptr == NULL) {
0627 printk("SatCAN: Failed to allocate DMA memory\n\r");
0628 free(priv->cfg);
0629 free(priv);
0630 return -1;
0631 }
0632
0633
0634 while (regs->ctrl & CTRL_RST)
0635 ;
0636
0637
0638 regs->membase = (unsigned int)priv->alptr;
0639 regs->satcan[SATCAN_RAM_BASE] = (unsigned int)priv->alptr >> 15;
0640
0641 DBG("regs->membase = %x\n\r", (unsigned int)priv->alptr);
0642 DBG("regs->satcan[SATCAN_RAM_BASE] = %x\n\r", (unsigned int)priv->alptr >> 15);
0643
0644 status = rtems_semaphore_create(
0645 rtems_build_name('S', 'd', 'v', '0'),
0646 1,
0647 RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
0648 RTEMS_NO_PRIORITY_CEILING,
0649 0,
0650 &priv->devsem);
0651 if (status != RTEMS_SUCCESSFUL) {
0652 printk("SatCAN: Failed to create dev semaphore (%d)\n\r", status);
0653 free(priv->cfg);
0654 free(priv);
0655 return RTEMS_UNSATISFIED;
0656 }
0657 status = rtems_semaphore_create(
0658 rtems_build_name('S', 't', 'x', '0'),
0659 0,
0660 RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
0661 RTEMS_NO_PRIORITY_CEILING,
0662 0,
0663 &priv->txsem);
0664 if (status != RTEMS_SUCCESSFUL) {
0665 printk("SatCAN: Failed to create tx semaphore (%d)\n\r", status);
0666 free(priv->cfg);
0667 free(priv);
0668 return RTEMS_UNSATISFIED;
0669 }
0670
0671 priv->txactive = 0;
0672 priv->open = 0;
0673 priv->dmaen = 0;
0674 priv->doff = 0;
0675 priv->timeout = RTEMS_NO_TIMEOUT;
0676 priv->dmamode = SATCAN_DMA_MODE_SYSTEM;
0677
0678
0679 rtems_interrupt_handler_install(d.common.irq, "satcan",
0680 RTEMS_INTERRUPT_SHARED,
0681 satcan_interrupt_handler, NULL);
0682
0683 return RTEMS_SUCCESSFUL;
0684 }
0685
0686
0687
0688 #define SATCAN_DRIVER_TABLE_ENTRY { satcan_initialize, satcan_open, satcan_close, satcan_read, satcan_write, satcan_ioctl }
0689
0690 static rtems_driver_address_table satcan_driver = SATCAN_DRIVER_TABLE_ENTRY;
0691
0692 int satcan_register(satcan_config *conf)
0693 {
0694 rtems_status_code r;
0695 rtems_device_major_number m;
0696
0697 DBG("SatCAN: satcan_register called\n\r");
0698
0699
0700 if ((priv = grlib_malloc(sizeof(*priv))) == NULL) {
0701 printk("SatCAN driver could not allocate memory for priv structure\n\r");
0702 return -1;
0703 }
0704
0705 DBG("SatCAN: Creating local copy of config structure\n\r");
0706 if ((priv->cfg = grlib_malloc(sizeof(*priv->cfg))) == NULL) {
0707 printk("SatCAN driver could not allocate memory for cfg structure\n\r");
0708 return 1;
0709 }
0710 memcpy(priv->cfg, conf, sizeof(satcan_config));
0711
0712 if ((r = rtems_io_register_driver(0, &satcan_driver, &m)) == RTEMS_SUCCESSFUL) {
0713 DBG("SatCAN driver successfully registered, major: %d\n\r", m);
0714 } else {
0715 switch(r) {
0716 case RTEMS_TOO_MANY:
0717 printk("SatCAN rtems_io_register_driver failed: RTEMS_TOO_MANY\n\r"); break;
0718 case RTEMS_INVALID_NUMBER:
0719 printk("SatCAN rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n\r"); break;
0720 case RTEMS_RESOURCE_IN_USE:
0721 printk("SatCAN rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n\r"); break;
0722 default:
0723 printk("SatCAN rtems_io_register_driver failed\n\r");
0724 }
0725 return 1;
0726 }
0727
0728 return 0;
0729 }