static err_t SMapLowLevelOutput ( NetIF* pNetIF, PBuf* pOutput ) { while ( 1 ) { int iFlags; SMapStatus Res; if ( ( Res = AddToQueue ( pOutput ) ) == SMap_OK ) return ERR_OK; if ( Res == SMap_Err ) return ERR_IF; if ( Res == SMap_Con ) return ERR_CONN; WaitSema ( iSendMutex ); CpuSuspendIntr ( &iFlags ); if ( iReqCNT == MAX_REQ_CNT ) { iSendReq = iSendReqMutex; CpuResumeIntr ( iFlags ); WaitSema ( iSendReqMutex ); } else CpuResumeIntr ( iFlags ); SignalSema ( iSendMutex ); } /* end while */ } /* end SMapLowLevelOutput */
int NetManRpcNetIFSendPacket(const void *packet, unsigned int length){ struct PacketTag *PacketTag; WaitSema(NetManTxSemaID); NetmanTxWaitingThread=GetThreadId(); WaitSema(TxBankAccessSema); //Check is there is space in the current Tx FIFO. If not, wait for the Tx thread to empty out the other FIFO. */ while(CurrentTxFIFOData->PacketReqs.NumPackets>=NETMAN_RPC_BLOCK_SIZE){ SignalSema(TxBankAccessSema); WakeupThread(TxThreadID); SleepThread(); WaitSema(TxBankAccessSema); } memcpy(&CurrentTxFIFOData->FrameBuffer[CurrentTxFIFOData->PacketReqs.TotalLength], packet, length); PacketTag=&CurrentTxFIFOData->PacketReqs.tags[CurrentTxFIFOData->PacketReqs.NumPackets]; PacketTag->offset=CurrentTxFIFOData->PacketReqs.TotalLength; PacketTag->length=length; CurrentTxFIFOData->PacketReqs.TotalLength+=(length+3)&~3; CurrentTxFIFOData->PacketReqs.NumPackets++; WakeupThread(TxThreadID); SignalSema(TxBankAccessSema); NetmanTxWaitingThread=-1; SignalSema(NetManTxSemaID); return 0; }
static void ioWorkerThread(void) { while (!gIOTerminate) { SleepThread(); // no processing when io is blocked if (isIOBlocked) continue; // if term requested exit immediately from the loop if (gIOTerminate) break; // do we have a request in the queue? while (gReqList) { WaitSema(gProcSemaId); struct io_request_t* req = gReqList; ioProcessRequest(req); // lock the queue tip as well now WaitSema(gEndSemaId); // can't be sure if the request was gReqList = req->next; free(req); if (!gReqList) gReqEnd = NULL; SignalSema(gProcSemaId); SignalSema(gEndSemaId); } } // delete the pending requests while (gReqList) { struct io_request_t* req = gReqList; gReqList = gReqList->next; free(req); // TODO: Leak over here - we need a propper flag to free/not the user data } // delete the semaphores DeleteSema(gProcSemaId); DeleteSema(gEndSemaId); isIORunning = 0; ExitDeleteThread(); }
static void TxThread(void *arg){ struct TxFIFOData *TxFIFODataToTransmit; SifDmaTransfer_t dmat; int dmat_id, ThreadToWakeUp; while(1){ SleepThread(); WaitSema(TxBankAccessSema); if(CurrentTxFIFOData->PacketReqs.NumPackets>0){ // Switch banks TxFIFODataToTransmit=CurrentTxFIFOData; if(TxActiveBankID==0){ CurrentTxFIFOData=&TxFIFOData2; TxActiveBankID=1; } else{ CurrentTxFIFOData=&TxFIFOData1; TxActiveBankID=0; } SignalSema(TxBankAccessSema); SifWriteBackDCache(&TxFIFODataToTransmit->PacketReqs, sizeof(TxFIFODataToTransmit->PacketReqs)); dmat.src=&TxFIFODataToTransmit->PacketReqs; dmat.dest=TxFrameTagBuffer; dmat.size=8+sizeof(struct PacketTag)*TxFIFODataToTransmit->PacketReqs.NumPackets; dmat.attr=0; while((dmat_id=SifSetDma(&dmat, 1))==0){}; WaitSema(NetManIOSemaID); SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_SEND_PACKETS, 0, TxFIFODataToTransmit->FrameBuffer, TxFIFODataToTransmit->PacketReqs.TotalLength, NULL, 0, NULL, NULL); SignalSema(NetManIOSemaID); TxFIFODataToTransmit->PacketReqs.NumPackets=0; TxFIFODataToTransmit->PacketReqs.TotalLength=0; } else SignalSema(TxBankAccessSema); if(NetmanTxWaitingThread>=0){ ThreadToWakeUp=NetmanTxWaitingThread; NetmanTxWaitingThread=-1; //To prevent a race condition from occurring, invalidate NetmanTxWaitingThread before invoking WakeupThread. WakeupThread(ThreadToWakeUp); } } }
static void ioWorkerThread(void *arg) { while (!gIOTerminate) { SleepThread(); // if term requested exit immediately from the loop if (gIOTerminate) break; // do we have a request in the queue? WaitSema(gProcSemaId); while (gReqList) { // if term requested exit immediately from the loop if (gIOTerminate) break; struct io_request_t* req = gReqList; ioProcessRequest(req); // lock the queue tip as well now WaitSema(gEndSemaId); // can't be sure if the request was gReqList = req->next; free(req); if (!gReqList) gReqEnd = NULL; SignalSema(gEndSemaId); } SignalSema(gProcSemaId); } // delete the pending requests while (gReqList) { struct io_request_t* req = gReqList; gReqList = gReqList->next; free(req); } // delete the semaphores DeleteSema(gProcSemaId); DeleteSema(gEndSemaId); isIORunning = 0; ExitDeleteThread(); }
u32_t sys_arch_sem_wait(sys_sem_t Sema,u32_t u32Timeout) { //Wait u32Timeout msec for the Sema to receive a signal. dbgprintf("sys_arch_sem_wait: Sema: %d, Timeout: %x (TID: %d)\n",Sema,u32Timeout,GetThreadId()); if(u32Timeout==0) { //Wait with no timeouts. return WaitSema(Sema)==0 ? 0:SYS_ARCH_TIMEOUT; } else if(u32Timeout==1) { //Poll. return PollSema(Sema)==0 ? 0:SYS_ARCH_TIMEOUT; } else { //Use alarm to timeout. iop_sys_clock_t ClockTicks; iop_sys_clock_t Start; iop_sys_clock_t End; int iPID=GetThreadId(); u32_t u32WaitTime; GetSystemTime(&Start); USec2SysClock(u32Timeout*1000,&ClockTicks); SetAlarm(&ClockTicks,TimeoutHandler,(void*)iPID); if(WaitSema(Sema)!=0) { return SYS_ARCH_TIMEOUT; } CancelAlarm(TimeoutHandler,(void*)iPID); GetSystemTime(&End); u32WaitTime=ComputeTimeDiff(&Start,&End); return u32WaitTime<=u32Timeout ? u32WaitTime:u32Timeout; } }
static arch_message *alloc_msg(void) { unsigned int i; arch_message *message; int OldState; WaitSema(MsgCountSema); CpuSuspendIntr(&OldState); for(i=0,message=NULL; i<SYS_MAX_MESSAGES; i++) { if((msg_pool[i].next == NULL) && (msg_pool[i].sys_msg == NULL)) { msg_pool[i].next = (arch_message *) 0xFFFFFFFF; msg_pool[i].sys_msg = (void *) 0xFFFFFFFF; message=&msg_pool[i]; break; } } CpuResumeIntr(OldState); return message; }
Ps2File *findInCache(int64 id) { if (id <= 0) return NULL; WaitSema(cacheListSema); FioHandleCache *node = cacheListStart; while (node) { if (node->file->_cacheId == id) { if (node == cacheListStart) cacheListStart = node->next; if (node == cacheListEnd) cacheListEnd = node->prev; if (node->prev) node->prev->next = node->next; if (node->next) node->next->prev = node->prev; Ps2File *ret = node->file; delete node; cacheListLen--; SignalSema(cacheListSema); return ret; } else node = node->next; } SignalSema(cacheListSema); return NULL; }
int PS2CamReadPacket(int handle) { int *ret; int *iop_addr; WaitSema(sem); ret = (int *)&data[0]; ret[0] = handle; SifCallRpc(&cdata, PS2CAM_RPC_READPACKET, 0, (void*)(&data[0]),4,(void*)(&data[0]),4*2,0,0); if(ret[0] < 0) return ret[0]; DI(); ee_kmode_enter(); iop_addr = (int *)(0xbc000000+ret[1]); memcpy(&campacket[0],iop_addr, ret[0]); ee_kmode_exit(); EI(); //if i add a printf here, the ps2 will exit to sony's explorer SignalSema(sem); return ret[0]; }
int hddOpen(iop_file_t *f, const char *name, int flags, int mode) { int rv; apa_params_t params; hdd_file_slot_t *fileSlot; if(f->unit >= 2 || hddDevices[f->unit].status!=0) return -ENODEV; if(!(f->mode & O_DIROPEN)) if((rv=fioGetInput(name, ¶ms)) < 0) return rv; WaitSema(fioSema); if((rv=getFileSlot(¶ms, &fileSlot))==0) { if(!(f->mode & O_DIROPEN)) { if((rv=apaOpen(f->unit, fileSlot, ¶ms, flags))==0){ fileSlot->f=f; f->privdata=fileSlot; } } else { fileSlot->f=f; f->privdata=fileSlot; } } SignalSema(fioSema); return rv; }
int fioDclose(int fd) { union { int fd; int result; } arg; int res, result; if ((res = fioInit()) < 0) return res; WaitSema(_fio_completion_sema); arg.fd = fd; if ((res = SifCallRpc(&_fio_cd, FIO_F_DCLOSE, 0, &arg, sizeof arg, &arg, 4, (void *)_fio_intr, NULL)) >= 0) { result=arg.result; } else { result=res; } return result; }
int audsrv_play_audio(const char *chunk, int bytes) { int copy, maxcopy, copied; int packet_size; int sent = 0; set_error(AUDSRV_ERR_NOERROR); maxcopy = sizeof(sbuff) - sizeof(int); while (bytes > 0) { WaitSema(completion_sema); copy = MIN(bytes, maxcopy); sbuff[0] = copy; memcpy(&sbuff[1], chunk, copy); packet_size = copy + sizeof(int); SifCallRpc(&cd0, AUDSRV_PLAY_AUDIO, 0, sbuff, packet_size, sbuff, 1*4, NULL, NULL); copied = sbuff[0]; SignalSema(completion_sema); if (copied < 0) { /* there was an error */ set_error(-copied); break; } chunk = chunk + copy; bytes = bytes - copy; sent = sent + copied; } return sent; }
int fioFormat(const char *name) { union { char path[FIO_PATH_MAX]; int result; } arg; int res, result; if ((res = fioInit()) < 0) return res; WaitSema(_fio_completion_sema); strncpy(arg.path, name, FIO_PATH_MAX - 1); arg.path[FIO_PATH_MAX - 1] = 0; if ((res = SifCallRpc(&_fio_cd, FIO_F_FORMAT, 0, &arg, sizeof arg, &arg, 4, (void *)_fio_intr, NULL)) >= 0) { result=arg.result; } else { result=res; } return result; }
int fioChstat(const char *name, fio_stat_t *buf, u32 cbit) { struct _fio_chstat_arg arg; int res, result; if ((res = fioInit()) < 0) return res; WaitSema(_fio_completion_sema); arg.p.cbit = cbit; memcpy(&arg.stat, buf, sizeof(fio_stat_t)); strncpy(arg.name, name, FIO_PATH_MAX - 1); arg.name[FIO_PATH_MAX - 1] = 0; if ((res = SifCallRpc(&_fio_cd, FIO_F_CHSTAT, 0, &arg, sizeof arg, &arg, 4, (void *)_fio_intr, NULL)) >= 0) { result=arg.p.result; } else { result=res; } return result; }
int fioGetstat(const char *name, fio_stat_t *buf) { struct _fio_getstat_arg arg; int res, result; if ((res = fioInit()) < 0) return res; WaitSema(_fio_completion_sema); arg.p.buf = buf; strncpy(arg.name, name, FIO_PATH_MAX - 1); arg.name[FIO_PATH_MAX - 1] = 0; if (!IS_UNCACHED_SEG(buf)) SifWriteBackDCache(buf, sizeof(fio_stat_t)); if ((res = SifCallRpc(&_fio_cd, FIO_F_GETSTAT, 0, &arg, sizeof arg, &arg, 4, (void *)_fio_intr, NULL)) >= 0) { result=arg.p.result; } else { result=res; } return result; }
int fioDread(int fd, fio_dirent_t *buf) { struct _fio_dread_arg arg; int res, result; if ((res = fioInit()) < 0) return res; WaitSema(_fio_completion_sema); arg.p.fd = fd; arg.buf = buf; if (!IS_UNCACHED_SEG(buf)) SifWriteBackDCache(buf, sizeof(fio_dirent_t)); if ((res = SifCallRpc(&_fio_cd, FIO_F_DREAD, 0, &arg, sizeof arg, &arg, 4, (void *)_fio_intr, NULL)) >= 0) { result=arg.p.result; } else { result=res; } return result; }
static void topThread(void *arg) { int index; while(1) { WaitSema(topSema); index = topArg.requestOut & 0x1FF; topArg.requestOut = index + 1; switch(topArg.request[index].mode) { case TOP_REQ_WAKEUP: WakeupThread(topArg.request[index].data); break; case TOP_REQ_ROTATE: RotateThreadReadyQueue(topArg.request[index].data); break; case TOP_REQ_SUSPEND: SuspendThread(topArg.request[index].data); break; /* default: Kprintf("## internal error in libkernel!\n"); */ } } }
int fioOpen(const char *name, int mode) { struct _fio_open_arg arg; int res; if ((res = fioInit()) < 0) return res; WaitSema(_fio_completion_sema); arg.mode = mode; strncpy(arg.name, name, FIO_PATH_MAX - 1); arg.name[FIO_PATH_MAX - 1] = 0; /* TODO: All of these can be cleaned up (get rid of res), and an appropiate error from errno.h be used instead. */ if ((res = SifCallRpc(&_fio_cd, FIO_F_OPEN, _fio_block_mode, &arg, sizeof arg, _fio_recv_data, 4, (void *)_fio_intr, NULL)) < 0) return res; if(_fio_block_mode == FIO_NOWAIT) return 0; else return _fio_recv_data[0]; }
int NetManRpcIoctl(unsigned int command, void *args, unsigned int args_len, void *output, unsigned int length){ int result; /* void *AlignedOutput; int AlignedSize; */ WaitSema(NetManIOSemaID); ((struct NetManIoctl*)UNCACHED_SEG(TransmitBuffer))->command=command; memcpy(((struct NetManIoctl*)UNCACHED_SEG(TransmitBuffer))->args, args, args_len); ((struct NetManIoctl*)UNCACHED_SEG(TransmitBuffer))->args_len=args_len; ((struct NetManIoctl*)UNCACHED_SEG(TransmitBuffer))->output=output; ((struct NetManIoctl*)UNCACHED_SEG(TransmitBuffer))->length=length; /* !!! This entire system is not working. And I don't know why. AlignedOutput=(void*)(((unsigned int)output+0x3F)&~0x3F); AlignedSize=length-((unsigned int)AlignedOutput-(unsigned int)output); AlignedSize-=(AlignedSize&0x3F); if(AlignedSize>0){ SifWriteBackDCache(AlignedOutput, AlignedSize); } */ if((result=SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_IOCTL, SIF_RPC_M_NOWBDC, TransmitBuffer, sizeof(struct NetManIoctl), ReceiveBuffer, sizeof(struct NetManIoctlResult), NULL, NULL))>=0){ result=((struct NetManIoctlResult*)UNCACHED_SEG(ReceiveBuffer))->result; memcpy(output, ((struct NetManIoctlResult*)UNCACHED_SEG(ReceiveBuffer))->output, length); } SignalSema(NetManIOSemaID); return result; }
int fioLseek(int fd, int offset, int whence) { struct _fio_lseek_arg arg; int res, result; if ((res = fioInit()) < 0) return res; WaitSema(_fio_completion_sema); arg.p.fd = fd; arg.offset = offset; arg.whence = whence; if ((res = SifCallRpc(&_fio_cd, FIO_F_LSEEK, 0, &arg, sizeof arg, &arg, 4, (void *)_fio_intr, NULL)) >= 0) { result=arg.p.result; } else { result=res; } return result; }
static int WaitValidNetState(int (*checkingFunction)(void)){ int SemaID, retry_cycles; ee_sema_t SemaData; // Wait for a valid network status; SemaData.option = SemaData.attr = 0; SemaData.init_count = 0; SemaData.max_count = 1; if((SemaID = CreateSema(&SemaData)) < 0) return SemaID; for(retry_cycles = 0; checkingFunction() == 0; retry_cycles++) { SetAlarm(1000 * rmGetHsync(), &EthStatusCheckCb, &SemaID); WaitSema(SemaID); if(retry_cycles >= 30) //30s = 30*1000ms { DeleteSema(SemaID); return -1; } } DeleteSema(SemaID); return 0; }
int fioIoctl(int fd, int request, void *data) { struct _fio_ioctl_arg arg; int res, result; if ((res = fioInit()) < 0) return res; WaitSema(_fio_completion_sema); arg.p.fd = fd; arg.request = request; memcpy(arg.data, data, 1024); if ((res = SifCallRpc(&_fio_cd, FIO_F_IOCTL, 0, &arg, sizeof arg, &arg, 4, (void *)_fio_intr, NULL)) >= 0) { result=arg.p.result; } else { result=res; } return result; }
int fioRead(int fd, void *ptr, int size) { struct _fio_read_arg arg; int res; if ((res = fioInit()) < 0) return res; WaitSema(_fio_completion_sema); arg.fd = fd; arg.ptr = ptr; arg.size = size; arg.read_data = (struct _fio_read_data *)_fio_intr_data; if (!IS_UNCACHED_SEG(ptr)) SifWriteBackDCache(ptr, size); SifWriteBackDCache(_fio_intr_data, 128); SifWriteBackDCache(&arg, sizeof(arg)); if ((res = SifCallRpc(&_fio_cd, FIO_F_READ, _fio_block_mode, &arg, sizeof arg, _fio_recv_data, 4, (void *)_fio_read_intr, _fio_intr_data)) < 0) return res; if(_fio_block_mode == FIO_NOWAIT) return 0; else return _fio_recv_data[0]; }
static void ethInitSMB(void) { int ret; WaitSema(ethInitSemaID); ret = ethInitApplyConfig(); SignalSema(ethInitSemaID); if(ret != 0) { ethDisplayErrorStatus(); return; } // connect ethSMBConnect(); if (gNetworkStartup == 0) { // update Themes char path[256]; sprintf(path, "%sTHM", ethPrefix); thmAddElements(path, "\\", ethGameList.mode); sbCreateFolders(ethPrefix, 1); } else if (gPCShareName[0] || !(gNetworkStartup >= ERROR_ETH_SMB_OPENSHARE)) { ethDisplayErrorStatus(); } }
static int fioDataTransfer(iop_file_t *f, void *buf, int size, int mode) { hdd_file_slot_t *fileSlot=(hdd_file_slot_t *)f->privdata; if((size & 0x1FF)) return -EINVAL; size>>=9; // size/512 if(fileSlot->post+size>=0x1FF9)// no over reading size=0x1FF8-fileSlot->post; if(size!=0) { int rv=0; WaitSema(fioSema); if(ata_device_sector_io(f->unit, buf, fileSlot->post+fileSlot->parts[0].start+8, size, mode)) rv=-EIO; SignalSema(fioSema); if(rv==0) { fileSlot->post+=size; return size<<9; } return rv; } return 0; }
static void TxThread(void *arg) { int ThreadToWakeUp; while(1) { SleepThread(); if(PacketReqs.count > 0) { while(PacketReqs.count > 0) { WaitSema(NetManIOSemaID); while(SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_SEND_PACKETS, 0, &PacketReqs, sizeof(PacketReqs), &ReceiveBuffer, sizeof(ReceiveBuffer.result), &TxEndCallback, NULL) < 0){}; SignalSema(NetManIOSemaID); } } else { if(NetmanTxWaitingThread >= 0) { DI(); ThreadToWakeUp=NetmanTxWaitingThread; NetmanTxWaitingThread=-1; EI(); WakeupThread(ThreadToWakeUp); } } } }
int hddClose(iop_file_t *f) { WaitSema(fioSema); memset(f->privdata, 0, sizeof(hdd_file_slot_t)); SignalSema(fioSema); return 0; }
int Ps2ReadFile::seek(int32 offset, int origin) { WaitSema(_sema); int seekDest; int res = -1; switch (origin) { case SEEK_SET: seekDest = offset; break; case SEEK_CUR: seekDest = _filePos + offset; break; case SEEK_END: seekDest = _fileSize + offset; break; default: seekDest = -1; break; } if ((seekDest >= 0) && (seekDest <= (int)_fileSize)) { _filePos = seekDest; res = 0; } SignalSema(_sema); return res; }
//-------------------------------------------------------------- int ntpbserverEndReply(void) { int rcvSize, sndSize, recv_size, sent_size, ntpbpktSize, packetSize; // Waiting io semaphore WaitSema(ntpbserver_io_sema); // Build up ntpb packet memcpy(&ntpb_buf[0], ntpb_hdrmagic, ntpb_MagicSize); //copying NTPB Magic *((u16 *)&ntpb_buf[ntpb_MagicSize]) = 0; *((u16 *)&ntpb_buf[ntpb_MagicSize+2]) = 0xffff; packetSize = ntpb_hdrSize; // Send ntpb packet to client sent_size = 0; // fragmented packet handling while (sent_size < packetSize) { sndSize = lwip_send(client_socket, &ntpb_buf[sent_size], packetSize - sent_size, 0); if (sndSize < 0) return -1; sent_size += sndSize; } // receive the response packet from client rcvSize = recv_noblock(client_socket, &ntpb_buf[0], sizeof(ntpb_buf)); if (rcvSize <= 0) return -1; ntpbpktSize = *((u16 *)&ntpb_buf[ntpb_MagicSize]); packetSize = ntpbpktSize + ntpb_hdrSize; recv_size = rcvSize; // fragmented packet handling while (recv_size < packetSize) { rcvSize = recv_noblock(client_socket, &ntpb_buf[recv_size], sizeof(ntpb_buf) - recv_size); if (rcvSize <= 0) return -1; recv_size += rcvSize; } // parses packet if (!check_ntpb_header(ntpb_buf)) return -2; // check client reply if (*((u16 *)&ntpb_buf[ntpb_hdrSize]) != 1) return -2; // Posting semaphore for server Thread so it's able to wait for requests again SignalSema(ntpbserver_cmd_sema); // posting io semaphore SignalSema(ntpbserver_io_sema); return 0; }
int ps2_fclose(FILE *stream) { Ps2File *file = (Ps2File*)stream; if (file->_cacheId > 0) { // this is a file on the CD, could be smart to cache it FioHandleCache *newHandle = new FioHandleCache; newHandle->file = file; file->seek(0, SEEK_SET); WaitSema(cacheListSema); if (!cacheListEnd) { assert(!cacheListStart); newHandle->prev = newHandle->next = NULL; cacheListEnd = cacheListStart = newHandle; } else { assert(cacheListStart); newHandle->prev = NULL; newHandle->next = cacheListStart; cacheListStart->prev = newHandle; cacheListStart = newHandle; } cacheListLen++; checkCacheListLen(); SignalSema(cacheListSema); } else { openFileCount--; delete file; } return 0; }