📄 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_FD */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -