コード例 #1
0
ファイル: sbp2_driver.c プロジェクト: scuriumk/ps2sdk
int ieee1394_SendCommandBlockORB(struct SBP2Device *dev, struct CommandDescriptorBlock *firstCDB){
	int result, retries;
	struct sbp2_pointer address;

	memset((unsigned char *)statusFIFO, 0, sizeof(statusFIFO));

	address.low=(u32)firstCDB;
	address.NodeID=dev->InitiatorNodeID;
	address.high=0;

	retries=0;

	/* Write the pointer to the first ORB in the fetch agent's NEXT_ORB register. */
	while((result=iLinkTrWrite(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low+0x08, &address, 8))<0){
		XPRINTF("Error writing to the Fetch Agent's ORB_POINTER register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low+0x08, result);

		DelayThread(200000);
		ieee1394_ResetFetchAgent(dev);

		retries++;
		if(retries>3) return(-1);
	}

#if 0
	/* Write a value to the fetch agent's DOORBELL register. */
	result=1;
	if((result=iLinkTrWrite(dev->trContext, dev->CommandBlockAgent_high, dev->CommandBlockAgent_low+0x10, &result, 4))<0){
		XPRINTF("Error writing to the Fetch Agent's DOORBELL register @ 0x%08lx %08lx. Code: %d.\n", dev->CommandBlockAgent_high, dev->CommandBlockAgent_low+0x10, result);
		return -2;
	}
#endif

	return 1;
}
コード例 #2
0
ファイル: ioptrap.c プロジェクト: AKuHAK/ps2sdk
void main_thread(void *unused) {
    int i = 0;

    DelayThread(1000*1000);

    printf("IOP: about to trap!\n");
    trigger();
    printf("IOP: back from trap!\n");
    while(1) {
        printf("IOP: still running %d\n", i++);
        DelayThread(2000*1000);
	if (i == 10)
	    break;
    }
    ExitDeleteThread();
}
コード例 #3
0
ファイル: sbp2_driver.c プロジェクト: scuriumk/ps2sdk
/* This is declared as inline as there is only one call to it. */
static inline int ieee1394_Sync_withTimeout(u32 n500mSecUnits){
/*	iop_sys_clock_t timeout_clk;
	u32 ef_result;

	USec2SysClock(n500mSecUnits*500000, &timeout_clk);

	SetAlarm(&timeout_clk, &alarm_cb, NULL);
	WaitEventFlag(sbp2_event_flag, WRITE_REQ_INCOMING|ERROR_TIME_OUT, WEF_OR|WEF_CLEAR, &ef_result);

	if(ef_result&ERROR_TIME_OUT){
		XPRINTF("-=Time out=-\n");
		return(-1);
	}
	else CancelAlarm(&alarm_cb, NULL); */

	unsigned int i=0;

	while(RESP_SRC(((struct sbp2_status *)statusFIFO)->status)==0){
		if(i>n500mSecUnits*10000){
			XPRINTF("-=Time out=-\n");
			return(-1);
		}

		DelayThread(50);
		i++;
	};

	return(ProcessStatus());
}
コード例 #4
0
ファイル: mcserv.c プロジェクト: AKuHAK2/ps2sdk
//--------------------------------------------------------------
int _McChDir(void *rpc_buf)
{
	g_nameParam_t *nP = (g_nameParam_t *)rpc_buf;
	register int status, r;
	SifDmaTransfer_t dmaStruct;
	int intStatus;

#ifdef DEBUG
	DPRINTF("mcserv: _McChDir port%d slot%d newdir %s\n", nP->port, nP->slot, nP->name);
#endif

	r = McChDir(nP->port, nP->slot, nP->name, (char *)mcserv_buf);

	dmaStruct.src = (void *)mcserv_buf;
	dmaStruct.dest = (void *)nP->mcT;
	dmaStruct.size = 1024;
	dmaStruct.attr = 0;

	CpuSuspendIntr(&intStatus);
	status = sceSifSetDma(&dmaStruct, 1);
	CpuResumeIntr(intStatus);

	while (sceSifDmaStat(status) >= 0)
		DelayThread(100);

	return r;
}
コード例 #5
0
ファイル: iLink_internal.c プロジェクト: AKuHAK/ps2sdk
int iLinkResetHW(void){
	ShutDownDMAChannels();

    	/* Turn off, and then turn back on the LINK and PHY. If this is not done, the iLink hardware might not function correctly on some consoles. :( */
	ILINKRegisterBase->UnknownRegister7C=0x40;	/* Shut down. */
	DelayThread(400000);
	ILINKRegisterBase->UnknownRegister7C=0;

	/* If the LINK is off, switch it on. */
	if(!(ILINKRegisterBase->ctrl2&iLink_CTRL2_LPSEn)) ILINKRegisterBase->ctrl2=iLink_CTRL2_LPSEn;

	/* Wait for the clock to stabilize. */
	while(!(ILINKRegisterBase->ctrl2&iLink_CTRL2_SOK)) DelayThread(50);

	return 0;
}
コード例 #6
0
ファイル: ps2ip.c プロジェクト: ylyking/ps2sdk
static void TimerThread(void* pvArg)
{
	while (1)
	{
		//TCP timer.
		tcp_tmr();

		//ARP timer.
		iTimerARP+=TCP_TMR_INTERVAL;
		if	(iTimerARP>=ARP_TMR_INTERVAL)
		{
			iTimerARP-=ARP_TMR_INTERVAL;
			etharp_tmr();
		}

#if		defined(PS2IP_DHCP)

		//DHCP timer.

		iTimerDHCP+=TCP_TMR_INTERVAL;
		if ((iTimerDHCP-TCP_TMR_INTERVAL)/DHCP_FINE_TIMER_MSECS!=iTimerDHCP/DHCP_FINE_TIMER_MSECS)
		{
			dhcp_fine_tmr();
		}

		if (iTimerDHCP>=DHCP_COARSE_TIMER_SECS*1000)
		{
			iTimerDHCP-=DHCP_COARSE_TIMER_SECS*1000;
			dhcp_coarse_tmr();
		}
#endif

		DelayThread(TCP_TMR_INTERVAL*250);	/* Note: The IOP's DelayThread() function isn't accurate, and the actual timming accuracy is about 25% of the specified value. */
	}
}
コード例 #7
0
ファイル: mcserv.c プロジェクト: AKuHAK2/ps2sdk
//--------------------------------------------------------------
int _McGetInfo2(void *rpc_buf)
{
	g_descParam_t *dP = (g_descParam_t *)rpc_buf;
	register int status, mc_free, r;
	g_endParam2_t eP;
	SifDmaTransfer_t dmaStruct;
	int intStatus;

#ifdef DEBUG
	DPRINTF("mcserv: _McGetInfo2 port%d slot%d\n", dP->port, dP->slot);
#endif

	mc_free = 0;

	r = McDetectCard2(dP->port, dP->slot);

	if (dP->origin > 0)
		eP.fastIO1_size = McGetMcType(dP->port, dP->slot);

	if (r < -1) {
		eP.fastIO2_size = 0;
		eP.flag = 0;
		goto dma_transfer;
	}

	if (dP->offset > 0) {
		mc_free = McGetFreeClusters(dP->port, dP->slot);

		if (mc_free < 0)
			eP.fastIO2_size = 0;
		else
			eP.fastIO2_size = mc_free;
	}

	if (dP->size > 0) {
		eP.flag = 0;
		if (McGetFormat(dP->port, dP->slot) > 0)
			eP.flag = 1;
	}

dma_transfer:

	dmaStruct.src = (void *)&eP;
	dmaStruct.dest = (void *)dP->param;
	dmaStruct.size = sizeof (g_endParam2_t);
	dmaStruct.attr = 0;

	CpuSuspendIntr(&intStatus);
	status = sceSifSetDma(&dmaStruct, 1);
	CpuResumeIntr(intStatus);

	while (sceSifDmaStat(status) >= 0)
		DelayThread(100);

	if (mc_free < 0)
		return mc_free;

	return r;
}
コード例 #8
0
ファイル: sbp2_driver.c プロジェクト: scuriumk/ps2sdk
int ieee1394_Sync(void){
//	WaitEventFlag(sbp2_event_flag, WRITE_REQ_INCOMING, WEF_AND|WEF_CLEAR, NULL);

	while(RESP_SRC(((struct sbp2_status *)statusFIFO)->status)==0){
		DelayThread(50);
	};

	return(ProcessStatus());
}
コード例 #9
0
ファイル: ps2ip.c プロジェクト: AzagraMac/PS2_SDK
static void
TimerThread(void* pvArg)
{
	while (1)
	{
		tcpip_callback(Timer,NULL);
		DelayThread(TCP_TMR_INTERVAL*1000);
	}
}
コード例 #10
0
ファイル: sys_arch.c プロジェクト: AzagraMac/PS2_SDK
void sys_mbox_post(sys_mbox_t mbid, void *sys_msg)
{
	arch_message *msg;
	//This function should only be invoked by ps2ip_input. It'll be invoked from an interrupt-context and the pMBox is non-full.

    // FIXME: Not sure if this is the best thing to do, will this lock up the only thread which will free up a message??
    while((msg = alloc_msg()) == NULL) { DelayThread(100); }

    msg->sys_msg = sys_msg;
    SendMbx(mbid, (iop_message_t *) msg);
}
コード例 #11
0
ファイル: codyvdfs.c プロジェクト: 86400/scummvm
int checkDiscReady(int retries) {
	if (retries == -1) {
		if (CdDiskReady(0) == 2) // block until drive ready, should always return 2
			return 0;
	} else {
		do {
			if (CdDiskReady(1) == 2)
				return 0;
			DelayThread(10 * 1000);
		} while (--retries >= 0);
	}
	return -1;
}
コード例 #12
0
ファイル: main.c プロジェクト: scuriumk/ps2sdk
int _start(int argc, char** argv)
{
  if(InitFAT() != 0)
  {
	printf("Error initializing FAT driver!\n");
	return MODULE_NO_RESIDENT_END;
  }

  init_ieee1394DiskDriver();

  DelDrv(dev_name);
  AddDrv(&device_driver);

#if 0
   iop_sys_clock_t lTime;
   u32 lSecStart, lUSecStart;
   u32 lSecEnd,   lUSecEnd, nbytes;
   int fd, size, bytesToRead, block_size;

   printf("trying to open file...");
   while((fd=open("sd0:PS2ESDL/SLPM_55052_00.pdi", O_RDONLY))<0){DelayThread(2000);};
   nbytes=size=lseek(fd, 0, SEEK_END)/4;
   block_size=2048*512;
   lseek(fd, 0, SEEK_SET);

   printf("Read test start\n" );

   GetSystemTime ( &lTime );
   SysClock2USec ( &lTime, &lSecStart, &lUSecStart );

	void *buffer;
	if((buffer=malloc(block_size))==NULL) printf("Unable to allocate memory. :(\n");
	printf("Read test: %p.\n", buffer);
	while(size>0){
		bytesToRead=(size>(block_size))?(block_size):size;
		read(fd, buffer, bytesToRead);
		size-=bytesToRead;
	}
	free(buffer);
	printf("Completed.\n");

   GetSystemTime ( &lTime );
   SysClock2USec ( &lTime, &lSecEnd, &lUSecEnd );
   close(fd);

   printf("Done: %lu %lu/%lu %lu\n", lSecStart, lUSecStart, lSecEnd, lUSecEnd );
   printf("KB: %ld, time: %ld, Approximate KB/s: %ld.\n", (nbytes/1024), (lSecEnd -lSecStart), (nbytes/1024)/(lSecEnd -lSecStart));
#endif

  return MODULE_RESIDENT_END;
}
コード例 #13
0
ファイル: mcserv.c プロジェクト: AKuHAK2/ps2sdk
//--------------------------------------------------------------
int _McGetDir(void *rpc_buf)
{
	g_nameParam_t *nP = (g_nameParam_t *)rpc_buf;
	register int status, file_entries, flags, r;
	SifDmaTransfer_t dmaStruct;
	int intStatus;

#ifdef DEBUG
	DPRINTF("mcserv: _McGetDir port%d slot%d dir %s flags %d maxent %d mcT addr %x\n", nP->port, nP->slot, nP->name, nP->flags, nP->maxent, (int)nP->mcT);
#endif

	status = 0;
	file_entries = 0;
	flags = nP->flags;

	nP->maxent--;

	while (nP->maxent > -1) {

		r = McGetDir(nP->port, nP->slot, nP->name, flags & 0xffff, 1, (mcTable_t *)mcserv_buf);
		if (r < 0)
			return r;
		if (r == 0)
			goto dma_wait;

		file_entries++;

		dmaStruct.src = (void *)mcserv_buf;
		dmaStruct.dest = (void *)nP->mcT;
		dmaStruct.size = sizeof (mcTable_t);
		dmaStruct.attr = 0;

		CpuSuspendIntr(&intStatus);
		status = sceSifSetDma(&dmaStruct, 1);
		CpuResumeIntr(intStatus);

		flags = 1;
		nP->mcT++;
		nP->maxent--;
	}

dma_wait:
	if (status == 0)
		return file_entries;

	while (sceSifDmaStat(status) >= 0)
		DelayThread(100);

	return file_entries;
}
コード例 #14
0
ファイル: smap.c プロジェクト: sp193/ps2sdk
static void _smap_write_phy(volatile u8 *emac3_regbase, unsigned char address, unsigned short int value){
	unsigned int i, PHYRegisterValue;

	PHYRegisterValue=(address&SMAP_E3_PHY_REG_ADDR_MSK)|SMAP_E3_PHY_WRITE|((SMAP_DsPHYTER_ADDRESS&SMAP_E3_PHY_ADDR_MSK)<<SMAP_E3_PHY_ADDR_BITSFT);
	PHYRegisterValue|=((unsigned int)value)<<SMAP_E3_PHY_DATA_BITSFT;

	i=0;
	SMAP_EMAC3_SET(SMAP_R_EMAC3_STA_CTRL, PHYRegisterValue);

	for(; !(SMAP_EMAC3_GET(SMAP_R_EMAC3_STA_CTRL)&SMAP_E3_PHY_OP_COMP); i++){
		DelayThread(1000);
		if(i>=100) break;
	}

	if(i>=100) printf("smap: %s: > %d ms\n", "_smap_write_phy", i);
}
コード例 #15
0
ファイル: rpcfs.c プロジェクト: 0xf1sh/scummvm
void *driveStandby(void *data) {
	int type;
	if (CdStandby() == 1) {
		if (CdSync(0) == 0) {
			*(int *)data = CdGetError();
		} else
			*(int *)data = -0x100;
	} else
		*(int *)data = -0x101;

	do {	// wait until drive detected disc type
		type = CdGetDiskType();
		if (DISC_NOT_READY(type))
			DelayThread(10 * 1000);
	} while (DISC_NOT_READY(type));
	printf("Standby: Disc type: %02X\n", type);

	return data;
}
コード例 #16
0
ファイル: ata.c プロジェクト: joshdekock/jim-ps2ware
static void dma_stop(int val)
{
	USE_SPD_REGS;
	u8 if_ctrl;

	_sw(0, DEV9_DMAC_CHCR);

	SPD_REG8(SPD_R_XFR_CTRL) = 0;
	SPD_REG8(SPD_R_IF_CTRL) = SPD_REG8(SPD_R_IF_CTRL) & 0xfb;

	if (val) {
		if_ctrl = SPD_REG8(SPD_R_IF_CTRL);
		SPD_REG8(SPD_R_IF_CTRL) = SPD_IF_ATA_RESET;
		DelayThread(100);
		SPD_REG8(SPD_R_IF_CTRL) = if_ctrl;
	}

	/*M_PRINTF("ATA DMA force break\n");*/
}
コード例 #17
0
ファイル: smap.c プロジェクト: sp193/ps2sdk
static int _smap_read_phy(volatile u8 *emac3_regbase, unsigned int address){
	unsigned int i, PHYRegisterValue;
	int result;

	PHYRegisterValue=(address&SMAP_E3_PHY_REG_ADDR_MSK)|SMAP_E3_PHY_READ|((SMAP_DsPHYTER_ADDRESS&SMAP_E3_PHY_ADDR_MSK)<<SMAP_E3_PHY_ADDR_BITSFT);

	i=0;
	result=0;
	SMAP_EMAC3_SET(SMAP_R_EMAC3_STA_CTRL, PHYRegisterValue);

	do{
		if(SMAP_EMAC3_GET(SMAP_R_EMAC3_STA_CTRL)&SMAP_E3_PHY_OP_COMP){
			if(SMAP_EMAC3_GET(SMAP_R_EMAC3_STA_CTRL)&SMAP_E3_PHY_OP_COMP){
				if((result=SMAP_EMAC3_GET(SMAP_R_EMAC3_STA_CTRL))&SMAP_E3_PHY_OP_COMP){
					result>>=SMAP_E3_PHY_DATA_BITSFT;
					break;
				}
			}
		}

		DelayThread(1000);
		i++;
	}while(i<100);
コード例 #18
0
ファイル: codyvdfs.c プロジェクト: 86400/scummvm
int initDisc(void) {
	int type, sector, discType;
	ISOPvd *pvd;
	CdRMode rmode = { 16, 0, CdSect2048, 0 };
	ISOPathTableRecord *rootRec;

	if (checkDiscReady(0) < 0) {
		printf("disc not ready\n");
		mediaType = DISC_UNKNOWN; // retry later
		return -1;
	}

	do {	// wait until drive detected disc type
		type = CdGetDiskType();
		if (DISC_NOT_READY(type))
			DelayThread(10 * 1000);
	} while (DISC_NOT_READY(type));

	if (type == CdDiskIllegal) {
		printf("Illegal disc type\n");
		mediaType = DISC_NONE;
		return -1;
	}
	if (type == CdDiskNone) {
		printf("Tray empty\n");
		mediaType = DISC_NONE;
		return -1;
	}

	discType = DISC_DVD;
	switch (type) {
		case CdDiskCDPS1:
		case CdDiskCDDAPS1:
		case CdDiskCDPS2:
		case CdDiskCDDAPS2:
		case CdDiskCDDA:
			discType = DISC_MODE2;
			rmode.datapattern = CdSect2340;
		default:
			break;
	}

	for (sector = 16; sector < 32; sector++) {
		printf("sec %d\n", sector);
		if (cdReadSectors(sector, 1, cacheBuf, &rmode) == 0) {
			if (discType == DISC_DVD)
				pvd = (ISOPvd *)cacheBuf;
			else {
				switch (cacheBuf[3]) {
					case 1:
						discType = DISC_MODE1;
						printf("Disc: Mode1\n");
						pvd = (ISOPvd *)(cacheBuf + 4);
						break;
					case 2:
						discType = DISC_MODE2;
						printf("Disc: Mode2\n");
						pvd = (ISOPvd *)(cacheBuf + 12);
						break;
					default:
						DBG_PRINTF("Unknown Sector Type %02X\n", cacheBuf[3]);
						return -1;
				}
			}
			rmode.datapattern = CdSect2048;
			if ((pvd->type == 1) && (memcmp(pvd->identifier, "CD001", 5) == 0)) { // found ISO9660 PVD
				DBG_PRINTF("Found ISO9660 PVD in sector %d\n", sector);

				DBG_PRINTF("reading path table from sector %d\n", pvd->pathTablePos);
				if (cdReadSectors(pvd->pathTablePos, 1, cacheBuf, &rmode) < 0) {
					DBG_PRINTF("Can't read path table\n");
					return -1;
				}

				rootRec = (ISOPathTableRecord *)cacheBuf;
				if ((rootRec->len_di != 1) || (rootRec->name[0] != 0)) {
					DBG_PRINTF("Root entry missing: %02X - %02X\n", rootRec->len_di, rootRec->name[0]);
					return -1;
				}

				fsRootLba = READ_ARRAY32(rootRec->lba); // this points to the root record

				mediaType = discType;
				DBG_PRINTF("Root directory in sector %d\n", fsRootLba);
				return initRootCache();
			}
		}
	}
	mediaType = DISC_NONE;
	// PVD not found
	return -1;
}
コード例 #19
0
ファイル: mcserv.c プロジェクト: AKuHAK2/ps2sdk
//--------------------------------------------------------------
int _McRead2(void *rpc_buf)
{
	g_descParam_t *dP = (g_descParam_t *)rpc_buf;
	register int file_offset, status;
	register int left_to_read, size_readed, size_to_read;
	g_endParam2_t eP;
	SifDmaTransfer_t dmaStruct;
	int intStatus;
	void *eedata;

#ifdef DEBUG
	DPRINTF("mcserv: _McRead2 fd %d ee buffer addr %x size %d\n", dP->fd, (int)dP->buffer, dP->size);
#endif

	eP.fastIO1_size = 0;
	eP.fastIO2_size = 0;
	eP.fastIO1_eeaddr = NULL;
	eP.fastIO2_eeaddr = NULL;

	size_readed = 0;
	file_offset = 0;

	eedata = dP->buffer;

	eP.fastIO1_size = dP->size;

	if (dP->size > 64)
		eP.fastIO1_size = (((u32)(eedata)-1) & 0xffffffc0) - ((u32)(eedata) - 64);

	eP.fastIO2_size = (dP->size - eP.fastIO1_size) & 0x3f;
	left_to_read = (dP->size - eP.fastIO1_size) - eP.fastIO2_size;

	if (eP.fastIO2_size != 0)
		eP.fastIO2_eeaddr = (void *)(eedata + eP.fastIO1_size + left_to_read);

	if (eP.fastIO1_size != 0) {
		size_readed = McRead(dP->fd, eP.fastIO1_data, eP.fastIO1_size);

		if (size_readed < 0) {
			eP.fastIO1_size = 0;
			eP.fastIO2_size = 0;
			goto dma_transfer2;
		}
		else {
			file_offset = size_readed;
			eP.fastIO1_eeaddr = eedata;
			eedata += size_readed;

			if (size_readed != eP.fastIO1_size) {
				eP.fastIO1_size = size_readed;
				eP.fastIO2_size = 0;
				size_readed = 0;
				goto dma_transfer2;
			}
			else
				size_readed = 0;
		}
	}

	while (left_to_read > 0) {

		size_to_read = left_to_read;

		if (left_to_read > MCSERV_BUFSIZE)
			size_to_read = MCSERV_BUFSIZE;

		size_readed = McRead(dP->fd, mcserv_buf, size_to_read);

		if (size_readed < 0) {
			eP.fastIO2_size = 0;
			goto dma_transfer2;
		}

		if (size_readed == size_to_read) {
			dmaStruct.size = size_readed;
			goto dma_transfer;
		}

		eP.fastIO2_size = size_readed & 0x3f;
		if ((size_readed & 0x3f) != 0) {
			eP.fastIO2_eeaddr = (void *)(eedata + (size_readed & 0xffffffc0));
			memcpy(eP.fastIO2_data, (void *)(mcserv_buf + (size_readed & 0xffffffc0)), size_readed & 0x3f);
		}

		if (eP.fastIO2_size == size_readed)
			goto skip_dma_transfer;

		dmaStruct.size = size_readed - eP.fastIO2_size;

dma_transfer:
		dmaStruct.src = (void *)mcserv_buf;
		dmaStruct.dest = (void *)eedata;
		dmaStruct.attr = 0;

		CpuSuspendIntr(&intStatus);
		sceSifSetDma(&dmaStruct, 1);
		CpuResumeIntr(intStatus);

skip_dma_transfer:
		file_offset += size_readed;
		left_to_read -= size_readed;
		eedata += size_readed;

		if (size_to_read != size_readed) {
			size_readed = 0;
			goto dma_transfer2;
		}
		size_readed = 0;
	}

	if (eP.fastIO2_size == 0)
		goto dma_transfer2;

	size_readed = McRead(dP->fd, eP.fastIO2_data, eP.fastIO2_size);

	if (size_readed < 0) {
		eP.fastIO2_size = 0;
		goto dma_transfer2;
	}

	file_offset += size_readed;
	eP.fastIO2_size = size_readed;
	size_readed = 0;

dma_transfer2:
	dmaStruct.src = (void *)&eP;
	dmaStruct.dest = (void *)dP->param;
	dmaStruct.size = sizeof (g_endParam2_t);
	dmaStruct.attr = 0;

	CpuSuspendIntr(&intStatus);
	status = sceSifSetDma(&dmaStruct, 1);
	CpuResumeIntr(intStatus);

	while (sceSifDmaStat(status) >= 0)
		DelayThread(100);

	if (size_readed != 0)
		return size_readed;

	return file_offset;
}
コード例 #20
0
ファイル: mcserv.c プロジェクト: AKuHAK2/ps2sdk
//--------------------------------------------------------------
int _McReadPage(void *rpc_buf)
{
	g_descParam_t *dP = (g_descParam_t *)rpc_buf;
	g_endParam_t eP;
	register int status, fastsize, r, i, j;
	SifDmaTransfer_t dmaStruct;
	int intStatus;

#ifdef DEBUG
	DPRINTF("mcserv: _McReadPage port%d slot%d page %d\n", dP->port, dP->slot, dP->fd);
#endif

	eP.fastIO1_eeaddr = dP->buffer;

	fastsize = ((u32)dP->buffer) & 0xf;
	dP->port = (dP->port & 1) + 2;

	if (McGetMcType(dP->port, dP->slot) == 2) {
		r = 0;
		McReadPage(dP->port, dP->slot, dP->fd, (void *)(mcserv_buf + fastsize));
	}
	else {
		memset((void *)(mcserv_buf + fastsize), 0, 512);
		r = McReadPS1PDACard(dP->port, dP->slot, dP->fd, (void *)(mcserv_buf + fastsize));
	}

	if (fastsize == 0)
		goto fullpage;

	i = 0;
	j = fastsize;
	while (j < 16) {
		eP.fastIO1_data[i] = mcserv_buf[j];
		j++;
		i++;
	}

	j = 0;
	if (fastsize > 0) {
		while (j < 16) {
			eP.fastIO1_data[i] = mcserv_buf[512 + j];
			j++;
			i++;
		}
	}

	dmaStruct.src = (void *)(mcserv_buf + 16);
	dmaStruct.dest = (void *)(dP->buffer - (fastsize - 16));
	dmaStruct.size = 496;
	dmaStruct.attr = 0;
	goto dma_transfer;

fullpage:
	dmaStruct.src = (void *)mcserv_buf;
	dmaStruct.dest = (void *)dP->buffer;
	dmaStruct.size = 512;
	dmaStruct.attr = 0;

dma_transfer:
	CpuSuspendIntr(&intStatus);
	status = sceSifSetDma(&dmaStruct, 1);
	CpuResumeIntr(intStatus);

	dmaStruct.src = (void *)&eP;
	dmaStruct.dest = (void *)dP->param;
	dmaStruct.size = sizeof (g_endParam_t);
	dmaStruct.attr = 0;

	CpuSuspendIntr(&intStatus);
	status = sceSifSetDma(&dmaStruct, 1);
	CpuResumeIntr(intStatus);

	while (sceSifDmaStat(status) >= 0)
		DelayThread(100);

	return r;
}