📄 m5200atadrv.c
字号:
/* 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) && (pParam->valid & 0x02)) { pDrive->singleDmaMode = (pParam->dmaMode >> 8) & 0x03; if (pDrive->singleDmaMode >= 2) pDrive->singleDmaMode = 0; pDrive->multiDmaMode = 0; if (pParam->singleDma & 0x04) pDrive->singleDmaMode = 2; else if (pParam->singleDma & 0x02) pDrive->singleDmaMode = 1; else if (pParam->singleDma & 0x01) pDrive->singleDmaMode = 0; if (pParam->multiDma & 0x04) pDrive->multiDmaMode = 2; else if (pParam->multiDma & 0x02) pDrive->multiDmaMode = 1; else if (pParam->multiDma & 0x01) pDrive->multiDmaMode = 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; break; case ATA_PIO_AUTO: pDrive->rwMode = ATA_PIO_W_0 + pDrive->pioMode; 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; if (pDrive->rwDma == ATA_DMA_MULTI) pDrive->rwMode |= ATA_DMA_MULTI_0; } break; case ATA_DMA_AUTO: if (pDrive->okDma) { if (pDrive->rwDma == ATA_DMA_SINGLE) pDrive->rwMode = ATA_DMA_SINGLE_0 + pDrive->singleDmaMode; if (pDrive->rwDma == ATA_DMA_MULTI) pDrive->rwMode = ATA_DMA_MULTI_0 + pDrive->multiDmaMode; } break; default: break; } /* Set the transfer mode */ (void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, ATA_SUB_SET_RWMODE, pDrive->rwMode); /* 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; } 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); 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); 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); sysIntEnablePIC (level); /* unmask the interrupt level */ pCtrl->intLevel = level; pCtrl->wdgOkay = TRUE; pCtrl->configType = configType; semTake (&pCtrl->muteSem, WAIT_FOREVER); pCtrl->installed = TRUE; for (drive = 0; drive < drives; drive++) { pType = &ataTypes[ctrl][drive]; pDrive = &pCtrl->drive[drive]; pParam = &pDrive->param; pDrive->state = ATA_DEV_INIT; pDrive->type = ATA_TYPE_INIT; pDrive->diagCode = 0; pDrive->Reset = ataInit; ataDriveInit (ctrl, drive); } ATA_DEBUG_MSG (1, "ataDrv Calling sysAtaInit (if present):\n", 0, 0, 0, 0, 0, 0); /* Call system INIT routine to allow proper PIO mode setup */ SYS_ATA_INIT_RTN (ctrl); ATA_DEBUG_MSG (1, "ataDrv sysAtaInit returned:\n", 0, 0, 0, 0, 0, 0); semGive (&pCtrl->muteSem); } return (OK); }/********************************************************************************* ataDevCreate - create a device for a ATA/IDE disk** This routine creates a device for a specified ATA/IDE or ATAPI CDROM disk.** <ctrl> is a controller number for the ATA controller; the primary controller* is 0. The maximum is specified via ATA_MAX_CTRLS.** <drive> is the drive number for the ATA hard drive; the master drive* is 0. The maximum is specified via ATA_MAX_DRIVES.** The <nBlocks> parameter specifies the size of the device in blocks.* If <nBlocks> is zero, the whole disk is used.** The <blkOffset> parameter specifies an offset, in blocks, from the start* of the device to be used when writing or reading the hard disk. This* offset is added to the block numbers passed by the file system during* disk accesses. (VxWorks file systems always use block numbers beginning* at zero for the start of a device.)*** RETURNS:* A pointer to a block device structure (BLK_DEV) or NULL if memory cannot* be allocated for the device structure.** SEE ALSO: dosFsMkfs(), dosFsDevInit(), rawFsDevInit()*/BLK_DEV *ataDevCreate ( int ctrl, /* ATA controller number, 0 is the primary controller */ int drive, /* ATA drive number, 0 is the master drive */ int nBlocks, /* number of blocks on device, 0 = use entire disc */ int blkOffset /* offset BLK_DEV nBlocks from the start of the drive */ ) { ATA_CTRL *pCtrl = &ataCtrl[ctrl]; ATA_TYPE *pType = &ataTypes[ctrl][drive]; ATA_DRIVE *pDrive = &pCtrl->drive[drive]; ATA_PARAM *pParam = &pDrive->param; /* move * */ ATA_DEV *pDev; BLK_DEV *pBlkdev; int maxBlks; if ((ctrl >= ATA_MAX_CTRLS) || (drive >= ATA_MAX_DRIVES) || !ataDrvInstalled || !pCtrl->installed)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -