gonzui


Format: Advanced Search

tkernel_2/driver/tef_em1d/sysdsk/src/accept.cbare sourcepermlink (0.05 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T-Kernel 2.0 Software Package
    4:  *
    5:  *    Copyright 2011 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
   10:  *    Modified by T-Engine Forum at 2014/09/10.
   11:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
   12:  *
   13:  *----------------------------------------------------------------------
   14:  */
   15: 
   16: 
   17: /*
   18:  *      accept.c     System disk driver
   19:  *
   20:  *      Device request processing
   21:  */
   22: 
   23: #include "sdisk.h"
   24: 
   25: /*
   26:  *      Check the device ID error (Also set the object subunit)
   27:  */
   28: LOCAL   DrvTab    *CheckDrvTab(DrvTab *drv, INT devid)
   29: {
   30:         for (; drv != NULL; drv = drv->Next) {
   31:                 if (devid >= drv->DevId &&
   32:                     devid <= drv->DevId + drv->nSUnit) break;
   33:         }
   34:         if (drv != NULL) {
   35:                 /* Set the object subunit */
   36:                 drv->CurSUnit = devid - drv->DevId;
   37:         }
   38:         return drv;
   39: }
   40: 
   41: /*
   42:  *      Check data size
   43:  */
   44: EXPORT  INT      CheckSize(W datacnt, W size)
   45: {
   46:         if (datacnt >= size) return E_OK;
   47:         return (datacnt == 0) ? size : E_PAR;
   48: }
   49: 
   50: /*
   51:  *      DN_DISKEVENT: message buffer ID for event notification (RW)
   52:  */
   53: LOCAL   INT       accDISKEVENT(DrvTab *drv, T_DEVREQ *req)
   54: {
   55:         if (req->cmd == TDC_READ)      *((ID*)req->buf) = drv->MbfId;
   56:         else                           drv->MbfId = *((ID*)req->buf);
   57:         return sizeof(ID);
   58: }
   59: 
   60: /*
   61:  *      DN_DISKINFO: disk information (R)
   62:  */
   63: LOCAL   INT       accDISKINFO(DrvTab *drv, T_DEVREQ *req)
   64: {
   65:         sdMakeDiskInfo(drv, (DiskInfo*)req->buf);
   66:         return sizeof(DiskInfo);
   67: }
   68: 
   69: /*
   70:  *      DN_DISKFORMAT: disk format (W)
   71:  */
   72: LOCAL   INT       accDISKFORMAT(DrvTab *drv, T_DEVREQ *req)
   73: {
   74:         ER     er, err;
   75: 
   76:         /* Check read-only : the request shall not come */
   77:         if (drv->Spec.readonly) return E_RONLY;
   78: 
   79:         /* Format the disk : logical unit also shall be approved */
   80:         er = (*(drv->Format))(drv, ((DiskFormat*)req->buf), req->size);
   81: 
   82:         /* In the case of physical unit, initialize the disk and re-register the device.
   83:            Re-register to deregister subunit also when format error occurs. */
   84:         if (er != E_PAR && drv->CurSUnit == 0) {
   85:                 err = sdRegistDevice(drv);
   86:                 if (er == E_OK) er = err;
   87:         }
   88:         return (er >= E_OK) ? sizeof(DiskFormat) : er;
   89: }
   90: 
   91: /*
   92:  *      DN_DISKINIT: Initialize disk (W)
   93:  */
   94: LOCAL   INT       accDISKINIT(DrvTab *drv, T_DEVREQ *req)
   95: {
   96:         ER     er;
   97: 
   98:         /* Check data */
   99:         if (*((DiskInit*)req->buf) != DISKINIT) return E_PAR;
  100: 
  101:         /* Logical unit also shall be OK'd since it is automatically executed after the format */
  102:         if (drv->CurSUnit == 0) {
  103:                 /* Initialize disk & Re-register device */
  104:                 if ((er = sdRegistDevice(drv)) < E_OK) return er;
  105:         }
  106:         return sizeof(DiskInit);
  107: }
  108: 
  109: /*
  110:  *      DN_DISKMEMADR:       disk area top address (R)
  111:  */
  112: LOCAL   INT       accDISKMEMADR(DrvTab *drv, T_DEVREQ *req)
  113: {
  114:         /* Check the support */
  115:         if (drv->Spec.accif != MEM_ACCIF) return E_NOSPT;
  116: 
  117:         *((void**)req->buf) = (void*)drv->IOB;
  118:         return sizeof(void*);
  119: }
  120: 
  121: /*
  122:  *      DN_DISKPARTINFO: Disk partition information (R)
  123:  */
  124: LOCAL   INT       accDISKPARTINFO(DrvTab *drv, T_DEVREQ *req)
  125: {
  126:         /* Approve the logical unit only */
  127:         if (drv->CurSUnit == 0) return E_PAR;
  128: 
  129:         ((DiskPartInfo*)req->buf)->systemid =
  130:                                 drv->s.SUnit[drv->CurSUnit].SystemId;
  131:         ((DiskPartInfo*)req->buf)->startblock =
  132:                                 drv->s.SUnit[drv->CurSUnit].StartBlock;
  133:         ((DiskPartInfo*)req->buf)->endblock =
  134:                                 drv->s.SUnit[drv->CurSUnit].EndBlock - 1;
  135:         return sizeof(DiskPartInfo);
  136: }
  137: 
  138: /*
  139:  *      DN_DISKCHSINFO: Disk CHS information (R)
  140:  */
  141: LOCAL   INT       accDISKCHSINFO(DrvTab *drv, T_DEVREQ *req)
  142: {
  143:         ((DiskCHSInfo*)req->buf)->cylinder = drv->nXCyl;
  144:         ((DiskCHSInfo*)req->buf)->head = drv->nXHead;
  145:         ((DiskCHSInfo*)req->buf)->sector = drv->nXSec;
  146:         return sizeof(DiskCHSInfo);
  147: }
  148: 
  149: /*
  150:  *      DN_DISKIDINFO: Disk ID information (R)
  151:  */
  152: LOCAL   INT       accDISKIDINFO(DrvTab *drv, T_DEVREQ *req)
  153: {
  154:         /* Check the support */
  155:         if (drv->Spec.accif != ATA_ACCIF &&
  156:             drv->Spec.accif != MMC_ACCIF) return E_NOSPT;
  157: 
  158:         MEMCPY(req->buf, drv->Ident, IDENT_DTSZ);
  159:         return IDENT_DTSZ;
  160: }
  161: 
  162: /*
  163:  *      DN_DISKCMD: disk command (W)
  164:  */
  165: LOCAL   INT       accDISKCMD(DrvTab *drv, T_DEVREQ *req)
  166: {
  167:         /* Support "ATAPI" only */
  168:         return E_NOSPT;
  169: }
  170: 
  171: /*
  172:  *      (-999999) Disk master boot record information (special processing) (R)
  173:  */
  174: #define MBR_DTSZ        (512 + 4)
  175: 
  176: LOCAL   INT       accDISKMBR(DrvTab *drv, T_DEVREQ *req)
  177: {
  178:         ER     er;
  179:         UW     *mp;
  180:         BOOL   write;
  181: 
  182:         /* Check the support */
  183:         if (!drv->SuptMBR || drv->CurSUnit != 0) return E_PAR;
  184: 
  185:         if (req->size != MBR_DTSZ) return E_PAR;
  186: 
  187:         /* Check data & Determine "R/W" */
  188:         mp = (UW*)req->buf;
  189:         if (*mp == (UW)CH4toW('M','B','R','R'))                write = FALSE;
  190:         else if (*mp == (UW)CH4toW('M','B','R','W')
  191:                         && !drv->Spec.readonly)              write = TRUE;
  192:         else                                           return E_PAR;
  193: 
  194:         /* "R/W" of disk master boot record */
  195:         er = (*(drv->ReadWrite))(drv, 0, 1, (void*)(++mp), write);
  196: 
  197:         if (er >= E_OK && write) {
  198:                 /* Disk initialization and device re-registration are not executed : ignore error */
  199:                 (*(drv->DiskInit))(drv);
  200:         }
  201:         return (er >= E_OK) ? MBR_DTSZ : er;
  202: }
  203: 
  204: /*
  205:  *      The read-in / writing request
  206:  */
  207: LOCAL   ER        ReadWriteReq(DrvTab *drv, T_DEVREQ *req)
  208: {
  209: #define nDnT    10
  210: static  const    struct {           /* Attribute data definition     */
  211:         W      dn;                          /* Data number                */
  212:         UW     dsz:16;                             /* Data size             */
  213:         UW     nomedia:1;                  /* OK even without media */
  214:         UW     readable:1;                 /* Read OK            */
  215:         UW     writable:1;                 /* Write OK           */
  216:         INT    (*acc)(DrvTab*, T_DEVREQ*);        /* Access functiuon    */
  217: } DnT[nDnT] = {
  218:         { DN_DISKEVENT,                /* RW: "Mbf" ID for event notification       */
  219:                 sizeof(ID),           1, 1, 1, accDISKEVENT    },
  220:         { DN_DISKINFO,                 /* R : Disk information               */
  221:                 sizeof(DiskInfo),     0, 1, 0,    accDISKINFO        },
  222:         { DN_DISKFORMAT,               /* W : Disk format   */
  223:                 sizeof(DiskFormat),   0, 0, 1,  accDISKFORMAT    },
  224:         { DN_DISKINIT,                 /* W : Disk initialization    */
  225:                 sizeof(DiskInit),     0, 0, 1,    accDISKINIT        },
  226:         { DN_DISKMEMADR,               /* R : Disk area top address */
  227:                 sizeof(void*),                0, 1, 0,      accDISKMEMADR        },
  228:         { DN_DISKPARTINFO,             /* R : Disk partition information  */
  229:                 sizeof(DiskPartInfo), 0, 1, 0,        accDISKPARTINFO        },
  230:         { DN_DISKCHSINFO,              /* R : Disk CHS information */
  231:                 sizeof(DiskCHSInfo),  0, 1, 0, accDISKCHSINFO  },
  232:         { DN_DISKIDINFO,               /* R : Disk identification information       */
  233:                 IDENT_DTSZ,           1, 1, 0, accDISKIDINFO   },
  234:         { (-999999),                   /* R: Special processing (MBR)          */
  235:                 MBR_DTSZ,             0, 1, 0,   accDISKMBR        },
  236:         { DN_DISKCMD,                  /* W : Disk command    */
  237:                 sizeof(DiskCmd),      0, 0, 1,     accDISKCMD  }
  238: };
  239:         ER     er;
  240:         W      cnt, dn, i, edn;
  241: 
  242:         /* Parameter check     */
  243:         if ((cnt = req->size) < 0)
  244:                 {er = E_PAR; goto E_EXIT;}
  245: 
  246:         /* Set user space      */
  247:         er = tk_set_tsp(TSK_SELF, &req->tskspc);
  248:         if (er < E_OK) goto E_EXIT;
  249: 
  250:         if ((dn = req->start) >= 0) {          /* Specific data       */
  251:                 if (!drv->MediaOK) {
  252:                         er = ERR_NOMEDIA;    /* There is no media   */
  253:                 } else if (req->cmd == TDC_WRITE && drv->Spec.readonly) {
  254:                         er = E_RONLY;                /* Read-only (request shall not come) */
  255:                 } else {
  256:                         /* Absolutize & Check the start/end block */
  257:                         dn += drv->s.SUnit[drv->CurSUnit].StartBlock;
  258:                         edn = drv->s.SUnit[drv->CurSUnit].EndBlock;
  259: 
  260:                         if (dn >= edn || (edn - dn) < cnt) {
  261:                                 er = E_PAR; /* Illegal*/
  262:                         } else if (cnt == 0) {
  263:                                 er = edn - dn;      /* Return the remaining number of blocks */
  264:                         } else {             /* R/W processing */
  265:                                 er = (*(drv->ReadWrite))(drv, dn, cnt,
  266:                                         req->buf, req->cmd == TDC_WRITE);
  267:                         }
  268:                 }
  269: 
  270:         } else {                               /* Attribute data  */
  271:                 for (i = 0; i < nDnT && DnT[i].dn != dn; i++);
  272: 
  273:                 if (i >= nDnT) {
  274:                         er = E_PAR;                  /* Illegal number      */
  275:                 } else if (DnT[i].acc == NULL) {
  276:                         er = E_NOSPT;                        /* Unsupported               */
  277:                 } else if (!drv->MediaOK && DnT[i].nomedia == 0) {
  278:                         er = ERR_NOMEDIA;            /* There is no media      */
  279:                 } else if (((req->cmd == TDC_READ) ?
  280:                                 DnT[i].readable : DnT[i].writable) == 0) {
  281:                         er = E_PAR;                  /* Disable "R/W"       */
  282:                 } else if ((er = CheckSize(cnt, DnT[i].dsz)) == E_OK) {
  283:                         er = (*(DnT[i].acc))(drv, req);      /* "R/W" processing  */
  284:                 }
  285:         }
  286: 
  287:         if (er < E_OK) goto E_EXIT;
  288:         req->asize = (INT)er;
  289:         return E_OK;
  290: 
  291: E_EXIT:
  292:         return er;
  293: }
  294: 
  295: /*
  296:  *      Abort processing function
  297:  */
  298: EXPORT  ER       sdAbortFn(T_DEVREQ *req, GDI gdi)
  299: {
  300:         DrvTab *drv;
  301: 
  302:         drv = CheckDrvTab(GDI_exinf(gdi), req->devid);
  303:         if (! drv) return E_OK;                /* Ignore the request for invalid device */
  304: 
  305:         /* Ignore it while in "suspend" status */
  306:         if (!drv->Suspended) {
  307: 
  308:                 /* Abort it when the request from the specified task is in execution */
  309:                 if (drv->CurReq && drv->CurReq == req) {
  310:                         /* Abort request */
  311:                         (*(drv->Abort))(drv);
  312: 
  313:                         /* In order to ensure no access to user space,
  314:                                 wait until the completion of the request in processing */
  315:                         Lock(&drv->ProcLock);
  316:                         Unlock(&drv->ProcLock);
  317:                 }
  318:         }
  319:         return E_OK;
  320: }
  321: 
  322: /*
  323:  *      "Suspend" request
  324:  */
  325: LOCAL   ER        SuspendReq(DrvTab *drv)
  326: {
  327:         /* Ignore it while in "suspend" status */
  328:         if (!drv->Suspended) {
  329: 
  330:                 /* Wait until the completion of the request in processing instead of aborting :
  331:                         It takes time for format processing, etc., however,
  332:                         tentative waiting shall be executed without executing stop/resume. */
  333: 
  334:                 Lock(&drv->ProcLock);
  335: 
  336:                 drv->Suspended = TRUE;
  337: 
  338:                 /* Turn OFF the power if possible */
  339:                 sdPowerOff(drv, CP_SUSPEND);
  340: 
  341:                 /* Set the drive to the reset status */
  342:                 drv->Reset = TRUE;
  343: 
  344:                 /* Exit the processing while locking the common processing */
  345:         }
  346:         return E_OK;
  347: }
  348: 
  349: /*
  350:  *      Resume request
  351:  */
  352: LOCAL   ER        ResumeReq(DrvTab *drv)
  353: {
  354:         /* Ignore it while it is not in "suspend" status */
  355:         if (drv->Suspended) {
  356:                 /* Turn ON power : ignore error */
  357:                 sdPowerOn(drv, CP_RESUME);
  358: 
  359:                 /* Release the suspend status/common processing lock, and resume processing */
  360:                 drv->Suspended = FALSE;
  361:                 Unlock(&drv->ProcLock);
  362:         }
  363:         return E_OK;
  364: }
  365: 
  366: /*
  367:  *      Event processing function
  368:  */
  369: EXPORT  INT      sdEventFn(INT evttyp, void *evtinf, GDI gdi)
  370: {
  371:         ER     er;
  372:         DrvTab *drv;
  373: 
  374:         drv = CheckDrvTab(GDI_exinf(gdi), GDI_devid(gdi));
  375:         if (! drv) return E_NOEXS;
  376: 
  377:         switch (evttyp) {
  378:         case TDV_SUSPEND:
  379:                 er = SuspendReq(drv);
  380:                 break;
  381:         case TDV_RESUME:
  382:                 er = ResumeReq(drv);
  383:                 break;
  384:         case TDV_CARDEVT:
  385:                 Lock(&drv->ProcLock);
  386:                 drv->CurSUnit = 0;
  387:                 er = sdCardEvent(evttyp, evtinf, gdi);
  388:                 Unlock(&drv->ProcLock);
  389:                 break;
  390:         case TDV_USBEVT:
  391:                 er = E_NOSPT;
  392:                 break;
  393:         default:       /* Undefined event */
  394:                 er = E_PAR;
  395:         }
  396:         return er;
  397: }
  398: 
  399: /*
  400:  *      Open processing function
  401:  */
  402: EXPORT  ER       sdOpenFn(ID devid, UINT omode, GDI gdi)
  403: {
  404:         ER     er;
  405:         DrvTab *drv;
  406: 
  407:         drv = CheckDrvTab(GDI_exinf(gdi), devid);
  408:         if (! drv) return E_NOEXS;
  409: 
  410:         Lock(&drv->ProcLock);
  411: 
  412:         /* Open processing (checking of the absence or presence of media is also included) */
  413:         if (drv->DriveOK && drv->OpenCnt == 0) {
  414:                 er = (*(drv->Misc))(drv, (W)DC_OPEN);
  415:                 if (er < E_OK) goto E_EXIT;
  416:         }
  417: 
  418:         er = ERR_NOMEDIA;
  419: 
  420:         /* Checking of the absence or presence of drive */
  421:         if (!drv->DriveOK) goto E_EXIT;
  422: 
  423:         /* Checking of the absence or presence of media */
  424:         if (!drv->MediaOK) {
  425:                 /* In physical device, it shall be openable without media.  */
  426:                 if (drv->CurSUnit != 0) goto E_EXIT;
  427:         }
  428: 
  429:         /* Check the existence of subunit :
  430:            to register the subunit for all partitions unconditionally in the case of HD.
  431: */
  432:         if (drv->CurSUnit != 0 &&
  433:             drv->s.SUnit[drv->CurSUnit].StartBlock >=
  434:             drv->s.SUnit[drv->CurSUnit].EndBlock) goto E_EXIT;
  435: 
  436:         /* Open count of subunit */
  437:         drv->s.SUnit[drv->CurSUnit].OpenCnt++;
  438: 
  439:         /* Overall open count: Turn ON the power at the first open */
  440:         er = E_OK;
  441:         if (drv->OpenCnt++ == 0) {
  442:                 if ((er = sdPowerOn(drv, CP_POWERON)) < E_OK) {
  443:                         drv->OpenCnt--;
  444:                         drv->s.SUnit[drv->CurSUnit].OpenCnt--;
  445:                 }
  446:         }
  447: E_EXIT:
  448:         Unlock(&drv->ProcLock);
  449:         return er;
  450: }
  451: 
  452: /*
  453:  *      Close processing function
  454:  */
  455: EXPORT  ER       sdCloseFn(ID devid, UINT option, GDI gdi)
  456: {
  457:         DrvTab *drv;
  458: 
  459:         drv = CheckDrvTab(GDI_exinf(gdi), devid);
  460:         if (! drv) return E_NOEXS;
  461: 
  462:         Lock(&drv->ProcLock);
  463: 
  464:         /* Open count of subunit */
  465:         if (drv->s.SUnit[drv->CurSUnit].OpenCnt > 0) {
  466:                 drv->s.SUnit[drv->CurSUnit].OpenCnt--;
  467:         }
  468: 
  469:         /* Turn OFF the power at the last close */
  470:         if (--drv->OpenCnt <= 0) {
  471:                 drv->OpenCnt = 0;
  472:                 if (drv->DriveOK) {
  473:                         /* Close processing */
  474:                         (*(drv->Misc))(drv, (option & TD_EJECT) ?
  475:                                        DC_CLOSEALL : DC_CLOSE);
  476:                         /* Power-OFF*/
  477:                         sdPowerOff(drv, CP_POFF);
  478:                 }
  479:         }
  480: 
  481:         Unlock(&drv->ProcLock);
  482:         return E_OK;
  483: }
  484: 
  485: /*
  486:  *      Device request (read/write)
  487:  */
  488: EXPORT  void     sdAcceptRequest(DrvTab *drv)
  489: {
  490:         T_DEVREQ       *req;
  491:         INT            er;
  492: 
  493:         /* Infinite loop of the request accept */
  494:         for (;;) {
  495:                 /* Accept a processing request */
  496:                 er = GDI_Accept(&req, NORMAL_REQPTN, drv->ReqTmout, drv->Gdi);
  497: 
  498:                 if (er < E_OK || (er & DRP_NORMREQ) == 0) {
  499:                         if(er >= E_OK || er == E_TMOUT) {
  500:                                 /* Time-out processing */
  501:                                 (*(drv->Misc))(drv, DC_TSKTMO);
  502:                         }
  503:                         continue;
  504:                 }
  505: 
  506:                 drv = CheckDrvTab(drv, req->devid);
  507:                 if (! drv) er = E_NOEXS;
  508:                 else {
  509:                         Lock(&drv->ProcLock);
  510:                         if (!drv->DriveOK) er = ERR_NOMEDIA;
  511:                         else {
  512:                                 drv->CurReq = req;  /* Set the abort target */
  513:                                 er = ReadWriteReq(drv, req);
  514:                                 drv->CurReq = NULL; /* Release the abort target */
  515:                                 drv->Aborted = FALSE;       /* Release the abort request */
  516:                         }
  517:                         Unlock(&drv->ProcLock);
  518:                 }
  519: 
  520:                 /* Reply */
  521:                 req->error = er;
  522:                 GDI_Reply(req, drv->Gdi);
  523:         }
  524: }