// size should either be either 800 (NTSC) or 960 (PAL) void SjPCM_Enqueue(short *left, short *right, int size, int wait) { int i; struct t_SifDmaTransfer sdt; if (!sjpcm_inited) return; sdt.src = (void *)left; sdt.dest = (void *)(pcmbufl + bufpos); sdt.size = size*2; sdt.attr = 0; FlushCache(0); i = SifSetDma(&sdt, 1); // start dma transfer while ((wait != 0) && (SifDmaStat(i) >= 0)); // wait for completion of dma transfer sdt.src = (void *)right; sdt.dest = (void *)(pcmbufr + bufpos); sdt.size = size*2; sdt.attr = 0; FlushCache(0); i = SifSetDma(&sdt, 1); while ((wait != 0) && (SifDmaStat(i) >= 0)); sbuff[0] = size; SifCallRpc(&cd0,SJPCM_ENQUEUE,0,(void*)(&sbuff[0]),64,(void*)(&sbuff[0]),64,0,0); bufpos = sbuff[3]; }
int fileXio_getstat_RPC(char *filename, void* eeptr) { iox_stat_t localStat; int res = 0; struct t_SifDmaTransfer dmaStruct; int intStatus; // interrupt status - for dis/en-abling interrupts res = getstat(filename, &localStat); if(res >= 0) { // DMA localStat to the address specified by eeptr // setup the dma struct dmaStruct.src = &localStat; dmaStruct.dest = eeptr; dmaStruct.size = sizeof(iox_stat_t); dmaStruct.attr = 0; // Do the DMA transfer CpuSuspendIntr(&intStatus); SifSetDma(&dmaStruct, 1); CpuResumeIntr(intStatus); } return(res); }
int fileXio_GetDeviceList_RPC(struct fileXioDevice* ee_devices, int eecount) { int device_count = 0; iop_device_t **devices = GetDeviceList(); struct fileXioDevice local_devices[FILEXIO_MAX_DEVICES]; while (devices[device_count] && device_count < eecount) { iop_device_t *device = devices[device_count]; strncpy(local_devices[device_count].name, device->name, 128); local_devices[device_count].name[127] = '\0'; local_devices[device_count].type = device->type; local_devices[device_count].version = device->version; strncpy(local_devices[device_count].desc, device->desc, 128); local_devices[device_count].desc[127] = '\0'; ++device_count; } if (device_count) { struct t_SifDmaTransfer dmaStruct; int intStatus; // interrupt status - for dis/en-abling interrupts dmaStruct.src = local_devices; dmaStruct.dest = ee_devices; dmaStruct.size = sizeof(struct fileXioDevice) * device_count; dmaStruct.attr = 0; // Do the DMA transfer CpuSuspendIntr(&intStatus); SifSetDma(&dmaStruct, 1); CpuResumeIntr(intStatus); } return device_count; }
int sndLoadSample(void *buf, u32 spuaddr, int size) { void *iopbuf; int id, iopfree; SifDmaTransfer_t sifdma; iopfree = sndQueryMaxFreeMemSize()/2; if (size>iopfree) { return(-1); } iopbuf = SifAllocIopHeap(size); if (iopbuf==0) return(-1); FlushCache(0); sifdma.src = buf; sifdma.dest = iopbuf; sifdma.size = size; sifdma.attr = 0; id = SifSetDma(&sifdma, 1); while(SifDmaStat(id) >= 0);; FlushCache(0); SdVoiceTrans(0, SD_TRANS_WRITE, iopbuf, (void*)spuaddr, size); SdVoiceTransStatus(0, 1); SifFreeIopHeap(iopbuf); return(size); }
int audsrv_load_adpcm(audsrv_adpcm_t *adpcm, void *buffer, int size) { void* iop_addr; SifDmaTransfer_t sifdma; int id, ret; iop_addr = SifAllocIopHeap(size); if (iop_addr == 0) { return -AUDSRV_ERR_OUT_OF_MEMORY; } sifdma.src = buffer; sifdma.dest = iop_addr; sifdma.size = size; sifdma.attr = 0; /* send by dma */ while((id = SifSetDma(&sifdma, 1)) == 0); while(SifDmaStat(id) >= 0); WaitSema(completion_sema); sbuff[0] = (int)iop_addr; sbuff[1] = size; sbuff[2] = (int)adpcm; /* use as id */ SifCallRpc(&cd0, AUDSRV_LOAD_ADPCM, 0, sbuff, 12, sbuff, 16, NULL, NULL); if(sbuff[0] != 0) { adpcm->buffer = 0; ret = sbuff[0]; } else { adpcm->buffer = buffer; adpcm->size = size; adpcm->pitch = sbuff[1]; adpcm->loop = sbuff[2]; adpcm->channels = sbuff[3]; ret = AUDSRV_ERR_NOERROR; } SignalSema(completion_sema); SifFreeIopHeap(iop_addr); return ret; }
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); } } }
unsigned int sendCmd(unsigned int pos, int mode, SifCmdHdr *cp, int ps, void *src, void *dst, int size){ u32 x; struct sifman_DMA dma[2]; register int count, y; if (ps<16 || ps>112) return 0; count=0; if (size>0){ count=1; dma[0].addr=dst; dma[0].size=size; dma[0].attr=0; dma[0].data=src; cp->daddr=(u32)dst; cp->dsize=size; }else{ cp->daddr=0; cp->dsize=0; } count++; cp->psize=ps; cp->fcode=pos; dma[count-1].data=cp; dma[count-1].attr=SIF_DMA_INT_O; //calls SIF0 handler dma[count-1].size=ps; //on EE side after transfer;) dma[count-1].addr=cmd_common.saddr; if (mode & 1) //interrupt mode return SifSetDma(dma, count); else{ CpuSuspendIntr(&x); y=SifSetDma(dma, count); CpuResumeIntr(x); return y; } }
///////////////////////////////////////////////////////////////////////[15] void SifExecRequest(struct sifcmd_RPC_SERVER_DATA *sd){ u32 x; register int size, id, count, i; register void *buff; RPC_PACKET_END *epacket; struct sifman_DMA dma[2]; size=0; if (buff=sd->func(sd->fno, sd->buff, sd->size)) size=sd->rsize; CpuSuspendIntr(&x); epacket=(RPC_PACKET_END *)rpc_get_fpacket(&rpc_common); CpuResumeIntr(x); epacket->command=0x8000000A; epacket->client=sd->client; count=0; if (sd->rmode){ while (SifSendCmd(0x80000008, epacket, 0x40, buff, sd->receive, size)==0); return; }else{ epacket->packet.pid=0; epacket->packet.rec_id=0; if (size>0){ count=1; dma[count-1].data=buff; dma[count-1].size=size; dma[count-1].attr=0; dma[count-1].addr=sd->receive; } count++; dma[count-1].data=epacket; dma[count-1].size=0x40; dma[count-1].attr=0; dma[count-1].addr=sd->pkt_addr; do{ CpuSuspendIntr(&x); id=SifSetDma(dma, count); CpuResumeIntr(x); if (id) break; i=0xFFFF; do --i; while (i!=-1); } while (id==0); } }
int iop_heap_dma_upload(void *src,u32 dst,int size) { int i=0,len=0,size2; u8 *pkt; int ret=0; int ret2=0; int p=0; int cont1=0; while(size>0) // send data with src unaligned { if(size>512) size2=512; else size2=size; CD_memcpy2(memsend,((unsigned char *) src)+p,size2); do { FlushCache(0); /* build packet */ pkt = send_buffer2; PUSHDATA( u32, pkt, (u32)memsend, i); pkt += i; len += i; PUSHDATA( u32, pkt, dst, i); pkt += i; len += i; PUSHDATA( int, pkt, size2, i); pkt += i; len += i; PUSHDATA( int, pkt, 0, i); pkt += i; len += i; ret = SifSetDma((SifDmaTransfer_t*)send_buffer2,1); if(ret==0) {nopdelay();cont1++;} if(ret==0 && cont1>=3) {cont1=0;SifSetDChain();} }while(ret==0); // modificado por Hermes while((ret2 = SifDmaStat(ret))>=0); FlushCache(0); size-=size2; p+=size2; dst+=size2; } return (ret2 < -1); }
static u32 _SifSendCmd(int cid, int mode, void *pkt, u32 pktsize, void *src, void *dest, int size) { SifDmaTransfer_t dmat[2]; SifCmdHeader_t *header; int count = 0; pktsize &= 0xff; if (pktsize > CMD_PACKET_DATA_MAX) return 0; header = (SifCmdHeader_t *)pkt; header->cid = cid; header->size = pktsize; header->dest = NULL; if (size > 0) { header->size = pktsize | (size << 8); header->dest = dest; if (mode & 4) /* if mode is & 4, flush reference cache */ SifWriteBackDCache(src, size); dmat[count].src = src; dmat[count].dest = dest; dmat[count].size = size; dmat[count].attr = 0; count++; } dmat[count].src = pkt; dmat[count].dest = _sif_cmd_data.iopbuf; dmat[count].size = pktsize; dmat[count].attr = 0x40 | SIF_DMA_INT_O; count++; SifWriteBackDCache(pkt, pktsize); if (mode & 1) /* INTERRUPT DMA TRANSFER */ return iSifSetDma(dmat, count); else return SifSetDma(dmat, count); }
int SifIopReset(const char *arg, int mode) { struct _iop_reset_pkt reset_pkt; /* Implicitly aligned. */ struct t_SifDmaTransfer dmat; _iop_reboot_count++; // increment reboot counter to allow RPC clients to detect unbinding! SifStopDma(); memset(&reset_pkt, 0, sizeof reset_pkt); reset_pkt.header.size = sizeof reset_pkt; reset_pkt.header.cid = 0x80000003; reset_pkt.mode = mode; if (arg != NULL) { strncpy(reset_pkt.arg, arg, RESET_ARG_MAX); reset_pkt.arg[RESET_ARG_MAX] = '\0'; reset_pkt.arglen = strlen(reset_pkt.arg) + 1; } dmat.src = &reset_pkt; dmat.dest = (void *)SifGetReg(SIF_REG_SUBADDR); dmat.size = sizeof reset_pkt; dmat.attr = 0x40 | SIF_DMA_INT_O; SifWriteBackDCache(&reset_pkt, sizeof reset_pkt); SifSetReg(SIF_REG_SMFLAG, 0x40000); if (!SifSetDma(&dmat, 1)) return 0; SifSetReg(SIF_REG_SMFLAG, 0x10000); SifSetReg(SIF_REG_SMFLAG, 0x20000); SifSetReg(0x80000002, 0); SifSetReg(0x80000000, 0); return 1; }
//Only one thread can enter this critical section! static void EnQFrame(const void *frame, unsigned int length) { SifDmaTransfer_t dmat; int dmat_id; //Write back D-cache, before performing a DMA transfer. SifWriteBackDCache((void*)frame, length); //Wait for a spot to be freed up. while(PacketReqs.count + 1 >= NETMAN_RPC_BLOCK_SIZE) { NetmanTxWaitingThread = GetThreadId(); WakeupThread(TxThreadID); SleepThread(); } //Transfer to IOP RAM dmat.src = (void*)frame; dmat.dest = &IOPFrameBuffer[IOPFrameBufferWrPtr * NETMAN_MAX_FRAME_SIZE]; dmat.size = length; dmat.attr = 0; while((dmat_id = SifSetDma(&dmat, 1))==0){}; //Record the frame length. PacketReqs.length[IOPFrameBufferWrPtr] = length; DI(); //Update the frame count. PacketReqs.count++; EI(); //Increase write pointer by one position. IOPFrameBufferWrPtr = (IOPFrameBufferWrPtr + 1) % NETMAN_RPC_BLOCK_SIZE; //Signal the transmission thread that there are more frames to transmit. WakeupThread(TxThreadID); //Ensure that the frame is copied over before returning (so that the buffer can be freed). while(SifDmaStat(dmat_id) >= 0){}; }
//int io_ioctl2(int fd, int cmd, void *arg, unsigned int arglen, void *bufp, // unsigned int buflen); void* fileXioRpc_Ioctl2(unsigned int* sbuff) { struct fxio_ioctl2_packet *packet = (struct fxio_ioctl2_packet *)sbuff; struct fxio_ctl_return_pkt *ret_buf = (struct fxio_ctl_return_pkt *)rwbuf; SifDmaTransfer_t dmatrans; int intStatus; int ret; #ifdef DEBUG printf("RPC ioctl2 Request\n"); #endif ret = ioctl2(packet->fd, packet->cmd, packet->arg, packet->arglen, ret_buf->buf, packet->buflen); // Transfer buffer back to EE if(packet->buflen != 0) { dmatrans.src = ret_buf; dmatrans.dest = packet->intr_data; dmatrans.attr = 0; dmatrans.size = sizeof(struct fxio_ctl_return_pkt); ret_buf->dest = packet->buf; // EE is expecting data.. on error, simply use size of 0 so no data is copied. if(ret >= 0) ret_buf->len = packet->buflen; else ret_buf->len = 0; CpuSuspendIntr(&intStatus); SifSetDma(&dmatrans, 1); CpuResumeIntr(intStatus); } sbuff[0] = ret; return sbuff; }
/** * Send SIF1 command from EE to IOP using DMA. * @param src EE memory source address. * @param dest IOP memory destination address. * @param size Size of data to be copied in bytes. 0, if nothing should be * transfered. * @return 0, on error. * @return ID, describing DMA transfers. */ u32 sif_cmd_send(u32 fid, u32 flags, void *packet, u32 packet_size, void *src, void *dest, u32 size) { tge_sifdma_transfer_t transfer[2]; tge_sifcmd_header_t *header = packet; u32 count = 0; if (packet_size > CMD_PACKET_DATA_MAX) { return -E_LIB_INVALID_ARG; } header = (tge_sifcmd_header_t *) packet; header->fid = fid; header->size = packet_size; header->dest = NULL; if (size > 0) { header->dest = dest; header->size = packet_size | (size << 8); if (flags & 4) { SifWriteBackDCache(src, size); } transfer[count].src = src; transfer[count].dest = dest; transfer[count].size = size; transfer[count].attr = 0; count++; } else { header->option = 0; } transfer[count].src = packet; transfer[count].dest = _sif_cmd_data.iopbuf; transfer[count].size = packet_size; transfer[count].attr = TGE_SIFDMA_ATTR_ERT | TGE_SIFDMA_ATTR_INT_O; count++; SifWriteBackDCache(packet, packet_size); return SifSetDma(transfer, count); }
int fileXio_dread_RPC(int fd, void* eeptr) { int res=0; iox_dirent_t localDir; struct t_SifDmaTransfer dmaStruct; int intStatus; // interrupt status - for dis/en-abling interrupts res = dread(fd, &localDir); if (res > 0) { // DMA localStat to the address specified by eeptr // setup the dma struct dmaStruct.src = &localDir; dmaStruct.dest = eeptr; dmaStruct.size = 64+256; dmaStruct.attr = 0; // Do the DMA transfer CpuSuspendIntr(&intStatus); SifSetDma(&dmaStruct, 1); CpuResumeIntr(intStatus); } return(res); }
// This is the getdir for use by the EE RPC client // It DMA's entries to the specified buffer in EE memory int fileXio_GetDir_RPC(const char* pathname, struct fileXioDirEntry dirEntry[], unsigned int req_entries) { int matched_entries; int fd, res; iox_dirent_t dirbuf; struct fileXioDirEntry localDirEntry; int intStatus; // interrupt status - for dis/en-abling interrupts struct t_SifDmaTransfer dmaStruct; int dmaID; dmaID = 0; #ifdef DEBUG printf("RPC GetDir Request\n"); printf("dirname: %s\n",pathname); #endif matched_entries = 0; fd = dopen(pathname); if (fd <= 0) { return fd; } { res = 1; while (res > 0) { memset(&dirbuf, 0, sizeof(dirbuf)); res = dread(fd, &dirbuf); if (res > 0) { // check for too many entries if (matched_entries == req_entries) { close(fd); return (matched_entries); } // wait for any previous DMA to complete // before over-writing localDirEntry while(SifDmaStat(dmaID)>=0); DirEntryCopy(&localDirEntry, &dirbuf); // DMA localDirEntry to the address specified by dirEntry[matched_entries] // setup the dma struct dmaStruct.src = &localDirEntry; dmaStruct.dest = &dirEntry[matched_entries]; dmaStruct.size = sizeof(struct fileXioDirEntry); dmaStruct.attr = 0; // Do the DMA transfer CpuSuspendIntr(&intStatus); dmaID = SifSetDma(&dmaStruct, 1); CpuResumeIntr(intStatus); matched_entries++; } // if res } // while } // if dirs and files // cleanup and return # of entries close(fd); return (matched_entries); }
int fileXio_Read_RPC(int infd, char *read_buf, int read_size, void *intr_data) { int srest; int erest; int asize; int abuffer; int rlen; int total; int readlen; int status; struct t_SifDmaTransfer dmaStruct; void *buffer; void *aebuffer; int intStatus; // interrupt status - for dis/en-abling interrupts int read_buf2 = (int)read_buf; total = 0; if(read_size < 64) { srest = read_size; erest = asize = abuffer = 0; buffer = read_buf; aebuffer = 0; }else{ if ((read_buf2 & 0x3F) == 0) srest=0; else srest=(int)RDOWN_64(read_buf2) - read_buf2 + 64; buffer = read_buf; abuffer = read_buf2 + srest; aebuffer=(void *)RDOWN_64(read_buf2 + read_size); asize = (int)aebuffer - (int)abuffer; erest = (read_buf2 + read_size) - (int)aebuffer; } if (srest>0) { if (srest!=(rlen=read(infd, rests.sbuffer, srest))) { total += srest = (rlen>0 ? rlen:0); goto EXIT; } else total += srest; } status=0; while (asize>0) { readlen=MIN(RWBufferSize, asize); while(SifDmaStat(status)>=0); rlen=read(infd, rwbuf, readlen); if (readlen!=rlen){ if (rlen<=0)goto EXIT; dmaStruct.dest=(void *)abuffer; dmaStruct.size=rlen; dmaStruct.attr=0; dmaStruct.src =rwbuf; CpuSuspendIntr(&intStatus); SifSetDma(&dmaStruct, 1); CpuResumeIntr(intStatus); total +=rlen; goto EXIT; }else{ //read ok total += rlen; asize -=rlen; dmaStruct.dest=(void *)abuffer; abuffer +=rlen; dmaStruct.size=rlen; dmaStruct.attr=0; dmaStruct.src =rwbuf; CpuSuspendIntr(&intStatus); status=SifSetDma(&dmaStruct, 1); CpuResumeIntr(intStatus); } } if (erest>0) { rlen = read(infd, rests.ebuffer, erest); total += (rlen>0 ? rlen : 0); } EXIT: rests.ssize=srest; rests.esize=erest; rests.sbuf =buffer; rests.ebuf =aebuffer; dmaStruct.src =&rests; dmaStruct.size=sizeof(rests_pkt); dmaStruct.attr=0; dmaStruct.dest=intr_data; CpuSuspendIntr(&intStatus); SifSetDma(&dmaStruct, 1); CpuResumeIntr(intStatus); return (total); }