⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 temp.c

📁 nucleus10版本源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		/* high nybble */
		DrvHd=(DrvHd & 0x0F) | 0x40;/* b6 enables LBA */
		PRINT_DEBUG(printf("ataCmd2: LBA=%lu\n", Temp);)
	}
	else
	{
		Sect=Temp % Drive[Cmd->Dev].Sects + 1;
		Temp /= Drive[Cmd->Dev].Sects;
		DrvHd=Temp % Drive[Cmd->Dev].Heads;
		Cyl=Temp / Drive[Cmd->Dev].Heads;
		PRINT_DEBUG(printf("ataCmd2: CHS=%u:%u:%u\n", Cyl, DrvHd, Sect);)
	}
	DrvHd |= Drive[Cmd->Dev].DrvSel;
	PRINT_DEBUG(printf("ataCmd2: writing register file\n");)
	outp(IOAdr + ATA_REG_CNT, Count);
	outp(IOAdr + ATA_REG_SECT, Sect);
	outp(IOAdr + ATA_REG_LOCYL, Cyl);
	Cyl >>= 8; /* compiler bug work-around */
	outp(IOAdr + ATA_REG_HICYL, Cyl);
	// >> 8);
	outp(IOAdr + ATA_REG_DRVHD, DrvHd);
	InterruptOccured=0;
	outp(IOAdr + ATA_REG_CMD, CmdByte);
	nsleep(400);
}

/*****************************************************************************
name:	ataCmd
action:	ATA hard drive block read/write
returns: 0 if OK
	-1 if drive could not be selected
	-2 if unsupported command
	-3 if command timed out
	-4 if bad/questionable drive status after command
*****************************************************************************/
int ataCmd(drivecmd *Cmd)
{
	u8 Stat, CmdByte;
	u32 Count, Temp;
	u16 IOAdr;
	IOAdr=Drive[Cmd->Dev].IOAdr;
	/* select the drive */
	if(ataSelect(IOAdr, Drive[Cmd->Dev].DrvSel))
	{
		printf("ataCmd: could not select drive\n");
		return(-1);
	}
	if(Cmd->Cmd == DRV_CMD_RD)
	/* convert general block device command code into ATA command byte:ATA_CMD_RDMUL if drive supports multi-sector reads, ATA_CMD_RD if not */
	{
		if(Drive[Cmd->Dev].MultSect < 2)
			CmdByte=ATA_CMD_RD;
		else
			CmdByte=ATA_CMD_RDMUL;
		while(Cmd->Count)
		/* if drive supports multisector read/write, transfer as many sectors aspossible (fewer interrupts). We rely on MultSect to limit Temp (thesector count) to < 256 */
		{
			Temp=(Cmd->Count + ATA_SECTSIZE - 1) >> ATA_LG_SECTSIZE;
			Count=min(Temp, Drive[Cmd->Dev].MultSect);
			PRINT_DEBUG(printf("ataCmd: ready to read %lu "
					"sector(s) of %lu\n", Count, Temp);)
			/* compute CHS or LBA register values and write them, along with CmdByte */
			ataCmd2(Cmd, Count, CmdByte);/* await read interrupt */
			if(awaitInterrupt(0xC000, WAIT_CMD) == 0)
			{
				printf("ataCmd: read timed out\n");
				(void)inp(IOAdr + ATA_REG_STAT);
				return(-3);
			}
			/* check status */
			Stat=inp(IOAdr + ATA_REG_STAT);
			if((Stat & (0x81 | 0x58)) != 0x58)
			{
				printf("ataCmd: bad status (0x%02X) "
					"during read\n", Stat);
				return(-4);
			}
			/* advance pointers, read data */
			Cmd->Blk += Count;
			Count <<= ATA_LG_SECTSIZE;
			insw(IOAdr + ATA_REG_DATA, (u16 *)Cmd->Data, Count >> 1);
			Cmd->Data += Count;
			/* XXX - Cmd->Count had better be a multiple of 512... */
			Cmd->Count -= Count;
		}
		return(0);
	}
	else
	if(Cmd->Cmd == DRV_CMD_WR)
	/* convert general block device command code into ATA command byte:ATA_CMD_WRMUL if drive supports multi-sector reads, ATA_CMD_WR if not */
	{
		if(Drive[Cmd->Dev].MultSect < 2)
			CmdByte=ATA_CMD_WR;
		else
			CmdByte=ATA_CMD_WRMUL;
		while(Cmd->Count)
		/* if drive supports multisector read/write, transfer as many sectors aspossible (fewer interrupts). We rely on MultSect to limit Count(the sector count) to < 256 */
		{
			Temp=(Cmd->Count + ATA_SECTSIZE - 1) >> ATA_LG_SECTSIZE;
			Count=min(Temp, Drive[Cmd->Dev].MultSect);
			PRINT_DEBUG(printf("ataCmd: ready to write %lu "
					"sector(s) of %lu\n", Count, Temp);)
                        /* compute CHS or LBA register values and write them, along with CmdByte */
                        ataCmd2(Cmd, Count, CmdByte);
                        /* await DRQ */
		        for(Temp=WAIT_DRQ; Temp; Temp--)
		        {
			        if(inp(IOAdr + ATA_REG_ALTST) & 0x08) break;
				             msleep(1);
                        }
		        /* XXX - blocking delay */
		        if(Temp == 0)
		        {
			        printf("ataCmd: no DRQ during write\n");
			        (void)inp(IOAdr + ATA_REG_STAT);
			        return(-3);
                        }
		        /* advance pointer, write data */
		        Cmd->Blk += Count;
		        Count <<= ATA_LG_SECTSIZE;
		        outsw(IOAdr + ATA_REG_DATA, (u16 *)Cmd->Data, Count >> 1);
		        /* await write interrupt */
		        Temp=awaitInterrupt(0xC000, WAIT_CMD);
		        if(Temp == 0)
		        {
			        printf("ataCmd: write timed out\n");
			        (void)inp(IOAdr + ATA_REG_STAT);
			        return(-3);
		        }
		        /* check status */
		        Stat=inp(IOAdr + ATA_REG_STAT);
		        if((Stat & (0xA1 | 0x50)) != 0x50)
		        {
			        printf("ataCmd: bad status (0x%02X) during "
				"write\n", Stat);
			        return(-4);
		        }
		        /* advance pointers */
		        Cmd->Data += Count;
		        /* XXX - Cmd->Count had better be a multiple of 512... */
		        Cmd->Count -= Count;
                }
                return(0);
        }
        else
        {
	        printf("ataCmd: bad cmd (%u)\n", Cmd->Cmd);
	        return(-2);
        }
}
/*
////////////////////////////////////////////////////////////////////////////
ATAPI-ONLY STUFF
////////////////////////////////////////////////////////////////////////////
*/
/* ATAPI packet command bytes */
#define	ATAPI_CMD_START_STOP	0x1B	/* eject/load */
#define	ATAPI_CMD_READ10	0x28	/* read data sector(s) */
#define	ATAPI_CMD_READTOC	0x43	/* read audio table-of-contents */
#define	ATAPI_CMD_PLAY		0x47	/* play audio */
#define	ATAPI_CMD_PAUSE		0x4B	/* pause/continue audio */
/* ATAPI data/command transfer 'phases' */
#define	ATAPI_PH_ABORT		0	/* other possible phases (1, 2, */
#define	ATAPI_PH_DONE		3	/* and 11) are invalid */
#define	ATAPI_PH_DATAOUT	8
#define	ATAPI_PH_CMDOUT		9
#define	ATAPI_PH_DATAIN		10
typedef struct			/* 4 bytes */
{
	u8 Res0, Min, Sec, Frame;
} atapimsf;
typedef struct			/* 4 bytes */
{
	u16 TocLen;
	u8 FirstTrk;
	u8 LastTrk;
} atapitocheader;
typedef struct			/* 8 bytes */
{
	u8 Res0;
	/* In Linux ide.h, the next field was 'unsigned control : 4'I thought "hey, unsigned is 32 bits under GNU"... and that ledto great confusion. The size of this structure _IS_ 8 bytes. */
	u8 Ctrl : 4;
	u8 Adr : 4;
	u8 Trk;
	u8 Res1;
	union	{
		u32 Block;
		atapimsf Time;
	} Where;
} atapitocentry;
typedef struct
{
	atapitocheader Hdr;
	atapitocentry Ent[100];
} atapitoc;

/*****************************************************************************
name:	atapiCmd2
action:	writes ATA register file including packet command byte,
	busy-waits until drive ready, then writes 12-byte ATAPI
	command	packet, and services interrupts
returns:0  if success
	-1 if drive could not be selected
	-3 timeout after writing pkt cmd byte (0xA0)
	-4 timeout after writing cmd pkt
	-5 data shortage (premature ATAPI_PH_DONE)
	-6 drive aborted command
	-7 bad drive phase
*****************************************************************************/
/* ATA_REG_STAT & 0x08 (DRQ)
ATA_REG_REASON	"phase"	0	0
ATAPI_PH_ABORT		0	1
bad			0	2
bad			0	3
ATAPI_PH_DONE		8	0
ATAPI_PH_DATAOUT	8	1
ATAPI_PH_CMDOUT		8	2
ATAPI_PH_DATAIN		8	3
badb0 of ATA_REG_REASON is C/nD (0=data, 1=command)b1 of ATA_REG_REASON is IO (0=out to drive, 1=in from drive) */
int atapiCmd2(drivecmd *Cmd, u8 *Pkt)
{
	u16 IOAdr, Got;
	u8 Phase;
	u32 Temp;
	IOAdr=Drive[Cmd->Dev].IOAdr;
	if(ataSelect(IOAdr, Drive[Cmd->Dev].DrvSel))
	{
		printf("atapiCmd2: could not select drive\n");
		return(-1);
	}
	PRINT_DEBUG(printf("atapiCmd2: writing register file\n");)
	outp(IOAdr + ATA_REG_FEAT, 0);
	/* irrelevant? */
	outp(IOAdr + ATA_REG_REASON, 0);
	/* irrelevant? */
	outp(IOAdr + ATA_REG_SECT, 0);
	/* irrelevant? */
	outp(IOAdr + ATA_REG_LOCNT, 32768ul);
	outp(IOAdr + ATA_REG_HICNT, 32768ul >> 8);
	outp(IOAdr + ATA_REG_CMD, ATA_CMD_PKT);
	nsleep(400);
	for(Temp=500; Temp; Temp--)
	/* XXX - why 500? */
	{
		if((inp(IOAdr + ATA_REG_STAT) & 0x88) == 0x08) break;
		msleep(1);
	}
	/* this _must_ be polled, I guess */
	if(Temp == 0)
	{
		printf("atapiCmd2: drive did not accept pkt cmd byte\n");
		return(-3);
	}
	InterruptOccured=0;
	outsw(IOAdr + ATA_REG_DATA, (u16 *)Pkt, 6);
	while(1)
	{
		if(awaitInterrupt(0xC000, WAIT_CMD) == 0)
		{
			(void)inp(IOAdr + ATA_REG_STAT);
			printf("atapiCmd2: pkt cmd timed out\n");
			return(-4);
		}
		Phase=inp(IOAdr + ATA_REG_STAT) & 0x08;
		Phase |= (inp(IOAdr + ATA_REG_REASON) & 3);
		if(Phase == ATAPI_PH_DONE)
		{
			if(Cmd->Count)	
			{
				printf("atapiCmd2: data shortage\n");/* could mean no CD or audio CD */
				return(-5);
			}
			return(0);
		}
		else
		if(Phase == ATAPI_PH_ABORT)
		{
			printf("atapiCmd2: cmd aborted\n");
			return(-6);
		}
		else
		if(Phase != ATAPI_PH_DATAIN)/* ATAPI_PH_DATAOUT or ATAPI_PH_CMDOUT or something completely bogus */
		{
			printf("atapiCmd2: bad phase %u\n", Phase);
			return(-7);
		}
		Got=inp(IOAdr + ATA_REG_HICNT);
		Got=(Got << 8) | inp(IOAdr + ATA_REG_LOCNT);
		PRINT_DEBUG(printf("<%5u bytes>   ", Got);)
		/* Cmd->Count=how many bytes we want to transferGot=how many bytes are available for transferTemp=smaller of these two */	
		Temp=min(Cmd->Count, Got);
		/* read data. XXX - what if Temp odd?XXX - allow read from middle of one sector to middle of another? */
		insw(IOAdr + ATA_REG_DATA, (u16 *)Cmd->Data, Temp >> 1);
		/* read and discard surplus data */
		for(Got -= Temp; Got > 1; Got -= 2)
			inpw(IOAdr + ATA_REG_DATA);
		if(Got) inp(IOAdr + ATA_REG_DATA);
		/* advance pointers */
		Cmd->Data += Temp;
		Cmd->Count -= Temp;
		Temp >>= ATAPI_LG_SECTSIZE;
		Cmd->Blk += Temp;
	}
}

/*****************************************************************************
name:	atapiCmd
action:	ATAPI device block read (and later, write)
returns:0  if success (OK)
	-1 if drive could not be selected
	-2 if unsupported command
	-3 timeout after writing pkt cmd byte (0xA0)
	-4 timeout after writing cmd pkt
	-5 data shortage (premature ATAPI_PH_DONE)
	-6 drive aborted command
	-7 bad drive phase
*****************************************************************************/
int atapiCmd(drivecmd *Cmd)
{
	u8 Pkt[12];
	u32 Count;
	/* convert general block device command code into ATAPI packet commands */
	if(Cmd->Cmd == DRV_CMD_RD)
		Pkt[0]=ATAPI_CMD_READ10;
	else
	{
		printf("atapiCmd: bad cmd\n");
		return(-2);
	}
	Pkt[1]=0;
	Pkt[2]=Cmd->Blk >> 24;
	Pkt[3]=Cmd->Blk >> 16;
	Pkt[4]=Cmd->Blk >> 8;
	Pkt[5]=Cmd->Blk;
	Count=Cmd->Count >> ATAPI_LG_SECTSIZE;
	Pkt[6]=Count >> 16;
	Pkt[7]=Count >> 8;
	Pkt[8]=Count;
	Pkt[9]=Pkt[10]=Pkt[11]=0;
	return(atapiCmd2(Cmd, Pkt));
}

/*****************************************************************************
name:	atapiEject
action:	loads (Load == 0) or ejects (Load != 0) CD-ROM
returns:whatever atapiCmd2() returns
*****************************************************************************/
int atapiEject(unsigned Load, unsigned WhichDrive)
{
	char Pkt[12]={
		ATAPI_CMD_START_STOP,
		0, 0, 0, 0,
		0, 0, 0, 0,
		0, 0, 0 };
	drivecmd Cmd;
	PRINT_DEBUG(printf("atapiEject\n");)
	Cmd.Blk=0;
	Cmd.Count=0;
	Cmd.Dev=WhichDrive;
	Cmd.Cmd=0;
	Cmd.Data=NULL;
	Pkt[4]=2 + (Load != 0);
	return(atapiCmd2(&Cmd, Pkt));
}

/*****************************************************************************
name:	atapiPlay
action:	plays audio from time index Start to End (units of 1/75 sec)
returns:whatever atapiCmd2() returns
*****************************************************************************/
int atapiPlay(unsigned WhichDrive, u32 Start, u32 End)
{
	char Pkt[12]={
		ATAPI_CMD_PLAY,
		0, 0,
		0, 0, 0,	/* starting minute:second:frame */
		0, 0, 0,	/* ending M:S:F (frame=1/75 sec) */
		0, 0, 0 };
	drivecmd Cmd;
	PRINT_DEBUG(printf("atapiPlay\n");)
	Cmd.Blk=0;
	Cmd.Count=0;
	Cmd.Dev=WhichDrive;
	Cmd.Cmd=0;
	Cmd.Data=NULL;
	Pkt[5]=Start % 75;
	Start /= 75;
	Pkt[4]=Start % 60;
	Start /= 60;
	Pkt[3]=Start;
	Pkt[8]=End % 75;
	End /= 75;
	Pkt[7]=End % 60;
	End /= 60;
	Pkt[6]=End;
	return(atapiCmd2(&Cmd, Pkt));
}

/*****************************************************************************
name:	atapiTOCEnt
action:	reads one or more table-of-contents entries from audio CD
returns:whatever atapiCmd2() returns
*****************************************************************************/
int atapiTOCEnt(atapitoc *Contents, unsigned Count, unsigned WhichDrive)
{
	char Pkt[12]={
		ATAPI_CMD_READTOC,
		0, 0, 0, 0,
		0, 0, 0, 0,
		0, 0, 0 };
	drivecmd Cmd;
	PRINT_DEBUG(printf("atapiTOCEnt\n");)
	Cmd.Blk=0;
	Cmd.Count=Count;
	Cmd.Dev=WhichDrive;
	Cmd.Cmd=0;
	Cmd.Data=(u8 *)Contents;
	Pkt[1]=2;
	Pkt[6]=0;
	Pkt[7]=Count >> 8;
	Pkt[8]=Count;
	Pkt[9]=0;
	return(atapiCmd2(&Cmd, Pkt));
}

/*****************************************************************************
name:	atapiTOC
action:	reads table of contents of audio CD and prints starting	
	time of each track
returns:whatever atapiCmd2() returns
*****************************************************************************/
#define	MAX_TRACKS		32
atapimsf Track[MAX_TRACKS];
unsigned NumTracks;
int atapiTOC(unsigned WhichDrive)
{
	atapitoc Contents;
	int Temp;/* read just the header at first */
	Temp=sizeof(atapitocheader);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -