//------------------------------------------------------------------------- // //------------------------------------------------------------------------- sys_res gd5100_Transmit(p_gd5100 p, p_gd5100 pD) { sys_res res; t_gd5100_header xH; uint_t nCS; buf b = {0}; buf_Push(b, p->rmsg->data->p, p->rmsg->data->len); xH.sc1 = 0x68; xH.rtua = p->rmsg->rtua; xH.terid = p->rmsg->terid; xH.msta = p->rmsg->msta; xH.fseq = p->rmsg->fseq; xH.iseq = p->rmsg->iseq; xH.sc2 = 0x68; xH.code = p->rmsg->code; xH.abn = p->rmsg->abn; xH.dir = p->rmsg->dir; xH.len = b->len; nCS = cs8(&xH, sizeof(t_gd5100_header)); nCS += cs8(b->p, b->len); buf_PushData(b, 0x1600 | (nCS & 0xFF), 2); res = dlrcp_TmsgSend(&pD->parent, &xH, sizeof(t_gd5100_header), b->p, b->len, DLRCP_TMSG_RESPOND); buf_Release(b); return res; }
//------------------------------------------------------------------------- //发送报文 //------------------------------------------------------------------------- sys_res gwvms_TmsgSend(p_gwvms p, uint_t nFType,uint_t nPType, buf b, uint_t nType) { t_gwvms_header xH; uint16_t nCRC; buf bBuf = {0}; gwvms_TmsgHeaderInit(p, &xH); if (nType == DLRCP_TMSG_REPORT) { if (p->parent.pfc == 0) p->parent.pfc = 1; else p->parent.pfc += 1; xH.fseq = p->parent.pfc; } else xH.fseq = p->fseq; xH.ftype = nFType; xH.ptype = nPType; xH.len = b->len; buf_Push(bBuf,&xH,sizeof(t_gwvms_header)); buf_Push(bBuf,b->p,b->len); nCRC = crc16(bBuf->p+2, bBuf->len-2); buf_Release(bBuf); buf_PushData(b, nCRC, 2); buf_PushData(b, 0x96, 1); return dlrcp_TmsgSend(&p->parent, &xH, sizeof(t_gwvms_header), b->p, b->len, nType); }
//------------------------------------------------------------------------- //登录、心跳 //------------------------------------------------------------------------- static sys_res gwvms_TmsgLinkcheck (void *p, uint_t nCmd) { sys_res res; buf b = {0}; res = gwvms_TmsgSend(p, 0x01,0x01, b, DLRCP_TMSG_REPORT);//心跳 buf_Release(b); return res; }
sys_res dlt645_Meter(chl c, buf b, uint_t nTmo) { uint8_t *pH, aAdr[6]; #if DLT645_DIR_CTRL p_dev_uart pUart; #endif #if DLT645_DIR_CTRL gpio_Set(2, 0); //稳定总线 chl_Send(c, dlt645_aFE, 4); chl_Send(c, b->p, b->len); pUart = (p_dev_uart)(c->pIf); if (pUart->para.baud < 2400) sys_Delay(200000); else sys_Delay(100000); gpio_Set(2, 1); #else chl_Send(c, dlt645_aFE, 4); chl_Send(c, b->p, b->len); #endif dlt645_DbgOut(1, b->p, b->len); memcpy(aAdr, &b->p[1], 6); buf_Release(b); for (nTmo /= OS_TICK_MS; nTmo; nTmo--) { if (chl_RecData(c, b, OS_TICK_MS) != SYS_R_OK) continue; pH = dlt645_PacketAnalyze(b->p, b->len); if (pH == NULL) continue; buf_Remove(b, pH - b->p); dlt645_DbgOut(0, b->p, b->p[9] + (DLT645_HEADER_SIZE + 2)); if (memcmp(&b->p[1], aAdr, 6)) { buf_Remove(b, DLT645_HEADER_SIZE); continue; } buf_Remove(b, DLT645_HEADER_SIZE - 2); if (b->p[0] & BITMASK(7)) { byteadd(&b->p[2], -0x33, b->p[1]); return SYS_R_OK; } } return SYS_R_TMO; }
static int vk321x_RegRead(uint_t nChl, uint_t nReg) { uint_t i; int res = -1; buf b = {0}; nReg |= (nChl << 4); for (i = VK321X_TIMEOUT / 200; i; i--) { if (uart_Send(vk321x_port, &nReg, 1) == SYS_R_OK) { if (uart_RecData(vk321x_port, b, 200) == SYS_R_OK) { res = b->p[0]; buf_Release(b); break; } } } return res; }
//------------------------------------------------------------------------- //分析报文 //------------------------------------------------------------------------- static sys_res gwvms_RmsgAnalyze(void *args) { p_gwvms p = (t_gwvms *)args; uint8_t *pTemp; uint16_t nCRC; p_gwvms_header pH; p_dlrcp pRcp = &p->parent; chl_RecData(pRcp->chl, pRcp->rbuf, OS_TICK_MS); for (; ; buf_Remove(pRcp->rbuf, 1)) { for (; ; buf_Remove(pRcp->rbuf, 1)) { //不足报文头长度 if (pRcp->rbuf->len < sizeof(t_gwvms_header)) return SYS_R_ERR; pH = (p_gwvms_header)pRcp->rbuf->p; if (pH->sc == 0x5AA5){ if (pH->len > GWVMS_DATA_SIZE) continue; break; } } //不足长度 if (pRcp->rbuf->len < (sizeof(t_gwvms_header) + pH->len + 2)) return SYS_R_ERR; pTemp = pRcp->rbuf->p + sizeof(t_gwvms_header) + pH->len; nCRC = *pTemp<<8 | *(pTemp+1); pTemp += 2; //CRC if (crc16(pRcp->rbuf->p + 2, sizeof(t_gwvms_header) + pH->len - 2) != nCRC) continue; //结束符 if (*pTemp != 0x96) continue; //接收到报文 p->fseq = pH->fseq; p->ftype = pH->ftype; p->ptype = pH->ptype; buf_Release(p->data); buf_Push(p->data, pRcp->rbuf->p + sizeof(t_gwvms_header), pH->len); buf_Remove(pRcp->rbuf, sizeof(t_gwvms_header) + pH->len + 2); return SYS_R_OK; } }
// 中继转发645帧20130906 // b - 输入发送645帧与输出接收的645帧 sys_res dlt645_Transmit(chl c, buf b, uint_t nTmo) { uint8_t *pH; chl_Send(c, dlt645_aFE, 4); chl_Send(c, b->p, b->len); dlt645_DbgOut(1, b->p, b->len); buf_Release(b); for (nTmo /= OS_TICK_MS; nTmo; nTmo--) { if (chl_RecData(c, b, OS_TICK_MS) != SYS_R_OK) continue; pH = dlt645_PacketAnalyze(b->p, b->len); if (pH == NULL) continue; buf_Remove(b, pH - b->p); return SYS_R_OK; } return SYS_R_ERR; }
//------------------------------------------------------------------------- //登录 //------------------------------------------------------------------------- static sys_res gd5100_TmsgLinkcheck (void *p, uint_t nCmd) { sys_res res; buf b = {0}; switch (nCmd) { case DLRCP_LINKCHECK_LOGIN: nCmd = GD5100_CCODE_LOGIN; buf_Push(b, ((p_gd5100)p)->pwd, 3); break; case DLRCP_LINKCHECK_LOGOUT: nCmd = GD5100_CCODE_LOGOUT; break; default: nCmd = GD5100_CCODE_KEEPALIVE; break; } res = gd5100_TmsgSend(p, nCmd, b, DLRCP_TMSG_REPORT); buf_Release(b); return res; }
static void _vk321x_ItHandler() { p_dev_uart pUart; p_uart_def pDef; int res; uint_t i, nLen, nGIR, nReg; buf b = {0}; if ((res = vk321x_RegRead(0, VK321X_GIR)) == -1) return; nGIR = res; for (pDef = tbl_bspUartDef, i = 0; pDef < ARR_ENDADR(tbl_bspUartDef); pDef++, i++) { if (pDef->type != UART_T_VK321X) continue; pUart = uart_Dev(i); if (nGIR & BITMASK(pDef->id)) { while (1) { //Rx Fifo Not Empty if ((res = vk321x_RegRead(pDef->id, VK321X_SSR)) == -1) return; if (res & BITMASK(0)) break; //Get rx fifo num if ((res = vk321x_RegRead(pDef->id, VK321X_SFSR)) == -1) return; nLen = (res - 1) & 0x0F; nReg = 0x40 | (pDef->id << 4) | nLen; if (uart_Send(vk321x_port, &nReg, 1) == SYS_R_OK) if (uart_RecLength(vk321x_port, b, nLen + 1, VK321X_TIMEOUT) == SYS_R_OK) { #if IO_BUF_TYPE == BUF_T_BUFFER buf_Push(pUart->bufrx, b->p, nLen + 1); #else dque_Push(dqueue, pUart->parent->id | UART_DQUE_RX_CHL, b->p, nLen + 1); #endif buf_Release(b); } } } } }
afs_int32 cm_RequestWillBlock(cm_bkgRequest_t *rp) { afs_int32 willBlock = 0; if (rp->procp == cm_BkgStore) { /* * If the datastoring flag is set, it means that another * thread is already performing an exclusive store operation * on this file. The exclusive state will be cleared once * the file server locks the vnode. Therefore, at most two * threads can be actively involved in storing data at a time * on a file. */ lock_ObtainRead(&rp->scp->rw); willBlock = (rp->scp->flags & CM_SCACHEFLAG_DATASTORING); lock_ReleaseRead(&rp->scp->rw); } else if (rp->procp == RDR_BkgFetch || rp->procp == cm_BkgPrefetch) { /* * Attempt to determine if there is a conflict on the requested * range of the file. If the first in the range does not exist * in the cache assume there is no conflict. If the buffer does * exist, check to see if an I/O operation is in progress * by using the writing and reading flags as an indicator. */ osi_hyper_t base; cm_buf_t *bufp = NULL; base.LowPart = rp->p1; base.HighPart = rp->p2; bufp = buf_Find(&rp->scp->fid, &base); if (bufp) { willBlock = (bufp->flags & (CM_BUF_WRITING|CM_BUF_READING)); buf_Release(bufp); } } return willBlock; }
/* * called with scp->rw lock held exclusive */ afs_int32 raw_ReadData( cm_scache_t *scp, osi_hyper_t *offsetp, afs_uint32 length, char *bufferp, afs_uint32 *readp, cm_user_t *userp, cm_req_t *reqp) { long code; cm_buf_t *bufp = NULL; osi_hyper_t fileLength; osi_hyper_t thyper; osi_hyper_t lastByte; osi_hyper_t bufferOffset; long bufIndex, nbytes; int sequential = 0; /* start by looking up the file's end */ code = cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); if (code) goto done; cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); /* now we have the entry locked, look up the length */ fileLength = scp->length; /* adjust length down so that it won't go past EOF */ thyper.LowPart = length; thyper.HighPart = 0; thyper = LargeIntegerAdd(*offsetp, thyper); /* where read should end */ lastByte = thyper; if (LargeIntegerGreaterThan(thyper, fileLength)) { /* we'd read past EOF, so just stop at fileLength bytes. * Start by computing how many bytes remain in the file. */ thyper = LargeIntegerSubtract(fileLength, *offsetp); /* if we are past EOF, read 0 bytes */ if (LargeIntegerLessThanZero(thyper)) length = 0; else length = thyper.LowPart; } *readp = length; /* now, copy the data one buffer at a time, * until we've filled the request packet */ while (1) { /* if we've copied all the data requested, we're done */ if (length <= 0) break; /* otherwise, load up a buffer of data */ thyper.HighPart = offsetp->HighPart; thyper.LowPart = offsetp->LowPart & ~(cm_data.blockSize-1); if (!bufp || !LargeIntegerEqualTo(thyper, bufferOffset)) { /* wrong buffer */ if (bufp) { buf_Release(bufp); bufp = NULL; } lock_ReleaseWrite(&scp->rw); code = buf_Get(scp, &thyper, reqp, 0, &bufp); lock_ObtainWrite(&scp->rw); if (code) goto done; bufferOffset = thyper; /* now get the data in the cache */ while (1) { code = cm_SyncOp(scp, bufp, userp, reqp, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ); if (code) goto done; cm_SyncOpDone(scp, bufp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ); if (cm_HaveBuffer(scp, bufp, 0)) break; /* otherwise, load the buffer and try again */ code = cm_GetBuffer(scp, bufp, NULL, userp, reqp); if (code) break; } if (code) { buf_Release(bufp); bufp = NULL; goto done; } } /* if (wrong buffer) ... */ /* now we have the right buffer loaded. Copy out the * data from here to the user's buffer. */ bufIndex = offsetp->LowPart & (cm_data.blockSize - 1); /* and figure out how many bytes we want from this buffer */ nbytes = cm_data.blockSize - bufIndex; /* what remains in buffer */ if (nbytes > length) nbytes = length; /* don't go past EOF */ /* now copy the data */ memcpy(bufferp, bufp->datap + bufIndex, nbytes); /* adjust lengthers, pointers, etc. */ bufferp += nbytes; length -= nbytes; thyper.LowPart = nbytes; thyper.HighPart = 0; *offsetp = LargeIntegerAdd(thyper, *offsetp); } /* while 1 */ done: if (bufp) buf_Release(bufp); if (code == 0 && sequential) cm_ConsiderPrefetch(scp, &lastByte, *readp, userp, reqp); return code; }
afs_uint32 raw_WriteData( cm_scache_t *scp, osi_hyper_t *offsetp, afs_uint32 length, char *bufferp, cm_user_t *userp, cm_req_t *reqp, afs_uint32 *writtenp) { long code = 0; long written = 0; osi_hyper_t fileLength; /* file's length at start of write */ osi_hyper_t minLength; /* don't read past this */ afs_uint32 nbytes; /* # of bytes to transfer this iteration */ cm_buf_t *bufp = NULL; osi_hyper_t thyper; /* hyper tmp variable */ osi_hyper_t bufferOffset; afs_uint32 bufIndex; /* index in buffer where our data is */ int doWriteBack = 0; osi_hyper_t writeBackOffset;/* offset of region to write back when I/O is done */ afs_uint32 writeBackLength; DWORD filter = 0; /* start by looking up the file's end */ code = cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS); if (code) goto done; cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS); /* now we have the entry locked, look up the length */ fileLength = scp->length; minLength = fileLength; if (LargeIntegerGreaterThan(minLength, scp->serverLength)) minLength = scp->serverLength; /* adjust file length if we extend past EOF */ thyper.LowPart = length; thyper.HighPart = 0; thyper = LargeIntegerAdd(*offsetp, thyper); /* where write should end */ if (LargeIntegerGreaterThan(thyper, fileLength)) { /* we'd write past EOF, so extend the file */ scp->mask |= CM_SCACHEMASK_LENGTH; scp->length = thyper; filter |= (FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE); } else filter |= FILE_NOTIFY_CHANGE_LAST_WRITE; doWriteBack = 1; writeBackOffset = *offsetp; writeBackLength = length; /* now, copy the data one buffer at a time, until we've filled the * request packet */ while (1) { /* if we've copied all the data requested, we're done */ if (length <= 0) break; /* otherwise, load up a buffer of data */ thyper.HighPart = offsetp->HighPart; thyper.LowPart = offsetp->LowPart & ~(cm_data.blockSize-1); if (!bufp || !LargeIntegerEqualTo(thyper, bufferOffset)) { /* wrong buffer */ if (bufp) { lock_ReleaseMutex(&bufp->mx); buf_Release(bufp); bufp = NULL; } lock_ReleaseWrite(&scp->rw); code = buf_Get(scp, &thyper, reqp, 0, &bufp); if (bufp) lock_ObtainMutex(&bufp->mx); lock_ObtainWrite(&scp->rw); if (code) goto done; bufferOffset = thyper; /* now get the data in the cache */ while (1) { code = cm_SyncOp(scp, bufp, userp, reqp, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_WRITE | CM_SCACHESYNC_BUFLOCKED); if (code) goto done; cm_SyncOpDone(scp, bufp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_WRITE | CM_SCACHESYNC_BUFLOCKED); /* If we're overwriting the entire buffer, or * if we're writing at or past EOF, mark the * buffer as current so we don't call * cm_GetBuffer. This skips the fetch from the * server in those cases where we're going to * obliterate all the data in the buffer anyway, * or in those cases where there is no useful * data at the server to start with. * * Use minLength instead of scp->length, since * the latter has already been updated by this * call. */ if (LargeIntegerGreaterThanOrEqualTo(bufp->offset, minLength) || LargeIntegerEqualTo(*offsetp, bufp->offset) && (length >= cm_data.blockSize || LargeIntegerGreaterThanOrEqualTo(LargeIntegerAdd(*offsetp, ConvertLongToLargeInteger(length)), minLength))) { if (length < cm_data.blockSize && bufp->dataVersion == CM_BUF_VERSION_BAD) memset(bufp->datap, 0, cm_data.blockSize); bufp->dataVersion = scp->dataVersion; } if (cm_HaveBuffer(scp, bufp, 1)) break; /* otherwise, load the buffer and try again */ lock_ReleaseMutex(&bufp->mx); code = cm_GetBuffer(scp, bufp, NULL, userp, reqp); lock_ReleaseWrite(&scp->rw); lock_ObtainMutex(&bufp->mx); lock_ObtainWrite(&scp->rw); if (code) break; } if (code) { lock_ReleaseMutex(&bufp->mx); buf_Release(bufp); bufp = NULL; goto done; } } /* if (wrong buffer) ... */ /* now we have the right buffer loaded. Copy out the * data from here to the user's buffer. */ bufIndex = offsetp->LowPart & (cm_data.blockSize - 1); /* and figure out how many bytes we want from this buffer */ nbytes = cm_data.blockSize - bufIndex; /* what remains in buffer */ if (nbytes > length) nbytes = length; /* don't go past end of request */ /* now copy the data */ memcpy(bufp->datap + bufIndex, bufferp, nbytes); buf_SetDirty(bufp, reqp, bufIndex, nbytes, userp); /* adjust lengthers, pointers, etc. */ bufferp += nbytes; length -= nbytes; written += nbytes; thyper.LowPart = nbytes; thyper.HighPart = 0; *offsetp = LargeIntegerAdd(thyper, *offsetp); } /* while 1 */ done: if (writtenp) *writtenp = written; if (bufp) { lock_ReleaseMutex(&bufp->mx); buf_Release(bufp); } if (code == 0 && doWriteBack) { rock_BkgStore_t *rockp = malloc(sizeof(*rockp)); if (rockp) { code = cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_ASYNCSTORE); if (code == 0) { rockp->length = writeBackLength; rockp->offset = writeBackOffset; lock_ReleaseWrite(&scp->rw); cm_QueueBKGRequest(scp, cm_BkgStore, rockp, userp, reqp); lock_ObtainWrite(&scp->rw); /* rock is freed by cm_BkgDaemon */ } else { free(rockp); } } } /* cm_SyncOpDone is called when cm_BkgStore completes */ return code; }
//Internal Functions //------------------------------------------------------------------------- //分析报文 //------------------------------------------------------------------------- static sys_res gd5100_RmsgAnalyze(void *args) { p_gd5100 p = (t_gd5100 *)args; p_dlrcp pRcp = &p->parent; uint8_t *pTemp; #if DLRCP_ZIP_ENABLE uint_t nLen; int nDelen; #endif p_gd5100_header pH; chl_RecData(pRcp->chl, pRcp->rbuf, OS_TICK_MS); for (; ; buf_Remove(pRcp->rbuf, 1)) { for (; ; buf_Remove(pRcp->rbuf, 1)) { //不足报文头长度 if (pRcp->rbuf->len < sizeof(t_gd5100_header)) return SYS_R_ERR; #if DLRCP_ZIP_ENABLE if (pRcp->zip) { pTemp = pRcp->rbuf->p; if ((pTemp[0] == 0x88) && (pTemp[4] == 0xFF)) { nLen = (pTemp[2] << 8) | pTemp[3]; if (pRcp->rbuf->len < (nLen + 5)) return SYS_R_ERR; if (pTemp[nLen + 4] == 0x77) { nDelen = DeData(pTemp, nLen + 5); if (nDelen > 0) { buf_Remove(pRcp->rbuf, nLen + 5); buf_Push(pRcp->rbuf, RecvBuf, nDelen); } } } } #endif pH = (p_gd5100_header)pRcp->rbuf->p; if ((pH->sc1 == 0x68) && (pH->sc2 == 0x68)) { if (pH->len > GD5100_DATA_SIZE) continue; //收到报文头 if (pRcp->rcvtime == 0) pRcp->rcvtime = rtc_GetTimet(); break; } } //不足长度 if (pRcp->rbuf->len < (sizeof(t_gd5100_header) + pH->len + 2)) { if (((uint16_t)rtc_GetTimet() - pRcp->rcvtime) < 10) return SYS_R_ERR; pRcp->rcvtime = 0; continue; } pRcp->rcvtime = 0; pTemp = pRcp->rbuf->p + sizeof(t_gd5100_header) + pH->len; //CS if (cs8(pRcp->rbuf->p, sizeof(t_gd5100_header) + pH->len) != *pTemp++) continue; //结束符 if (*pTemp != 0x16) continue; //接收到报文 p->rmsg->msta = pH->msta; p->rmsg->rtua = pH->rtua; p->rmsg->terid = pH->terid; p->rmsg->fseq = pH->fseq; p->rmsg->iseq = pH->iseq; p->rmsg->code = pH->code; p->rmsg->abn = pH->abn; p->rmsg->dir = pH->dir; buf_Release(p->rmsg->data); buf_Push(p->rmsg->data, pRcp->rbuf->p + sizeof(t_gd5100_header), pH->len); buf_Remove(pRcp->rbuf, sizeof(t_gd5100_header) + pH->len + 2); return SYS_R_OK; } }
sys_res gdfts_Handler(buf bIn, buf bOut) { sys_res res = SYS_R_ERR; uint_t nCode, nIsReset = 0; uint8_t *pData; adr_t adr = upd_DataDev.tbl[0].start; gdfts pFts = {0}; p_gdfts_header pH; os_que que; if (bOut->len) buf_Release(bOut); nCode = bIn->p[0] & 0x3F; pH = (p_gdfts_header)&bIn->p[1]; if (pH->id != GDFTS_ID_SELF) { //Transceiver if (os_que_Send(QUE_EVT_GDFTS_TRANS, NULL, bIn->p, bIn->len, GDFTS_TRANS_TMO) == SYS_R_OK) if ((que = os_que_Wait(QUE_EVT_GDFTS_RESPOND, NULL, GDFTS_TRANS_TMO)) != NULL) { buf_Push(bOut, que->data->b->p, que->data->b->len); os_que_Release(que); res = SYS_R_OK; } if (res != SYS_R_OK) { buf_PushData(bOut, nCode | GDFTS_CODE_ERR, 1); buf_PushData(bOut, crc16(bOut->p, bOut->len), 2); } return SYS_R_OK; } switch (nCode) { case GDFTS_CODE_TRANS: if (memcmp(gdfts_Pwd, pH->pwd, sizeof(gdfts_Pwd)) == 0) { pData = (uint8_t *)(pH + 1); if (pH->cnt) { if (sfs_Read(upd_SfsDev, pH->id, pFts) == SYS_R_OK) if (pFts->cnt == pH->cnt) if (flash_Program(upd_DataDev.dev, adr + IAP_HEADER_SIZE + pFts->reced, pData, pH->len) == SYS_R_OK) { pFts->cnt += 1; pFts->reced += pH->len; if (pFts->reced < pFts->len) { sfs_Write(upd_SfsDev, pH->id, pFts, sizeof(gdfts)); res = SYS_R_OK; } else if (pFts->crc == crc16((uint8_t *)(adr + IAP_HEADER_SIZE), pFts->len)) { t_iap xIap = {0}; xIap.magic1 = IAP_MAGICWORD_1; xIap.magic2 = IAP_MAGICWORD_2; xIap.dest = INTFLASH_ADR_BASE + BOOTLOADER_SIZE; xIap.len = pFts->len; xIap.id = pH->id; xIap.crc = pFts->crc; sfs_Delete(upd_SfsDev, pH->id); if (flash_Program(upd_DataDev.dev, adr, &xIap, sizeof(xIap)) == SYS_R_OK) { nIsReset = 1; res = SYS_R_OK; } } } } else { res = SYS_R_OK; if ((pH->restart) || (sfs_Read(upd_SfsDev, pH->id, pFts) != SYS_R_OK)) { gdfts_DataFormat(); pFts->cnt = 1; pFts->reced = 0; memcpy(&pFts->len, pData, sizeof(pFts->len)); memcpy(&pFts->crc, pData + sizeof(pFts->len), sizeof(pFts->crc)); res = sfs_Write(upd_SfsDev, pH->id, pFts, sizeof(gdfts)); } } } if (res == SYS_R_OK) gdfts_Response(bOut, nCode | GDFTS_CODE_OK, pH, pFts); else gdfts_Response(bOut, nCode | GDFTS_CODE_ERR, pH, pFts); break; case GDFTS_CODE_ABORT: if (memcmp(gdfts_Pwd, pH->pwd, sizeof(gdfts_Pwd)) == 0) res = sfs_Delete(upd_SfsDev, pH->id); if (res == SYS_R_OK) nCode |= GDFTS_CODE_OK; else nCode |= GDFTS_CODE_ERR; buf_PushData(bOut, nCode, 1); buf_PushData(bOut, pH->id, 2); buf_PushData(bOut, crc16(bOut->p, bOut->len), 2); break; case GDFTS_CODE_INIT: if (memcmp(gdfts_Pwd, pH->pwd, sizeof(gdfts_Pwd)) == 0) if ((res = gdfts_DataFormat()) == SYS_R_OK) if ((res = sfs_Init(upd_SfsDev)) == SYS_R_OK) res = sfs_Write(upd_SfsDev, GDFTS_MAGIC_INIT, NULL, 0); if (res == SYS_R_OK) nCode |= GDFTS_CODE_OK; else nCode |= GDFTS_CODE_ERR; buf_PushData(bOut, nCode, 1); buf_PushData(bOut, pH->id, 2); buf_PushData(bOut, crc16(bOut->p, bOut->len), 2); break; default: break; } if (nIsReset) return SYS_R_RESET; return SYS_R_OK; }
long WriteData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op, cm_user_t *userp, long *writtenp) { long code = 0; long written = 0; osi_hyper_t fileLength; /* file's length at start of write */ osi_hyper_t minLength; /* don't read past this */ afs_uint32 nbytes; /* # of bytes to transfer this iteration */ cm_buf_t *bufferp; osi_hyper_t thyper; /* hyper tmp variable */ osi_hyper_t bufferOffset; afs_uint32 bufIndex; /* index in buffer where our data is */ int doWriteBack; osi_hyper_t writeBackOffset;/* offset of region to write back when * I/O is done */ DWORD filter = 0; cm_req_t req; cm_InitReq(&req); bufferp = NULL; doWriteBack = 0; lock_ObtainWrite(&scp->rw); /* start by looking up the file's end */ code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS); if (code) goto done; cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS); #if 0 /* make sure we have a writable FD */ if (!(fidp->flags & SMB_FID_OPENWRITE)) { code = CM_ERROR_BADFDOP; goto done; } #endif /* now we have the entry locked, look up the length */ fileLength = scp->length; minLength = fileLength; if (LargeIntegerGreaterThan(minLength, scp->serverLength)) minLength = scp->serverLength; /* adjust file length if we extend past EOF */ thyper.LowPart = count; thyper.HighPart = 0; thyper = LargeIntegerAdd(offset, thyper); /* where write should end */ if (LargeIntegerGreaterThan(thyper, fileLength)) { /* we'd write past EOF, so extend the file */ scp->mask |= CM_SCACHEMASK_LENGTH; scp->length = thyper; filter |= (FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE); } else filter |= FILE_NOTIFY_CHANGE_LAST_WRITE; /* now, if the new position (thyper) and the old (offset) are in * different storeback windows, remember to store back the previous * storeback window when we're done with the write. */ if ((thyper.LowPart & (-cm_chunkSize)) != (offset.LowPart & (-cm_chunkSize))) { /* they're different */ doWriteBack = 1; writeBackOffset.HighPart = offset.HighPart; writeBackOffset.LowPart = offset.LowPart & (-cm_chunkSize); } *writtenp = count; /* now, copy the data one buffer at a time, until we've filled the * request packet */ while (1) { /* if we've copied all the data requested, we're done */ if (count <= 0) break; /* handle over quota or out of space */ if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE)) { *writtenp = written; break; } /* otherwise, load up a buffer of data */ thyper.HighPart = offset.HighPart; thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1); if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) { /* wrong buffer */ if (bufferp) { lock_ReleaseMutex(&bufferp->mx); buf_Release(bufferp); bufferp = NULL; } lock_ReleaseWrite(&scp->rw); code = buf_Get(scp, &thyper, &bufferp); lock_ObtainMutex(&bufferp->mx); lock_ObtainWrite(&scp->rw); if (code) goto done; bufferOffset = thyper; /* now get the data in the cache */ while (1) { code = cm_SyncOp(scp, bufferp, userp, &req, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_WRITE | CM_SCACHESYNC_BUFLOCKED); if (code) goto done; cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_WRITE | CM_SCACHESYNC_BUFLOCKED); /* If we're overwriting the entire buffer, or * if we're writing at or past EOF, mark the * buffer as current so we don't call * cm_GetBuffer. This skips the fetch from the * server in those cases where we're going to * obliterate all the data in the buffer anyway, * or in those cases where there is no useful * data at the server to start with. * * Use minLength instead of scp->length, since * the latter has already been updated by this * call. */ if (LargeIntegerGreaterThanOrEqualTo(bufferp->offset, minLength) || LargeIntegerEqualTo(offset, bufferp->offset) && (count >= buf_bufferSize || LargeIntegerGreaterThanOrEqualTo(LargeIntegerAdd(offset, ConvertLongToLargeInteger(count)), minLength))) { if (count < buf_bufferSize && bufferp->dataVersion == -1) memset(bufferp->datap, 0, buf_bufferSize); bufferp->dataVersion = scp->dataVersion; } if (cm_HaveBuffer(scp, bufferp, 1)) break; /* otherwise, load the buffer and try again */ lock_ReleaseMutex(&bufferp->mx); code = cm_GetBuffer(scp, bufferp, NULL, userp, &req); lock_ReleaseWrite(&scp->rw); lock_ObtainMutex(&bufferp->mx); lock_ObtainWrite(&scp->rw); if (code) break; } if (code) { lock_ReleaseMutex(&bufferp->mx); buf_Release(bufferp); bufferp = NULL; goto done; } } /* if (wrong buffer) ... */ /* now we have the right buffer loaded. Copy out the * data from here to the user's buffer. */ bufIndex = offset.LowPart & (buf_bufferSize - 1); /* and figure out how many bytes we want from this buffer */ nbytes = buf_bufferSize - bufIndex; /* what remains in buffer */ if (nbytes > count) nbytes = count; /* don't go past end of request */ /* now copy the data */ memcpy(bufferp->datap + bufIndex, op, nbytes); buf_SetDirty(bufferp, bufIndex, nbytes, userp); /* adjust counters, pointers, etc. */ op += nbytes; count -= nbytes; written += nbytes; thyper.LowPart = nbytes; thyper.HighPart = 0; offset = LargeIntegerAdd(thyper, offset); } /* while 1 */ done: lock_ReleaseWrite(&scp->rw); if (bufferp) { lock_ReleaseMutex(&bufferp->mx); buf_Release(bufferp); } if (code == 0 && doWriteBack) { lock_ObtainWrite(&scp->rw); code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE); lock_ReleaseWrite(&scp->rw); if (code == 0) cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart, writeBackOffset.HighPart, cm_chunkSize, 0, userp); } /* cm_SyncOpDone is called when cm_BkgStore completes */ return code; }