gonzui


Format: Advanced Search

mtkernel_3/device/ser/ser.cbare sourcepermlink (0.05 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    Device Driver for micro T-Kernel for μT-Kernel 3.0
    4:  *
    5:  *    Copyright (C) 2020-2021 by Ken Sakamura.
    6:  *    This software is distributed under the T-License 2.2.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by TRON Forum(http://www.tron.org) at 2021/08.
   10:  *
   11:  *----------------------------------------------------------------------
   12:  */
   13: #include <sys/machine.h>
   14: #include <tk/tkernel.h>
   15: #include <tstdlib.h>
   16: 
   17: #include "ser.h"
   18: #include "../include/dev_def.h"
   19: #if DEV_SER_ENABLE
   20: /*
   21:  *      ser.c
   22:  *      Serial communication driver
   23: */
   24: 
   25: /*----------------------------------------------------------------------*/
   26: /* Serial Device driver Control block
   27:  */
   28: #if TK_SUPPORT_MEMLIB
   29: 
   30: LOCAL T_SER_DCB *dev_ser_cb[DEV_SER_UNITNM];
   31: #define         get_dcb_mem(unit,a)    (dev_ser_cb[unit]->a)
   32: 
   33: #else
   34: 
   35: LOCAL T_SER_DCB dev_ser_cb[DEV_SER_UNITNM];
   36: #define         get_dcb_mem(unit,a)    (dev_ser_cb[unit].a)
   37: 
   38: #endif
   39: 
   40: /*----------------------------------------------------------------------*/
   41: /* Serial device driver low-level interface
   42:  *
   43:  *      Called from a low level interrupt handler.
   44:  */
   45: EXPORT BOOL dev_ser_get_snddat(UW unit, UW *data)
   46: {
   47:         T_SER_BUFF     *p_buff;
   48: 
   49:         p_buff = &get_dcb_mem(unit, snd_buff);
   50:         if(p_buff->top != p_buff->tail) {
   51:                 *data = p_buff->data[p_buff->tail];
   52:                 if(++p_buff->tail >= DEVCONF_SER_BUFFSIZE) p_buff->tail = 0;
   53: 
   54:                 if(p_buff->wait_tskid) {
   55:                         tk_wup_tsk( p_buff->wait_tskid);
   56:                         p_buff->wait_tskid = 0;
   57:                 }
   58:                 return TRUE;
   59:         } else {
   60:                 return FALSE;
   61:         }
   62: }
   63: 
   64: EXPORT void dev_ser_notify_rcv(UW unit, UW data)
   65: {
   66:         T_SER_BUFF     *p_buff;
   67:         INT            next;
   68: 
   69:         p_buff = &get_dcb_mem( unit, rcv_buff);
   70:         next = p_buff->top + 1;
   71:         if(next >= DEVCONF_SER_BUFFSIZE) next = 0;
   72:         if(next != p_buff->tail) {
   73:                 p_buff->data[p_buff->top] = data;
   74:                 p_buff->top = next;
   75:         } else {       
   76:                 dev_ser_notify_err( unit, DEV_SER_ERR_ROVR);  /* Buffer over flow */
   77:         }
   78: 
   79:         if(p_buff->wait_tskid) {
   80:                 tk_wup_tsk( p_buff->wait_tskid);
   81:                 p_buff->wait_tskid = 0;
   82:         }
   83: 
   84: }
   85: 
   86: EXPORT void dev_ser_notify_err(UW unit, UW err)
   87: {
   88:         get_dcb_mem(unit, com_error) |= err;   
   89: }
   90: 
   91: /*----------------------------------------------------------------------*/
   92: /* Attribute data control
   93:  */
   94: 
   95: LOCAL ER set_atr_size(T_DEVREQ *req)
   96: {
   97:         switch(req->start) {
   98:         case TDN_EVENT:                        /* MBF ID for event notification */
   99:                 req->asize = sizeof(ID);
  100:                 break;
  101:         case TDN_SER_MODE:             /* Communication mode */
  102:         case TDN_SER_SPEED:            /* Communication speed */
  103:         case TDN_SER_COMERR:           /* Communication Error */
  104:                 req->asize = sizeof(UW);
  105:                 break;
  106:         case TDN_SER_SNDTMO:           /* Send timeout */
  107:         case TDN_SER_RCVTMO:           /* Receive timeout */
  108:                 req->asize = sizeof(TMO);
  109:                 break;
  110:         default:
  111:                 return E_PAR;
  112:         }
  113:         return E_OK;
  114: }
  115: 
  116: LOCAL ER read_atr(T_SER_DCB *p_dcb, T_DEVREQ *req)
  117: {
  118:         UINT   imask;
  119:         ER     err;
  120: 
  121:         err = set_atr_size(req);
  122:         if(err != E_OK) return err;
  123: 
  124:         if(req->size) {
  125:                 switch(req->start) {
  126:                 case TDN_EVENT:                       /* MBF ID for event notification */
  127:                         *(ID*)req->buf = p_dcb->evtmbfid;
  128:                         break;
  129:                 case TDN_SER_MODE:            /* Communication mode */
  130:                         *(UW*)req->buf = p_dcb->com_mode;
  131:                         break;
  132:                 case TDN_SER_SPEED:           /* Communication speed */
  133:                         *(UW*)req->buf = p_dcb->com_speed;
  134:                         break;
  135:                 case TDN_SER_SNDTMO:          /* Send timeout */
  136:                         *(TMO*)req->buf = p_dcb->snd_tmo;
  137:                         break;
  138:                 case TDN_SER_RCVTMO:          /* Receive timeout */
  139:                         *(TMO*)req->buf = p_dcb->rcv_tmo;
  140:                         break;
  141:                 case TDN_SER_COMERR:          /* Communication Error */
  142:                         DI(imask);
  143:                         *(UW*)req->buf = p_dcb->com_error;
  144:                         p_dcb->com_error = 0;
  145:                         EI(imask);
  146:                         break;
  147:                 case TDN_SER_BREAK:           /* Send Break */
  148:                         /* no break */
  149:                 default:
  150:                         err = E_PAR;
  151:                 }
  152:         }
  153:         return err;
  154: }
  155: 
  156: LOCAL ER write_atr(T_SER_DCB *p_dcb, T_DEVREQ *req)
  157: {
  158:         ER     err;
  159: 
  160:         err = set_atr_size(req);
  161:         if(err != E_OK) return err;
  162: 
  163:         if(req->size) {
  164:                 switch(req->start) {
  165:                 case TDN_EVENT:                       /* Message buffer ID for event notification */
  166:                         p_dcb->evtmbfid = *(ID*)req->buf;
  167:                         break;
  168:                 case TDN_SER_MODE:            /* Communication mode */
  169:                         p_dcb->com_mode = *(UW*)req->buf;
  170:                         err = dev_ser_llctl( p_dcb->unit, LLD_SER_MODE, p_dcb->com_mode);
  171:                         break;
  172:                 case TDN_SER_SPEED:           /* Communication speed */
  173:                         p_dcb->com_speed = *(UW*)req->buf;
  174:                         err = dev_ser_llctl( p_dcb->unit, LLD_SER_SPEED, p_dcb->com_speed);
  175:                         break;
  176:                 case TDN_SER_SNDTMO:          /* Send timeout */
  177:                         p_dcb->snd_tmo = *(TMO*)req->buf;
  178:                         break;
  179:                 case TDN_SER_RCVTMO:          /* Receive timeout */
  180:                         p_dcb->rcv_tmo = *(TMO*)req->buf;
  181:                         break;
  182:                 case TDN_SER_BREAK:           /* Send Break */
  183:                         err = dev_ser_llctl( p_dcb->unit, LLD_SER_BREAK, *(UW*)req->buf);
  184:                         break;
  185:                 default:
  186:                         err = E_PAR;
  187:                 }
  188:         }
  189:         return err;
  190: }
  191: 
  192: /*----------------------------------------------------------------------*/
  193: /* Device-specific data control
  194:  */
  195: 
  196: LOCAL ER read_data( T_SER_DCB *p_dcb, T_DEVREQ *req)
  197: {
  198:         T_SER_BUFF     *p_buff;
  199:         UW             tail;
  200:         UB             *pd;
  201:         SZ             rsize;
  202:         ER             err;
  203: 
  204:         p_buff = &p_dcb->rcv_buff;
  205:         tail   = p_buff->tail;
  206:         pd     = req->buf;
  207:         rsize  = req->size;
  208:         err    = E_OK;
  209: 
  210:         if(rsize != 0 ) {              /* size != 0 : Receive data */
  211:                 while(rsize) {
  212:                         DisableInt(p_dcb->intno_rcv);        /* Disable Receive Int. */
  213:                         if(p_buff->top != tail) {
  214:                                 *pd++ = p_buff->data[tail++];
  215:                                 if(tail >= DEVCONF_SER_BUFFSIZE ) tail = 0;
  216:                                 p_buff->tail = tail;
  217:                                 EnableInt(p_dcb->intno_rcv, DEVCNF_SER_INTPRI);     /* Enable Receive Int. */
  218:                                 rsize--;
  219:                         } else {
  220:                                 p_buff->wait_tskid = tk_get_tid();
  221:                                 EnableInt(p_dcb->intno_rcv, DEVCNF_SER_INTPRI);     /* Enable Receive Int. */
  222:                                 err = tk_slp_tsk(p_dcb->rcv_tmo);
  223:                                 if( err != E_OK) break;
  224:                         }
  225:                 }
  226:                 req->asize = req->size - rsize;
  227:         } else {               /* size = 0: Get the number of readable data */
  228:                 /* Disable Receive Int. */
  229:                 rsize = p_buff->top - p_buff->tail;
  230:                 /* Enable Receive Int. */
  231:                 if(rsize < 0) {
  232:                         rsize += DEVCONF_SER_BUFFSIZE;
  233:                 }
  234:                 req->asize = rsize;
  235:         }
  236: 
  237:         return err;
  238: }
  239: 
  240: LOCAL ER write_data( T_SER_DCB *p_dcb, T_DEVREQ *req)
  241: {
  242:         T_SER_BUFF     *p_buff;
  243:         UW             next;
  244:         UB             *pd;
  245:         INT            ssize;
  246:         ER             err;
  247:         BOOL           s;
  248: 
  249:         p_buff = &p_dcb->snd_buff;
  250:         pd     = req->buf;
  251:         ssize  = req->size;
  252:         err    = E_OK;
  253: 
  254:         if(ssize != 0) {               /* size != 0 : Send data */
  255:                 while(ssize) {
  256:                         next = p_buff->top + 1;
  257:                         if(next >= DEVCONF_SER_BUFFSIZE) next = 0;
  258:                         
  259:                         DisableInt(p_dcb->intno_snd);        /* Disable Send Int. */
  260:                         if(next != p_buff->tail) {
  261:                                 s = FALSE;
  262:                                 if(p_buff->top == p_buff->tail) {
  263:                                         s = (E_OK == dev_ser_llctl( p_dcb->unit, LLD_SER_SEND, *pd));
  264:                                 }
  265:                                 if(s) {             /* Successful transmission. */
  266:                                         pd++;
  267:                                 } else {    /* FIFO is full. */
  268:                                         p_buff->data[p_buff->top] = *pd++;
  269:                                         p_buff->top = next;
  270:                                 }
  271:                                 EnableInt(p_dcb->intno_snd, DEVCNF_SER_INTPRI);     /* Enable Send Int. */
  272:                                 ssize--;
  273:                         } else {
  274:                                 p_buff->wait_tskid = tk_get_tid();
  275:                                 EnableInt(p_dcb->intno_snd, DEVCNF_SER_INTPRI);     /* Enable Send Int. */
  276:                                 err = tk_slp_tsk(p_dcb->snd_tmo);
  277:                                 if(err != E_OK) break;
  278:                         }
  279:                 }
  280:                 req->asize = req->size - ssize;
  281:         } else {               /* size = 0: Get the number of writable data */
  282:                 DisableInt(p_dcb->intno_snd);                 /* Disable Send Int. */
  283:                 ssize = p_buff->top - p_buff->tail;
  284:                 EnableInt(p_dcb->intno_snd, DEVCNF_SER_INTPRI);       /* Enable send Int. */
  285:                 if(ssize < 0) {
  286:                         ssize += DEVCONF_SER_BUFFSIZE;
  287:                 }
  288:                 req->asize = DEVCONF_SER_BUFFSIZE - ssize;
  289:         }
  290: 
  291:         return err;
  292: }
  293: 
  294: /*----------------------------------------------------------------------
  295:  * mSDI I/F function
  296:  */
  297: /*----------------------------------------------------------------------
  298:  * Open device
  299:  */
  300: ER dev_ser_openfn( ID devid, UINT omode, T_MSDI *p_msdi)
  301: {
  302:         T_SER_DCB      *p_dcb;
  303:         ER             err;
  304: 
  305:         p_dcb = (T_SER_DCB*)p_msdi->dmsdi.exinf;
  306: 
  307:         /* Device Open operation */
  308:         p_dcb->omode = omode;
  309:         buff_init(&p_dcb->snd_buff);
  310:         buff_init(&p_dcb->rcv_buff);
  311: 
  312:         err = dev_ser_llctl(p_dcb->unit, LLD_SER_START, 0);
  313: 
  314:         return err;
  315: }
  316: 
  317: /*----------------------------------------------------------------------
  318:  * Close Device
  319:  */
  320: ER dev_ser_closefn( ID devid, UINT option, T_MSDI *p_msdi)
  321: {
  322:         T_SER_DCB      *p_dcb;
  323:         ER             err;
  324: 
  325:         p_dcb = (T_SER_DCB*)(p_msdi->dmsdi.exinf);
  326: 
  327:         /* Device Close operation */
  328:         err = dev_ser_llctl(p_dcb->unit, LLD_SER_STOP, 0);
  329:         
  330:         return err;
  331: }
  332: 
  333: /*----------------------------------------------------------------------
  334:  * Read Device
  335:  */
  336: ER dev_ser_readfn( T_DEVREQ *req, T_MSDI *p_msdi)
  337: {
  338:         T_SER_DCB      *p_dcb;
  339:         ER             err;
  340: 
  341:         p_dcb = (T_SER_DCB*)(p_msdi->dmsdi.exinf);
  342: 
  343:         if(req->start >= 0) {  // Device specific data
  344:                 if( p_dcb->omode & TD_READ ) {
  345:                         err = read_data( p_dcb, req);
  346:                 } else {
  347:                         err = E_OACV;
  348:                 }
  349:         } else {               // Device attribute data
  350:                 err = read_atr( p_dcb, req);
  351:         }
  352: 
  353:         return err;
  354: }
  355: 
  356: /*----------------------------------------------------------------------
  357:  * Write Device
  358:  */
  359: ER dev_ser_writefn( T_DEVREQ *req, T_MSDI *p_msdi)
  360: {
  361:         T_SER_DCB      *p_dcb;
  362:         ER             err;
  363: 
  364:         p_dcb = (T_SER_DCB*)(p_msdi->dmsdi.exinf);
  365: 
  366:         if(req->start >= 0) {  // Device specific data
  367:                 if( p_dcb->omode & TD_WRITE) {
  368:                         err = write_data( p_dcb, req);
  369:                 } else {
  370:                         err = E_OACV;
  371:                 }
  372:         } else {               // Device attribute data
  373:                 err = write_atr( p_dcb, req);
  374:         }
  375: 
  376:         return err;
  377: }
  378: 
  379: /*----------------------------------------------------------------------
  380:  * Event Device
  381:  */
  382: ER dev_ser_eventfn( INT evttyp, void *evtinf, T_MSDI *p_msdi)
  383: {
  384:         return E_NOSPT;
  385: }
  386: 
  387: /*----------------------------------------------------------------------
  388:  * Serial communication Device initialization and registration
  389:  */
  390: EXPORT ER dev_init_ser( UW unit )
  391: {
  392:         T_SER_DCB      *p_dcb;
  393:         T_IDEV         idev;
  394:         T_MSDI         *p_msdi;
  395:         T_DMSDI                dmsdi;
  396:         ER             err;
  397:         INT            i;
  398: 
  399:         if( unit >= DEV_SER_UNITNM) return E_PAR;
  400: 
  401: #if TK_SUPPORT_MEMLIB
  402:         p_dcb = (T_SER_DCB*)Kmalloc(sizeof(T_SER_DCB));
  403:         if( p_dcb == NULL) return E_NOMEM;
  404:         dev_ser_cb[unit]       = p_dcb;
  405: #else
  406:         p_dcb = &dev_ser_cb[unit];
  407: #endif
  408: 
  409:         /* Device registration information */
  410:         dmsdi.exinf    = p_dcb;
  411:         dmsdi.drvatr   = 0;                      /* Driver attributes */
  412:         dmsdi.devatr   = TDK_UNDEF;              /* Device attributes */
  413:         dmsdi.nsub     = 0;                        /* Number of subunits */
  414:         dmsdi.blksz    = 1;                       /* Unique data block size (-1 = unknown) */
  415:         dmsdi.openfn   = dev_ser_openfn;
  416:         dmsdi.closefn  = dev_ser_closefn;
  417:         dmsdi.readfn   = dev_ser_readfn;
  418:         dmsdi.writefn  = dev_ser_writefn;
  419:         dmsdi.eventfn  = dev_ser_eventfn;
  420:         
  421:         knl_strcpy( (char*)dmsdi.devnm, DEVCNF_SER_DEVNAME);
  422:         i = knl_strlen(DEVCNF_SER_DEVNAME);
  423:         dmsdi.devnm[i] = (UB)('a' + unit);
  424:         dmsdi.devnm[i+1] = 0;
  425: 
  426:         err = msdi_def_dev( &dmsdi, &idev, &p_msdi);
  427:         if(err != E_OK) goto err_2;
  428: 
  429:         p_dcb->unit    = unit;
  430:         p_dcb->evtmbfid        = idev.evtmbfid;
  431: 
  432:         /* Low-level device initialization */
  433:         err = dev_ser_llinit( p_dcb);
  434:         if(err != E_OK) goto err_1;
  435: 
  436:         /* Set default value for attribute data */
  437:         p_dcb->com_speed = DEVCNF_SER_SPEED;
  438:         dev_ser_llctl( unit, LLD_SER_SPEED, DEVCNF_SER_SPEED);
  439:         p_dcb->com_mode = DEVCNF_SER_MODE;
  440:         dev_ser_llctl( unit, LLD_SER_MODE, DEVCNF_SER_MODE);
  441:         p_dcb->snd_tmo = DEVCNF_SER_SND_TMO;
  442:         p_dcb->rcv_tmo = DEVCNF_SER_RCV_TMO;
  443: 
  444:         return E_OK;
  445: 
  446: err_1:
  447:         msdi_del_dev(p_msdi);
  448: err_2:
  449:         Kfree(p_dcb);
  450:         return err;
  451: }
  452: 
  453: #endif          /* DEV_SER_ENABLE */