📄 fdcdrv.c
字号:
/*******************************************************************************
*
* fdcCP - calculate position
*
* This function's purpose is to calculate the position, in other
* words, the physical sector number, the physical head number,
* and the cylinder number.
*
* RETURNS: N/A
*/
LOCAL void fdcCP
(
register UINT nheads, /* number of heads */
register UINT sectrk, /* sectors per track */
register struct fdc_pos *p /* pointer to position template */
)
{
p->cylndrno = (USHORT)(p->lsector / (nheads * sectrk));
p->headno = (UCHAR)((p->lsector % (nheads * sectrk)) / sectrk);
p->sectorno = (UCHAR)(p->lsector % sectrk);
p->sectorno += 1;
}
/*******************************************************************************
*
* fdcRxd - receive data from FIFO
*
* This function's purpose is to retrieve one byte from the
* data FIFO for command execution status (result phase data).
*
* RETURNS: Data-Byte, or -1 on FIFO timeout.
*/
LOCAL UINT fdcRxd
(
register FDC *pFdc /* FDC registers pointer */
)
{
register UCHAR rdata; /* read data local variable */
register UINT acount; /* access count variable */
/*
* poll MSR for data availability, if data is availabilty,
* read data FIFO and return with read data
*/
for (acount = 0;;)
{
rdata = pFdc->msr_dsr;
if ((rdata & (FDC_MSR_RQM|FDC_MSR_DIO|FDC_MSR_NONDMA)) ==
(FDC_MSR_RQM|FDC_MSR_DIO))
{
rdata = pFdc->fifo;
return (rdata);
}
else
{
if (++acount > FDC_TIMEOUTCOUNT)
{
return ((UINT)-1);
}
}
}
}
/*******************************************************************************
*
* fdcTxd - transmit (send) byte to data FIFO
*
* This function's purpose is to send one byte to the
* data FIFO for command execution.
*
* RETURNS: OK, or -1 on FIFO timeout
*/
LOCAL UINT fdcTxd
(
register FDC *pFdc, /* FDC registers pointer */
register UCHAR wdata /* write data */
)
{
register UCHAR rdata; /* read data local variable */
register UINT acount; /* access count variable */
/*
* poll MSR for data fifo availability, if data fifo is availabilty,
* write data FIFO and return
*/
for (acount = 0;;)
{
rdata = pFdc->msr_dsr;
if ((rdata & (FDC_MSR_RQM|FDC_MSR_DIO|FDC_MSR_NONDMA)) ==
(FDC_MSR_RQM))
{
pFdc->fifo = wdata;
break;
}
else
{
if (++acount > FDC_TIMEOUTCOUNT)
{
return ((UINT)-1);
}
}
}
return (OK);
}
/*******************************************************************************
*
* fdcStat - retrieve command execution status (results)
*
* This function's purpose is to retrieve the command execution
* status (results) bytes from the data FIFO. The status bytes
* are placed into the buffer as specified by the caller's
* arguments.
*
* RETURNS: N/A
*/
LOCAL void fdcStat
(
register FDC *pFdc, /* FDC registers pointer */
register UCHAR *data_p, /* data pointer */
register UINT data_s /* data size in bytes */
)
{
register UINT rdata; /* read data local variable */
for (; data_s; data_s--, data_p++)
{
rdata = fdcRxd(pFdc);
if (rdata == (UINT)-1)
break;
*data_p = rdata;
}
}
/*******************************************************************************
* fdcExeCmd - execute command
*
* This function's purpose is to execute the specified command as
* specified by the passed data (pointer and size arguments).
*
* RETURNS: N/A
*/
LOCAL void fdcExeCmd
(
register FDC *pFdc, /* FDC registers pointer */
register UCHAR *data_p, /* data pointer */
register UINT data_s /* data size in bytes */
)
{
register UINT rdata; /* read data local variable */
for (; data_s; data_s--, data_p++)
{
rdata = fdcTxd(pFdc, *data_p);
if (rdata == (UINT)-1) break;
}
}
/*******************************************************************************
*
* fdcRxdEp - receive data from FIFO, execution phase
*
* This function's purpose is to retrieve all data from the
* data FIFO for the command execution phase. Only the
* number of bytes as specified will be transferred to
* the data buffer.
*
* RETURNS: number of bytes read
*/
LOCAL UINT fdcRxdEp
(
register FDC *pFdc, /* FDC registers pointer */
register UCHAR *data_p, /* data pointer */
register UINT data_s /* data size */
)
{
register UINT dcount; /* local data count variable */
register UINT acount; /* access count variable */
register UCHAR rdata; /* read data local variable */
/*
* poll MSR for data availability, if data is availabilty,
* read data FIFO and write to caller's data buffer, exit
* if the the FIFO changes state (execution to result)
*/
for (acount = 0, dcount = 0; dcount < data_s;)
{
rdata = pFdc->msr_dsr;
EIEIO_SYNC;
if (rdata & FDC_MSR_RQM)
{
if ((rdata & (FDC_MSR_NONDMA|FDC_MSR_DIO)) ==
(FDC_MSR_NONDMA|FDC_MSR_DIO))
{
rdata = pFdc->fifo;
EIEIO_SYNC;
*data_p++ = rdata;
dcount++;
acount = 0;
}
else
{
break;
}
}
else
{
if (++acount > FDC_TIMEOUTCOUNT)
{
pFdc->fifo = 0x00;
break;
}
}
}
return (dcount);
}
/*******************************************************************************
*
* fdcTxdEp - transmit data to FIFO, execution phase
*
* This function's purpose is to read all data from the data
* caller's buffer and write it to the data FIFO. This is for
* the command execution phase only. Only the number of bytes
* as specified will be transferred to the data FIFO.
*
* RETURNS: number of bytes written.
*/
LOCAL UINT fdcTxdEp
(
register FDC *pFdc, /* FDC registers pointer */
register UCHAR *data_p, /* data pointer */
register UINT data_s /* data size */
)
{
register UINT dcount; /* local data count variable */
register UINT acount; /* access count variable */
register UCHAR rdata; /* read data local variable */
/*
* poll MSR for data availability, if data is availabilty,
* read caller's data buffer and write data to FIFO, exit
* if the the FIFO changes state (execution to result)
*/
for (acount = 0, dcount = 0; dcount < data_s;)
{
rdata = pFdc->msr_dsr;
EIEIO_SYNC;
if (rdata & FDC_MSR_RQM)
{
if ((rdata & (FDC_MSR_NONDMA|FDC_MSR_DIO)) ==
(FDC_MSR_NONDMA))
{
pFdc->fifo = *data_p++;
dcount++;
EIEIO_SYNC;
acount = 0;
}
else
{
break;
}
}
else
{
if (++acount > FDC_TIMEOUTCOUNT)
{
pFdc->fifo = 0x00;
break;
}
}
}
return (dcount);
}
/*******************************************************************************
*
* fdcDRCode - return data-rate code
*
*This function's purpose is to return the data-rate code.
*This based upon the speed and sectors per track.
*
* RETURNS: data-rate code
*/
LOCAL UCHAR fdcDRCode
(
register FDC_DEV *pDev /* device descriptor pointer */
)
{
register UCHAR datarate;
switch (pDev->fdcType.ratedata)
{
case 250:
datarate = 0x02;
break;
case 500:
datarate = 0x00;
break;
case 1000:
datarate = 0x03;
break;
default:
datarate = 0x00;
break;
}
return (datarate);
}
/*******************************************************************************
*
* fdcSCode - return sector code
*
* This function's purpose is to return the sector code based
* upon the physical sector size.
*
* RETURNS: sector code.
*/
LOCAL UINT fdcSCode
(
register UINT ssize /* sector size */
)
{
register UINT multiple, npower;
multiple = ssize / 128; /* divide by base code value */
for (npower = 0;; multiple >>= 1, npower++)
{
if (multiple & 0x1)
{
break;
}
}
return (npower);
}
/*******************************************************************************
*
* fdcSetAES - setup additional error status information
*
* This function's purpose is to setup the additional error status
* information packet in the mass storage i/o subsystem. This
* additional error status information is used by the upper layers
* for display/reporting of errors.
*
* RETURNS: N/A
*/
LOCAL void fdcSetAES
(
register FDC_CMDPCKT *pCmd, /* command packet pointer */
register UCHAR *p, /* status data pointer */
register UINT s /* status data size (i.e., number of bytes) */
)
{
register UINT index;
pCmd->aescount = s;
for (index = 0; index < s; pCmd->aesdata[index++] = *p++);
}
/*******************************************************************************
*
* fdcDelay - delay
*
* This function's purpose is to delay (sleep) for the specified
* number of milli-seconds.
*
* RETURNS: N/A
*/
LOCAL void fdcDelay
(
register UINT msDelay /* number of milli-seconds to delay */
)
{
register UINT msTicks;
msTicks = 1000 / sysClkRateGet();
if (msDelay % msTicks) msDelay += msTicks;
taskDelay(msDelay / msTicks);
}
/*******************************************************************************
*
* fdcXfrcheck - sanity check on transfer request
*
* This function's purpose is to make a sanity check on the transfer
* request, this is done by examining the logical block size in
* conjunction with the physical block size of the media and the number
* of requested logical blocks. If the block number denotes a
* physical block number (not a file number), the block number is checked
* for the modulus condition.
*
* RETURNS: OK, or ERROR if sanity check failed
*/
LOCAL UINT fdcXfrcheck
(
register FDC_DEV *pDev, /* device descriptor pointer */
register FDC_CMDPCKT *pCmd, /* command packet pointer */
register UINT bvsf /* block number verse file number flag, true = file */
)
{
if (!((pCmd->nblcks * pDev->blockSize) / pDev->fdcType.sectorsize)
|| ((pCmd->nblcks * pDev->blockSize) % pDev->fdcType.sectorsize))
{
pCmd->status = FDC_ERROR_ILLDREQ;
return ((UINT) -1);
}
if (pDev->blockSize < pDev->fdcType.sectorsize)
{
if (!bvsf) /* block or file number? */
{
if (pCmd->blcknum % (pDev->fdcType.sectorsize / pDev->blockSize))
{
pCmd->status = FDC_ERROR_ILLDREQ;
return ((UINT) -1);
}
}
}
return (OK);
}
/*******************************************************************************
*
* fdcInt - FDC interrupt handler
*
* This function's purpose is handle/process the FDC interrupt
* request. The FDC's interrupt request line is active high, and
* is edge triggered. The interrupt request line is negated
* when the result bytes are read from the FDC. This interrupt
* handler basically returns control to the task that is blocked
* on the interrupt semaphore (taking ownership).
*
* RETURNS: N/A
*/
LOCAL void fdcInt
(
register FDC_IARGS *pFdcIArgs
)
{
/* increment global interrupt counter */
fdcDrvIntCount[pFdcIArgs->pDev->driveNumber] += 1;
/* return to task level */
if (fdcDrvIntVector != (UINT)-1)
{
semGive(pFdcIArgs->pDev->intSemId);
}
}
#endif /* INCLUDE_FDC */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -