atadrv.c
来自「MPC5200 BSP 支持ATA,USB, I2C,扩展网口」· C语言 代码 · 共 2,227 行 · 第 1/5 页
C
2,227 行
) { ATA_CTRL *pCtrl = &ataCtrl[ctrl]; ATA_DRIVE *pDrive = &pCtrl->drive[drive]; ATA_PARAM *pParam = &pDrive->param; ATA_TYPE *pType = &ataTypes[ctrl][drive]; int configType = pCtrl->configType; /* configuration type */ ATA_DEBUG_MSG (3, "Enter into ataDriveInit\n", 0, 0, 0, 0, 0, 0); if (!pCtrl->installed) return (ERROR); if (pType->cylinders == 0) return (ERROR); /* user specified the device as not present */ semTake (&pCtrl->muteSem, WAIT_FOREVER); /* Identify device presence and its type */ if (ataDevIdentify (ctrl, drive) != OK) goto driveInitExit; /* Set Reset function according to device type */ if (pDrive->type == ATA_TYPE_ATA) pDrive->Reset = ataInit; else if (pDrive->type == ATA_TYPE_ATAPI) pDrive->Reset = ataPiInit; if (pDrive->type == ATA_TYPE_ATA) { if (ataPread (ctrl, drive, (char *)pParam) == OK) { if ((pCtrl->ctrlType == ATA_PCMCIA) || ((pCtrl->ctrlType != ATA_PCMCIA) && (drive == 0))) { if (ataCmd (ctrl, drive, ATA_CMD_DIAGNOSE, 0, 0) != OK) { semGive (&pCtrl->muteSem); return (ERROR); } } /* find out geometry */ if ((configType & ATA_GEO_MASK) == ATA_GEO_FORCE) { (void) ataCmd (ctrl, drive, ATA_CMD_INITP, 0, 0); (void) ataPread (ctrl, drive, (char *)pParam); } else if ((configType & ATA_GEO_MASK) == ATA_GEO_PHYSICAL) { pType->cylinders = pParam->cylinders - 1; pType->heads = pParam->heads; pType->sectors = pParam->sectors; } else if ((configType & ATA_GEO_MASK) == ATA_GEO_CURRENT) { if ((pParam->currentCylinders != 0) && (pParam->currentHeads != 0) && (pParam->currentSectors != 0)) { pType->cylinders = pParam->currentCylinders - 1; pType->heads = pParam->currentHeads; pType->sectors = pParam->currentSectors; } else { pType->cylinders = pParam->cylinders - 1; pType->heads = pParam->heads; pType->sectors = pParam->sectors; } } /* * Not all modern hard drives report a true capacity value * in their IDENTIFY DEVICE CHS fields. * For example, a Western Digital 20 Gb drive reports * its CHS as 16383 cylinders, 16 heads, and 63 spt. * This is about 8.4GB, but the LBA sectors is reported * as 0x02607780, which is closer to 20Gb, the true capacity * of the drive. The reason for this is PC BIOS can have a * 8.4GB limitation, and drive manufacturers have broken the * ATA specification to be compatable. Negative competition. * Note that the ATA specifications original limit is * about 136.9 Gb, however when combinined with a PC BIOS * interface, a 8.4 Gb limit is produced. * VxWorks does not have such limitations being a true 32bit OS, * but since the drive manufactures are not honoring the CHS * values, we have to allow for devices that demand "pure" LBA * and present incorrect CHS. * If the drive supports Logical Block Addresses (LBA) * then we need to check the field located at 16bit words 60 & 61, * "Total number of user addressable sectors (LBA mode only)". * If this value is greater than the CHS fields report, * then 60-61 holds the true size of the disk and that * will be reported to the block device interface. * Note that the CHS values are still left as the disk reported. * This is tracked at WRS as SPR#22830 */ if (pParam->capabilities & 0x0200) /* if (drive supports LBA) */ { ataLbaTotalSecs[ctrl][drive] = (UINT32) ((((UINT32) ((pParam->sectors0) & 0x0000ffff)) << 0) | (((UINT32) ((pParam->sectors1) & 0x0000ffff)) << 16)); ATA_DEBUG_MSG (1, "ID_DRIVE reports LBA (60-61) as 0x%08lx\n", ataLbaTotalSecs[ctrl][drive], 0, 0, 0, 0, 0); } /* * reinitialize the controller with parameters read from the * controller. */ (void) ataCmd (ctrl, drive, ATA_CMD_INITP, 0, 0); /* recalibrate (this command !!! is absent in ATA-4) */ (void) ataCmd (ctrl, drive, ATA_CMD_RECALIB, 0, 0); } else { pDrive->state = ATA_DEV_PREAD_F; goto driveInitExit; } } else if (pDrive->type == ATA_TYPE_ATAPI) { /* Although ATAPI device parameters have been read by ataDevIdentify(), * execute ATAPI Identify Device command to allow ATA commands * acceptance by an ATAPI device after Diagnostic or Reset commands. */ if (ataPiPread (ctrl, drive, pParam) != OK) { pDrive->state = ATA_DEV_PREAD_F; goto driveInitExit; } } /* find out supported capabilities of the drive */ pDrive->multiSecs = pParam->multiSecs & 0x00ff; pDrive->okMulti = (pDrive->multiSecs != 0) ? TRUE : FALSE; pDrive->okIordy = (pParam->capabilities & 0x0800) ? TRUE : FALSE; pDrive->okLba = (pParam->capabilities & 0x0200) ? TRUE : FALSE; pDrive->okDma = (pParam->capabilities & 0x0100) ? TRUE : FALSE; /* find out supported max PIO mode */ pDrive->pioMode = (pParam->pioMode >> 8) & 0x03; /* PIO 0,1,2 */ if (pDrive->pioMode > 2) pDrive->pioMode = 0; if ((pDrive->okIordy) && (pParam->valid & 0x02)) /* PIO 3,4 */ { if (pParam->advancedPio & 0x01) pDrive->pioMode = 3; if (pParam->advancedPio & 0x02) pDrive->pioMode = 4; } /* find out supported max DMA mode */ if ( pDrive->okDma ) { if( pParam->valid & 0x02 ) { pDrive->singleDmaMode = (pParam->dmaMode >> 8) & 0x03; if (pDrive->singleDmaMode >= 2) pDrive->singleDmaMode = 0; if (pParam->singleDma & 0x04) pDrive->singleDmaMode = 2; else if (pParam->singleDma & 0x02) pDrive->singleDmaMode = 1; else if (pParam->singleDma & 0x01) pDrive->singleDmaMode = 0; pDrive->multiDmaMode = -1; if (pParam->multiDma & 0x04) pDrive->multiDmaMode = 2; else if (pParam->multiDma & 0x02) pDrive->multiDmaMode = 1; else if (pParam->multiDma & 0x01) pDrive->multiDmaMode = 0; } pDrive->ultraDmaMode = -1; if( pParam->valid & 0x04 ) { if (pParam->ultraDmaMode & 0x04 ) pDrive->ultraDmaMode = 2; else if( pParam->ultraDmaMode & 0x02 ) pDrive->ultraDmaMode = 1; else if( pParam->ultraDmaMode & 0x01 ) pDrive->ultraDmaMode = 0; } } /* find out transfer mode to use */ pDrive->rwBits = configType & ATA_BITS_MASK; pDrive->rwPio = configType & ATA_PIO_MASK; pDrive->rwDma = configType & ATA_DMA_MASK; pDrive->rwMode = ATA_PIO_DEF_W; switch (configType & ATA_MODE_MASK) { case ATA_PIO_0: case ATA_PIO_1: case ATA_PIO_2: case ATA_PIO_3: case ATA_PIO_4: case ATA_PIO_DEF_0: case ATA_PIO_DEF_1: pDrive->rwMode = configType & ATA_MODE_MASK; mpc5200_calc_pio_timings(pDrive->rwMode - ATA_PIO_0); ourRwMode = ATA_PIO; break; case ATA_PIO_AUTO: pDrive->rwMode = ATA_PIO_W_0 + pDrive->pioMode; mpc5200_calc_pio_timings(pDrive->rwMode - ATA_PIO_0); ourRwMode = ATA_PIO; break; case ATA_DMA_0: case ATA_DMA_1: case ATA_DMA_2: if (pDrive->okDma) { if (pDrive->rwDma == ATA_DMA_SINGLE) { pDrive->rwMode = ATA_DMA_SINGLE_0 + (configType & ATA_MODE_MASK) - ATA_DMA_0; mpc5200_calc_mdma_timings(pDrive->rwMode - ATA_DMA_SINGLE_0); ourRwMode = ATA_MDMA; } if (pDrive->rwDma == ATA_DMA_MULTI) { pDrive->rwMode = ATA_DMA_MULTI_0 + (configType & ATA_MODE_MASK) - ATA_DMA_0; mpc5200_calc_mdma_timings(pDrive->rwMode - ATA_DMA_MULTI_0); ourRwMode = ATA_MDMA; } if (pDrive->rwDma == ATA_DMA_ULTRA) { pDrive->rwMode = ATA_DMA_ULTRA_0 + (configType & ATA_MODE_MASK) - ATA_DMA_0; mpc5200_calc_udma_timings(pDrive->rwMode - ATA_DMA_ULTRA_0); ourRwMode = ATA_UDMA; } } break; case ATA_DMA_AUTO: if (pDrive->okDma) { { pDrive->rwMode = ATA_DMA_SINGLE_0 + pDrive->singleDmaMode; mpc5200_calc_mdma_timings(pDrive->rwMode - ATA_DMA_SINGLE_0); ourRwMode = ATA_MDMA; } if (pDrive->multiDmaMode >= 0) { pDrive->rwMode = ATA_DMA_MULTI_0 + pDrive->multiDmaMode; mpc5200_calc_mdma_timings(pDrive->rwMode - ATA_DMA_MULTI_0); ourRwMode = ATA_MDMA; } if (pDrive->ultraDmaMode >= 0) { pDrive->rwMode = ATA_DMA_ULTRA_0 + pDrive->ultraDmaMode; mpc5200_calc_udma_timings(pDrive->rwMode - ATA_DMA_ULTRA_0); ourRwMode = ATA_UDMA; } } else { pDrive->rwMode = ATA_PIO_W_0 + pDrive->pioMode; mpc5200_calc_pio_timings(pDrive->rwMode - ATA_PIO_0); ourRwMode = ATA_PIO; } break; default: break; } /* Disable reverting to power on defaults */ /* (void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, ATA_SUB_DISABLE_REVE, 0); */ /* Set multiple mode (multisector read/write) */ if ((pDrive->rwPio == ATA_PIO_MULTI) && (pDrive->type == ATA_TYPE_ATA)) { if (pDrive->okMulti) (void) ataCmd (ctrl, drive, ATA_CMD_SET_MULTI, pDrive->multiSecs, 0); else pDrive->rwPio = ATA_PIO_SINGLE; } /* Set multiple mode (multisector read/write) for all mode just device supported*/ if (pDrive->okMulti) (void) ataCmd (ctrl, drive, ATA_CMD_SET_MULTI, pDrive->multiSecs, 0); /* enable look ahead function if device supported just for best performance */ if(pParam->commandSetSup1 & 0x0040) (void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, ATA_SUB_ENABLE_LOOK, 0); /* enable write cache function if device supported just for best performance */ if(pParam->commandSetSup1 & 0x0020) (void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, ATA_SUB_ENABLE_WCACHE, 0); /* Set the transfer mode */ (void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, ATA_SUB_SET_RWMODE, pDrive->rwMode); pDrive->state = ATA_DEV_OK;driveInitExit: semGive (&pCtrl->muteSem); if (pDrive->state != ATA_DEV_OK) { ATA_DEBUG_MSG (1, "ataDriveInit%d/%d: ERROR: state=%d dev=0x%x " "status=0x%x error=0x%x\n", ctrl, drive, pDrive->state, ATA_IO_BYTE_READ (pCtrl->sdh), ATA_IO_BYTE_READ (pCtrl->status), ATA_IO_BYTE_READ (pCtrl->error)); return (ERROR); } return (OK); } /* ataDriveInit *//********************************************************************************* ataDrv - initialize the ATA driver** This routine initializes the ATA/IDE/ATAPI CDROM driver, sets up interrupt* vectors, and performs hardware initialization of the ATA/IDE chip.** This routine must be called exactly once, before any reads, writes,* or calls to ataDevCreate(). Normally, it is called by usrRoot()* in usrConfig.c.** RETURNS: OK, or ERROR if initialization fails.** SEE ALSO: ataDevCreate()*/STATUS ataDrv ( int ctrl, /* controller no. */ int drives, /* number of drives */ int vector, /* interrupt vector */ int level, /* interrupt level */ int configType, /* configuration type */ int semTimeout, /* timeout seconds for sync semaphore */ int wdgTimeout /* timeout seconds for watch dog */ ) { ATA_CTRL *pCtrl = &ataCtrl[ctrl]; ATA_RESOURCE *pAta = &ataResources[ctrl]; PCCARD_RESOURCE *pResource = &pAta->resource; ATA_DRIVE *pDrive; ATA_PARAM *pParam; ATA_TYPE *pType; int drive; int ix; if ((ctrl >= ATA_MAX_CTRLS) || (drives > ATA_MAX_DRIVES)) return (ERROR); ATA_DEBUG_MSG (3, "Enter into ataDrv\n", 0, 0, 0, 0, 0, 0); if (!ataDrvInstalled) { for (ix = 0; ix < ATA_MAX_CTRLS; ix++) ataCtrl[ix].wdgId = wdCreate (); ataDrvInstalled = TRUE; } if (!pCtrl->installed) { if (semTimeout == 0) pCtrl->semTimeout = ATA_SEM_TIMEOUT_DEF; else pCtrl->semTimeout = semTimeout; if (wdgTimeout == 0) pCtrl->wdgTimeout = ATA_WDG_TIMEOUT_DEF; else pCtrl->wdgTimeout = wdgTimeout; semBInit (&pCtrl->syncSem, SEM_Q_FIFO, SEM_EMPTY); semBInit (&pCtrl->rdsyncSem, SEM_Q_FIFO, SEM_EMPTY); semMInit (&pCtrl->muteSem, SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE); pCtrl->data = ATA_DATA (pResource->ioStart[0]); pCtrl->error = ATA_ERROR (pResource->ioStart[0]); pCtrl->feature = ATA_FEATURE (pResource->ioStart[0]); pCtrl->seccnt = ATA_SECCNT (pResource->ioStart[0]); pCtrl->sector = ATA_SECTOR (pResource->ioStart[0]); pCtrl->cylLo = ATA_CYL_LO (pResource->ioStart[0]); pCtrl->cylHi = ATA_CYL_HI (pResource->ioStart[0]); pCtrl->sdh = ATA_SDH (pResource->ioStart[0]); pCtrl->command = ATA_COMMAND (pResource->ioStart[0]); pCtrl->status = ATA_STATUS (pResource->ioStart[0]); pCtrl->aStatus = ATA_A_STATUS (pResource->ioStart[1]); pCtrl->dControl = ATA_D_CONTROL (pResource->ioStart[1]); pCtrl->dAddress = ATA_D_ADDRESS (pResource->ioStart[1]); (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (vector), (VOIDFUNCPTR)ataIntr, ctrl); (void) intConnect (IV_SDMA_TASK5, (VOIDFUNCPTR)ataBestcommIntr, ctrl); intEnable(INUM_SDMA_TASK5); sysIntEnablePIC (level); /* unmask the interrupt level */ /*API initialization function used when virtual memory is not used. The input parameter is the base address of the MPC5200 register map (MBAR). This function MUST be called before any of the other functions are called. */ TasksInitAPI((uint8*)MBAR_VALUE);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?