📄 fdcdrv.c
字号:
isaDmaStop(fdcDrvDmaChannel); x_count = 0; break; } } } } else { /* * transfer data to or from the data FIFO, this is * the execution phase */ if (pCmd->command == FDC_READOP) { x_count = fdcRxdEp(pFdc, bufadd, d_count); } else { x_count = fdcTxdEp(pFdc, bufadd, d_count); } } } /* * precondition the results phase status bytes, this is done * in the event the FDC timeouts while retrieving the status * data bytes from the results phase */ pd_p = (UCHAR *)&cr_data_p->r_data.r_justdata.databytes[0]; pd_p[0] = 0xC0 | (pos.headno << 2) | pDev->driveNumber; pd_p[1] = 0x14; pd_p[2] = 0x00; /* read data from data FIFO, results phase */ fdcStat(pFdc, pd_p, sizeof(cr_data_p->r_data.r_readdata)); /* * check for errors, if so, set up the additional error * status data */ statusx = pd_p[0]; if ((statusx & 0xC0) != 0x00) { switch (statusx & 0xC0) { case 0x40: statusx = pd_p[1]; if (statusx == 0x80) { statusx = pd_p[2]; if (statusx == 0x00) { break; } } case 0x80: case 0xC0: lstatus = (UINT)-1; break; } if (lstatus) { pCmd->status = ((pCmd->command == FDC_READOP) ? FDC_ERROR_READ : FDC_ERROR_WRITE); fdcSetAES(pCmd, pd_p, 3); break; } } /* * verify the expected data count with the actual data count, * if they do not match, post the appropriate error status */ if (d_count != x_count) { pCmd->e_count = d_count; pCmd->a_count = x_count; pCmd->status = FDC_ERROR_DATACOUNT; lstatus = (UINT)-1; break; } /* copy internal buffer to caller's buffer */ if (fdcDrvDmaChannel != (UINT)-1) { if (pCmd->command == FDC_READOP) { cacheInvalidate(DATA_CACHE, (void *)pDev->dmaBuffer, d_count); memcpy((void *) bufadd, (void *) pDev->dmaBuffer, d_count); } } /* * update the logical sector number * update the accumulated data count * update the buffer address */ pos.lsector += (d_count / pDev->fdcType.sectorsize); m_count -= d_count; bufadd += d_count; } /* motor off */ pFdc->dor &= (FDC_DOR_DMAEN|FDC_DOR_RESET); return (lstatus); }/********************************************************************************* fdcFormat - format track/disk** This function's purpose is to format the specified number* of tracks (i.e., one or all) of the specified device. The* format is specified by the configuration parameters.** RETURNS: 0 if OK, non-zero for error condition which means the status* word in the command packet is set.*/LOCAL UINT fdcFormat ( register FDC_DEV *pDev, /* device descriptor pointer */ register FDC_CMDPCKT *pCmd, /* command packet pointer */ register FDC *pFdc, /* FDC registers pointer */ register FDC_CRDATA *cr_data_p /* command/result data pointer */ ) { register UINT d_count, x_count; /* data count variables */ register UINT n_tracks; /* number of track variable */ register UINT lstatus; /* local status flag */ register UCHAR statusx; /* status register copy */ register UCHAR *pd_p; /* phase data pointer */ struct fdc_pos pos; UCHAR addressfieldbytes[64][4]; /* address field bytes array */ /* setup the return status */ lstatus = 0; /* setup the number of tracks to format variable */ if (pCmd->tdflg == 'T') { /* calculate logical sector number of selected track */ pos.lsector = fdc_clsn( pCmd->blcknum, pDev->fdcType.sectorsize, pDev->blockSize, pDev->fdcType.sectorstrack, 1 ); /* take sector number to a track boundary */ pos.lsector = (pos.lsector / pDev->fdcType.sectorstrack) * pDev->fdcType.sectorstrack; /* check the sanity of logical sector number */ if (pos.lsector >= (pDev->fdcType.sectorstrack * pDev->fdcType.numberofheads * pDev->fdcType.numberoftracks)) { pCmd->status = FDC_ERROR_ILLDREQ; return ((UINT)-1); } n_tracks = 1; } else { pos.lsector = 0; n_tracks = pDev->fdcType.numberoftracks * pDev->fdcType.numberofheads; } /* check state (take to known state) */ if (fdcCheck(pDev, pCmd, pFdc, cr_data_p, 0)) { lstatus = (UINT)-1; n_tracks = 0; } /* format tracks loop */ for (; n_tracks; n_tracks--, pos.lsector += pDev->fdcType.sectorstrack) { /* calculate floppy disk address from logical sector number */ fdcCP( pDev->fdcType.numberofheads, pDev->fdcType.sectorstrack, (struct fdc_pos *)&pos ); /* * seek to track to format * * if the seek to track call fails, post error status and * terminate for loop */ if (fdcSeek(pDev, pCmd, pFdc, cr_data_p, pos.headno, pos.cylndrno)) { lstatus = (UINT)-1; break; } /* setup the "format-track" command structure */ pd_p = (UCHAR *)&cr_data_p->c_data.c_justdata.databytes[0]; bzero((UCHAR *)cr_data_p, sizeof(FDC_CRDATA)); pd_p[0] = FDC_CP_MFM | FDC_CS_FORMATTRACK; pd_p[1] = pDev->driveNumber | (pos.headno ? FDC_ST0_HDS : 0); pd_p[2] = fdcSCode(pDev->fdcType.sectorsize); pd_p[3] = pDev->fdcType.sectorstrack; pd_p[4] = (UCHAR)pDev->fdcType.gapformat; pd_p[5] = 0xF6; /* setup the "format-track" data phase (address field bytes) */ d_count = pDev->fdcType.sectorstrack; for (x_count = 0; x_count < d_count; x_count++) { addressfieldbytes[x_count][0] = pos.cylndrno; addressfieldbytes[x_count][1] = pos.headno; addressfieldbytes[x_count][2] = pos.sectorno + x_count; addressfieldbytes[x_count][3] = pd_p[2]; } d_count *= 4; /* setup/start the DMA controller */ if (fdcDrvDmaChannel != (UINT)-1) { /* copy format-data buffer to internal buffer */ memcpy((void *) pDev->dmaBuffer, (UCHAR *)&addressfieldbytes[0], d_count); cacheFlush(DATA_CACHE, (void *)pDev->dmaBuffer, d_count); /* initialize DMA controller for DMA data transfer */ isaDmaStart( fdcDrvDmaChannel, I8237_MODE_TM_DEMAND, I8237_MODE_TT_READ, pDev->dmaBuffer, d_count ); } /* issue the "format-track" command */ fdcExeCmd(pFdc, pd_p, sizeof(cr_data_p->c_data.c_formattrack)); /* wait for interrupt, or poll for completion */ if (fdcDrvIntVector != (UINT)-1) { if (semTake(pDev->intSemId, pDev->sysClkRate * 2) == ERROR) { pFdc->fifo = 0x00; EIEIO_SYNC; isaDmaStop(fdcDrvDmaChannel); x_count = 0; } else { x_count = d_count; } } else { /* poll DMA controller for completion (terminal count) */ if (fdcDrvDmaChannel != (UINT)-1) { for (x_count = 0;; x_count++) { /* sleep for a bit (10ms) */ fdcDelay(10); /* retrieve DMA controller status */ if ((statusx = (UCHAR)isaDmaStatus(fdcDrvDmaChannel)) == 1) { x_count = d_count; break; } else { if (x_count >= (2000/10)) { pFdc->fifo = 0x00; EIEIO_SYNC; isaDmaStop(fdcDrvDmaChannel); x_count = 0; break; } } } } else { /* * transfer data to the data FIFO, * this is the execution phase */ d_count = pDev->fdcType.sectorstrack * 4; x_count = fdcTxdEp(pFdc, (UCHAR *)&addressfieldbytes[0], d_count); } } /* * precondition the results phase status bytes, this is done * in the event the FDC timeouts while retrieving the status * data bytes from the results phase */ pd_p = (UCHAR *)&cr_data_p->r_data.r_justdata.databytes[0]; pd_p[0] = 0xC0 | (pos.headno << 2) | pDev->driveNumber; pd_p[1] = 0x14; pd_p[2] = 0x00; /* read data from data FIFO, results phase */ fdcStat(pFdc, pd_p, sizeof(cr_data_p->r_data.r_formattrack)); /* * check for errors, if so, set up the additional error * status data */ statusx = pd_p[0]; if ((statusx & 0xC0) != 0x00) { switch (statusx & 0xC0) { case 0x40: statusx = pd_p[1]; if (statusx == 0x80) { statusx = pd_p[2]; if (statusx == 0x00) { break; } } case 0x80: case 0xC0: lstatus = (UINT)-1; break; } if (lstatus) { pCmd->status = FDC_ERROR_FORMAT; fdcSetAES(pCmd, pd_p, 3); break; } } /* * verify the expected data count with the actual data count, * if they do not match, post the appropriate error status */ if (d_count != x_count) { pCmd->e_count = d_count; pCmd->a_count = x_count; pCmd->status = FDC_ERROR_DATACOUNT; lstatus = (UINT)-1; break; } } /* motor off */ pFdc->dor &= (FDC_DOR_DMAEN|FDC_DOR_RESET); return (lstatus); }/********************************************************************************* fdcSeek - seek to track* * This function's purpose is to seek to the specified track.* The case of Head Zero and Track Zero, a recalibrate operation* will be performed.* * RETURNS: 0 if OK, non-zero for error condition which means the status* word in the command packet is set.*/LOCAL UINT fdcSeek ( register FDC_DEV *pDev, /* device descriptor pointer */ register FDC_CMDPCKT *pCmd, /* command packet pointer */ register FDC *pFdc, /* FDC registers pointer */ register FDC_CRDATA *cr_data_p, /* command/result data pointer */ register UINT headno, /* head number to seek to */ register UINT trackno /* track number to seek to */ ) { register UINT lstatus; /* local status flag */ register UCHAR statusx; /* status register copy */ register UCHAR *pd_p; /* phase data pointer */ /* setup the return status */ lstatus = 0; /* * if the Head Zero and Track Zero case is true, issue a * recalibrate, else issue a seek command */ if ((headno == 0) && (trackno == 0)) { /* setup the "recalibrate" command structure */ pd_p = (UCHAR *)&cr_data_p->c_data.c_justdata.databytes[0]; bzero((UCHAR *)cr_data_p, sizeof(FDC_CRDATA)); pd_p[0] = FDC_CS_RECALIBRATE; pd_p[1] = pDev->driveNumber; /* issue the "recalibrate" command */ fdcExeCmd(pFdc, pd_p, sizeof(cr_data_p->c_data.c_recalibrate)); } else { /* setup the "seek" command structure */ pd_p = (UCHAR *)&cr_data_p->c_data.c_justdata.databytes[0]; bzero((UCHAR *)cr_data_p, sizeof(FDC_CRDATA)); pd_p[0] = FDC_CS_SEEK; pd_p[1] = pDev->driveNumber | (headno ? FDC_ST0_HDS : 0); pd_p[2] = trackno; /* issue the "seek" command */ fdcExeCmd(pFdc, pd_p, sizeof(cr_data_p->c_data.c_seek) - 1); } /* wait for interrupt from the selected drive */ for (;;) { /* delay a bit, wait for interrupt status */ if (fdcDrvIntVector != (UINT)-1) { if (semTake(pDev->intSemId, pDev->sysClkRate * 4) == ERROR) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -