Nut/OS  4.10.3
API Reference
ide.c
Go to the documentation of this file.
00001 /****************************************************************************
00002 *  This file is part of the AVRIDE device driver.
00003 *
00004 *  Copyright (c) 2002-2003 by Michael Fischer. All rights reserved.
00005 *
00006 *  Redistribution and use in source and binary forms, with or without
00007 *  modification, are permitted provided that the following conditions
00008 *  are met:
00009 *
00010 *  1. Redistributions of source code must retain the above copyright
00011 *     notice, this list of conditions and the following disclaimer.
00012 *  2. Redistributions in binary form must reproduce the above copyright
00013 *     notice, this list of conditions and the following disclaimer in the
00014 *     documentation and/or other materials provided with the distribution.
00015 *  3. Neither the name of the author nor the names of its contributors may
00016 *     be used to endorse or promote products derived from this software
00017 *     without specific prior written permission.
00018 *
00019 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
00023 *  THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00026 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00027 *  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00028 *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00029 *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030 *  SUCH DAMAGE.
00031 *
00032 ****************************************************************************
00033 *  History:
00034 *
00035 *  14.12.02  mifi   First Version
00036 *  29.12.02  mifi   Support CF-Card too .
00037 *  01.01.03  mifi   Add support for IDELock, IDEFree.
00038 *  08.01.03  mifi   Now support several modes, like:
00039 *                   IDE_HARDDISK           16bit 14.7456Mhz / 2 wait states
00040 *                   IDE_HARDDISK_7MHZ      16bit  7.3728Mhz / 2 wait states
00041 *                   IDE_COMPACT_FLASH      16bit 14.7456Mhz / 2 wait states
00042 *                   MEM_8BIT_COMPACT_FLASH  8bit 14.7456Mhz / 2 wait states
00043 *  18.01.03  mifi   Change Licence from GPL to BSD.
00044 *  25.01.03  mifi   Fix the bug in ClearEvent.
00045 *                   Change IDEInit and add "AutoMount", "AutoUnMount"
00046 *                   callback function. With these functions we are
00047 *                   independent from the FileSystem.
00048 *                   Now support changing of the CF-Card in a running system.
00049 *  19.06.03  mifi   Change IDEInit, if the BaseAddress is 0, we use the
00050 *                   default address IDE_BASE_ADDRESS. Now we can use the
00051 *                   address 0 in FAT.C and hide the ide stuff.
00052 *  24.06.03  mifi   Enable the IDE Reset pin with DDRD = 0x20,
00053 *                   add some stuff to detect PACKET device.
00054 *  25.06.03  mifi   Fix overflow with IDE_MAX_SUPPORTED_DEVICE
00055 *  29.06.03  mifi   First ATAPI-Version
00056 ****************************************************************************/
00057 #define __IDE_C__
00058 
00059 #include <stddef.h>
00060 #include <string.h>
00061 
00062 #include <sys/timer.h>
00063 #include <sys/thread.h>
00064 #include <sys/event.h>
00065 #include <sys/atom.h>
00066 #include <sys/heap.h>
00067 #include <dev/irqreg.h>
00068 
00069 #include <dev/ide.h>
00070 #include <dev/idep.h>
00071 #include <fs/typedefs.h>
00072 
00073 #define HIBYTE(_x) (BYTE)((_x >> 8) & 0x00FF)
00074 #define LOBYTE(_x) (BYTE)(_x & 0x00FF)
00075 
00076 /*==========================================================*/
00077 /*  DEFINE: All Structures and Common Constants             */
00078 /*==========================================================*/
00079 //
00080 // Here are some important values.
00081 // Change these values if you change the hardware.
00082 //
00083 #define IDE_IRQ                 INT7
00084 #define IDE_INT_RISING_EDGE     0xC0
00085 
00086 #define CF_IRQ                  INT6
00087 #define CF_INT_SENS_MASK        0x30
00088 #define CF_INT_FALLING_EDGE     0x20
00089 #define CF_INT_RISING_EDGE      0x30
00090 
00091 /************************************************/
00092 #define IDE_MAX_SUPPORTED_DEVICE        1
00093 
00094 #define CF_AVAILABLE            0
00095 #define CF_NOT_AVAILABLE        1
00096 
00097 #define INITTIMEOUT             10000
00098 #define DISKTIMEOUT             10000
00099 #define CONTROLLERTIMEOUT       200
00100 #define ATAPITIMEOUT            5000
00101 
00102 #define IDEIn(x)                pIDE[x]
00103 #define IDEOut(x,y)             pIDE[x] = y
00104 
00105 //
00106 // Drive Flags
00107 //
00108 #define IDE_SUPPORT_LBA             0x0001
00109 #define IDE_SUPPORT_LBA48           0x0002
00110 #define IDE_SUPPORT_PACKET          0x0004
00111 //
00112 // Device shall assert INTRQ when DRQ
00113 // is set to one after receiving PACKET.
00114 //
00115 #define IDE_SUPPORT_INTRQ_PACKET    0x0008
00116 
00117 #define IDE_CDROM_DEVICE            0x1000
00118 #define IDE_ZIP_DEVICE              0x2000
00119 
00120 #define IDE_READ_ONLY               0x4000
00121 #define IDE_READY                   0x8000
00122 
00123 //
00124 // Identify packet device
00125 // config word[0] bit masks
00126 //
00127 #define ATAPI_CFG_12_BYTE_MSK       0x0003
00128 #define ATAPI_CFG_INTRQ             0x0060
00129 #define ATAPI_CFG_REM_MEDIUM        0x0080
00130 #define ATAPI_CFG_DEVICE            0x1F00
00131 #define ATAPI_CFG_ATAPI             0xC000
00132 
00133 #define ATAPI_IS_12_BYTE            0x0000
00134 #define ATAPI_USE_INTRQ             0x0020
00135 #define ATAPI_IS_DIRECT_ACCESS      0x0000
00136 #define ATAPI_IS_CDROM              0x0500
00137 #define ATAPI_IS_PACKET             0x8000
00138 
00139 
00140 typedef struct _drive {
00141     //
00142     // Interface values
00143     //
00144     WORD wFlags;
00145     BYTE bIDEMode;
00146     BYTE bDevice;
00147 
00148 #if (IDE_SUPPORT_CHS == 1)
00149     //
00150     // CHS values
00151     //
00152     WORD wCylinders;
00153     WORD wHeads;
00154     WORD wSectorsPerTrack;
00155     DWORD dwOneSide;
00156 #endif
00157 
00158     //
00159     // LBA value
00160     //
00161     DWORD dwTotalSectors;
00162 
00163     WORD wSectorSize;
00164 } DRIVE, *LPDRIVE;
00165 
00166 /*==========================================================*/
00167 /*  DEFINE: Prototypes                                      */
00168 /*==========================================================*/
00169 
00170 /*==========================================================*/
00171 /*  DEFINE: Definition of all local Data                    */
00172 /*==========================================================*/
00173 static HANDLE hIDEEvent;
00174 static volatile BYTE *pIDE;
00175 static volatile BYTE gbIntStatus = 0;
00176 
00177 static DRIVE sDrive[IDE_MAX_SUPPORTED_DEVICE];
00178 
00179 static HANDLE hIDESemaphore;
00180 static HANDLE hCFChangeInt;
00181 static BYTE gbCFMountStatus = 0;
00182 
00183 static IDE_MOUNT_FUNC *pUserMountFunc = NULL;
00184 static IDE_MOUNT_FUNC *pUserUnMountFunc = NULL;
00185 
00186 #if (IDE_SUPPORT_ATAPI == 1)
00187 //
00188 // ATAPI stuff
00189 //
00190 static BYTE aATAPICmd[12];
00191 
00192 #define ATAPI_CMD(_x) {                       \
00193   memset(aATAPICmd, 0x00, sizeof(aATAPICmd)); \
00194   aATAPICmd[0] = _x;                          \
00195 }
00196 
00197 #define CLEAR_ATAPI_CMD()   memset(aATAPICmd, 0x00, sizeof(aATAPICmd));
00198 #endif
00199 
00200 /*==========================================================*/
00201 /*  DEFINE: Definition of all local Procedures              */
00202 /*==========================================================*/
00203 /************************************************************/
00204 /*  Wait400ns                                               */
00205 /************************************************************/
00206 static void Wait400ns(void)
00207 {
00208     //
00209     // Wait at least 400ns, with 14.7456Mhz we need
00210     // 8 nop's for 500ns
00211     //
00212     COMPRESS_DISABLE;
00213     _NOP();
00214     _NOP();
00215     _NOP();
00216     _NOP();
00217     _NOP();
00218     _NOP();
00219     _NOP();
00220     _NOP();
00221     COMPRESS_REENABLE;
00222 }
00223 
00224 /************************************************************/
00225 /*  IDELock                                                 */
00226 /************************************************************/
00227 void IDELock(void)
00228 {
00229     NutEventWait(&hIDESemaphore, 0);
00230 }
00231 
00232 /************************************************************/
00233 /*  IDEFree                                                 */
00234 /************************************************************/
00235 void IDEFree(void)
00236 {
00237     NutEventPost(&hIDESemaphore);
00238 }
00239 
00240 /************************************************************/
00241 /*  IDESemaInit                                             */
00242 /************************************************************/
00243 void IDESemaInit(void)
00244 {
00245     NutEventPost(&hIDESemaphore);
00246 }
00247 
00248 /************************************************************/
00249 /*  HardwareReset                                           */
00250 /************************************************************/
00251 static void HardwareReset(DRIVE * pDrive)
00252 {
00253     if (pDrive->bIDEMode == MEM_8BIT_COMPACT_FLASH) {
00254         //
00255         // Set Reset
00256         //
00257         PORTD |= 0x20;
00258         _NOP();
00259 
00260         NutSleep(1000);
00261 
00262         //
00263         // Remove Reset
00264         //
00265         PORTD &= ~0x20;
00266         _NOP();
00267 
00268         NutSleep(1000);
00269     } else {                    /* HD */
00270         //
00271         // Set RESET
00272         //
00273         PORTD &= ~0x20;
00274         _NOP();
00275 
00276         NutSleep(1000);
00277 
00278         //
00279         // Remove RESET
00280         //
00281         PORTD |= 0x20;
00282         _NOP();
00283 
00284         if (pDrive->bIDEMode == IDE_COMPACT_FLASH) {
00285             NutSleep(1000);
00286         } else {
00287             //
00288             // It can takes up to 10 seconds (2.5-Inch drive)
00289             // from reset high to NOT busy.
00290             // Take a look in the drive manual "Reset timings"
00291             //
00292             NutSleep(10000);
00293         }
00294     }
00295 }
00296 
00297 /************************************************************/
00298 /*  CFInterrupt                                             */
00299 /************************************************************/
00300 static void CFInterrupt(void *p)
00301 {
00302     p = p;
00303 
00304     NutEventPostFromIrq(&hCFChangeInt);
00305 }
00306 
00307 /************************************************************/
00308 /*  IDEInterrupt                                            */
00309 /************************************************************/
00310 static void IDEInterrupt(void *p)
00311 {
00312     p = p;
00313 
00314     gbIntStatus = IDEIn(STATUS_REG);
00315 
00316     NutEventPostFromIrq(&hIDEEvent);
00317 }
00318 
00319 /************************************************************/
00320 /*  ClearEvent                                              */
00321 /************************************************************/
00322 static void ClearEvent(HANDLE * pEvent)
00323 {
00324     NutEnterCritical();
00325 
00326     *pEvent = 0;
00327 
00328     NutExitCritical();
00329 }
00330 
00331 /************************************************************/
00332 /*  WaitForInterrupt                                        */
00333 /*                                                          */
00334 /*  Return: IDE_OK, IDE_ERROR                               */
00335 /************************************************************/
00336 static int WaitForInterrupt(DWORD dwTimeout)
00337 {
00338     int nError;
00339     int nTimeout;
00340 
00341     nError = IDE_OK;
00342 
00343     nTimeout = NutEventWait(&hIDEEvent, dwTimeout);
00344     if (nTimeout == -1) {
00345         nError = IDE_ERROR;
00346     }
00347 
00348     return (nError);
00349 }
00350 
00351 #if ((IDE_SUPPORT_WRITE == 1) || (IDE_SUPPORT_ATAPI == 1))
00352 /************************************************************/
00353 /*  WaitDRQ                                                 */
00354 /*                                                          */
00355 /*  Return: IDE_OK, IDE_ERROR                               */
00356 /************************************************************/
00357 static int WaitDRQ(DWORD dwTimeout)
00358 {
00359     int nError;
00360     BYTE bStatus;
00361 
00362     nError = IDE_OK;
00363 
00364     bStatus = IDEIn(STATUS_REG);
00365     if ((bStatus & (STATUS_BUSY | STATUS_DATA_REQUEST)) != STATUS_DATA_REQUEST) {
00366 
00367         dwTimeout = (DWORD) (((dwTimeout * 10UL) / 625UL) + 1UL);
00368         dwTimeout += NutGetTickCount();
00369 
00370         bStatus = IDEIn(STATUS_REG);
00371         while ((bStatus & (STATUS_BUSY | STATUS_DATA_REQUEST)) != STATUS_DATA_REQUEST) {
00372             if (NutGetTickCount() > dwTimeout) {
00373                 nError = IDE_ERROR;
00374                 break;
00375             }
00376             bStatus = IDEIn(STATUS_REG);
00377         }
00378 
00379     }
00380 
00381     return (nError);
00382 }
00383 #endif
00384 
00385 /************************************************************/
00386 /*  WaitNotBusy  (see ATAPI-4 r17 p223 9.6)                 */
00387 /*                                                          */
00388 /*  Return: IDE_OK, IDE_ERROR                               */
00389 /************************************************************/
00390 static int WaitNotBusy(DWORD dwTimeout)
00391 {
00392     int nError;
00393     BYTE bStatus;
00394 
00395     nError = IDE_OK;
00396 
00397     bStatus = IDEIn(STATUS_REG);
00398     if (bStatus & (STATUS_BUSY | STATUS_DATA_REQUEST)) {
00399 
00400         dwTimeout = ((dwTimeout * 10) / 625) + 1;
00401         dwTimeout += NutGetTickCount();
00402 
00403         bStatus = IDEIn(STATUS_REG);
00404         while (bStatus & (STATUS_BUSY | STATUS_DATA_REQUEST)) {
00405             if (NutGetTickCount() > dwTimeout) {
00406                 nError = IDE_BUSY;
00407                 break;
00408             }
00409             bStatus = IDEIn(STATUS_REG);
00410         }
00411 
00412     }
00413 
00414     return (nError);
00415 }
00416 
00417 /************************************************************/
00418 /*  SelectDevice  (see ATAPI-4 r17 p223 9.6)                */
00419 /*                                                          */
00420 /*  Return: IDE_OK, IDE_ERROR                               */
00421 /************************************************************/
00422 static int SelectDevice(BYTE bDevice)
00423 {
00424     int nError;
00425     int nTimeout;
00426     BYTE bStatus;
00427     BYTE bDummy;
00428 
00429     nError = IDE_OK;
00430 
00431     if (WaitNotBusy(CONTROLLERTIMEOUT) == IDE_OK) {
00432 
00433         IDEOut(DISK_HEAD_REG, 0xA0 + (bDevice << 4));
00434 
00435         Wait400ns();
00436 
00437         nError = WaitNotBusy(CONTROLLERTIMEOUT);
00438     } else {
00439         nError = IDE_BUSY;
00440     }
00441 
00442     if (nError != IDE_OK) {
00443         //
00444         // Test for special case, data available.
00445         // If data available, read the data!!
00446         //
00447         bStatus = IDEIn(STATUS_REG);
00448         if (bStatus & STATUS_DATA_REQUEST) {
00449 
00450             nTimeout = 512;
00451             while ((bStatus & STATUS_DATA_REQUEST) && (nTimeout)) {
00452                 bDummy = IDEIn(DATA_READ_REG_LOW);
00453                 bDummy = IDEIn(DATA_READ_REG_LOW);
00454                 bStatus = IDEIn(STATUS_REG);
00455                 nTimeout--;
00456             }
00457         }
00458     }
00459 
00460     return (nError);
00461 }
00462 
00463 #if (IDE_SUPPORT_ATAPI == 1)
00464 /************************************************************/
00465 /*  ATAPISendCommand                                        */
00466 /*                                                          */
00467 /*  Return: IDE_OK, IDE_ERROR                               */
00468 /************************************************************/
00469 static int ATAPISendCommand(LPDRIVE pDrive, BYTE * pSectorBuffer, WORD * pReadCount)
00470 {
00471     int nError;
00472     BYTE bStatus;
00473     BYTE bDevice;
00474     WORD x, y;
00475     BYTE bDummy;
00476     WORD wSectorSize;
00477 
00478     nError = IDE_ERROR;
00479     bDummy = 0;
00480     bDevice = pDrive->bDevice;
00481     wSectorSize = pDrive->wSectorSize;
00482 
00483     *pReadCount = 0;
00484 
00485     if (SelectDevice(bDevice) == IDE_OK) {
00486 
00487         ClearEvent(&hIDEEvent);
00488 
00489         if (WaitNotBusy(ATAPITIMEOUT) == IDE_OK) {
00490 
00491             IDEOut(FEATURE_REG, 0x00);
00492             IDEOut(SECTOR_COUNT_REG, 0x00);
00493             IDEOut(SECTOR_REG, 0x00);
00494             IDEOut(CYLINDER_LOW_REG, LOBYTE(wSectorSize));
00495             IDEOut(CYLINDER_HIGH_REG, HIBYTE(wSectorSize));
00496             IDEOut(COMMAND_REG, 0xA0);
00497 
00498             if (pDrive->wFlags & IDE_SUPPORT_INTRQ_PACKET) {
00499                 nError = WaitForInterrupt(ATAPITIMEOUT);
00500                 if (nError == IDE_OK) {
00501                     ClearEvent(&hIDEEvent);
00502                 }
00503             } else {
00504                 nError = WaitDRQ(ATAPITIMEOUT);
00505             }
00506 
00507             if (nError == IDE_OK) {
00508                 for (x = 0; x < 12; x = x + 2) {
00509                     IDEOut(DATA_WRITE_REG_HIGH, aATAPICmd[x + 1]);
00510                     IDEOut(DATA_WRITE_REG_LOW, aATAPICmd[x]);
00511                 }
00512 
00513                 if (WaitForInterrupt(ATAPITIMEOUT) == IDE_OK) {
00514                     if (gbIntStatus & STATUS_ERROR) {
00515                         nError = IDE_ERROR;
00516                     } else {
00517                         nError = IDE_OK;
00518 
00519                         if (gbIntStatus & STATUS_DATA_REQUEST) {
00520 
00521                             Wait400ns();
00522 
00523                             y = IDEIn(CYLINDER_HIGH_REG) << 8;
00524                             y |= IDEIn(CYLINDER_LOW_REG);
00525 
00526                             if (y > wSectorSize) {
00527                                 y = wSectorSize;
00528                             }
00529 
00530                             if (pSectorBuffer != NULL) {
00531                                 for (x = 0; x < y; x = x + 2) {
00532                                     pSectorBuffer[x] = pIDE[DATA_READ_REG_LOW];
00533                                     pSectorBuffer[x + 1] = pIDE[DATA_READ_REG_HIGH];
00534                                 }
00535                             } else {
00536                                 for (x = 0; x < y; x = x + 2) {
00537                                     bDummy += pIDE[DATA_READ_REG_LOW];
00538                                     bDummy += pIDE[DATA_READ_REG_HIGH];
00539                                 }
00540                             }
00541 
00542                             *pReadCount = y;
00543 
00544                             bStatus = IDEIn(STATUS_REG);
00545                         }       /* endif STATUS_DATA_REQUEST */
00546                     }           /* endif STATUS_ERROR */
00547                 }               /* endif WaitForInterrupt(ATAPITIMEOUT) */
00548             }                   /* endif (WaitDRQ(ATAPITIMEOUT) */
00549         }                       /* endif WaitNotBusy(ATAPITIMEOUT) */
00550     }
00551     /* endif SelectDevice(bDevice) */
00552     return (nError);
00553 }
00554 
00555 /************************************************************/
00556 /*  ATAPIGetTotalSectors                                    */
00557 /*                                                          */
00558 /*  Return: IDE_OK, IDE_ERROR                               */
00559 /************************************************************/
00560 static int ATAPIGetTotalSectors(LPDRIVE pDrive, BYTE * pSectorBuffer, DWORD * pMaxSectors)
00561 {
00562     int nError;
00563     WORD wReadCount;
00564     WORD wErrorCount;
00565     DWORD dwValue;
00566 
00567     nError = IDE_OK;
00568     *pMaxSectors = 0;
00569 
00570     wErrorCount = 4;
00571     while (wErrorCount) {
00572 
00573         ATAPI_CMD(ATAPI_CMD_READ_CAPACITY);
00574         nError = ATAPISendCommand(pDrive, pSectorBuffer, &wReadCount);
00575         if ((nError == IDE_OK) && (wReadCount == 8)) {
00576             dwValue = pSectorBuffer[0];
00577             dwValue = dwValue << 8;
00578             dwValue |= pSectorBuffer[1];
00579             dwValue = dwValue << 8;
00580             dwValue |= pSectorBuffer[2];
00581             dwValue = dwValue << 8;
00582             dwValue |= pSectorBuffer[3];
00583             *pMaxSectors = dwValue;
00584 
00585             //
00586             // Get SectorSize
00587             //
00588             dwValue = pSectorBuffer[4];
00589             dwValue = dwValue << 8;
00590             dwValue |= pSectorBuffer[5];
00591             dwValue = dwValue << 8;
00592             dwValue |= pSectorBuffer[6];
00593             dwValue = dwValue << 8;
00594             dwValue |= pSectorBuffer[7];
00595             if (dwValue > ATAPI_SECTOR_SIZE) {
00596                 dwValue = ATAPI_SECTOR_SIZE;
00597             }
00598             pDrive->wSectorSize = (WORD) (dwValue & 0x0000FFFF);
00599             break;
00600         }
00601         wErrorCount--;
00602         NutSleep(2000);
00603     }
00604 
00605     return (nError);
00606 }
00607 
00608 /************************************************************/
00609 /*  GetDeviceInfoPacket                                     */
00610 /*                                                          */
00611 /*  PIO data in command protocol (see ATAPI-4 r17 p224 9.7) */
00612 /*                                                          */
00613 /*  Return: IDE_OK, IDE_ERROR                               */
00614 /************************************************************/
00615 static int GetDeviceInfoPacket(LPDRIVE pDrive, BYTE * pSectorBuffer)
00616 {
00617     WORD i;
00618     int nError;
00619     BYTE bStatus;
00620     BYTE bErrorReg;
00621     BYTE bDevice;
00622     WORD wConfig;
00623     DWORD dwTotalSectors;
00624 
00625     nError = IDE_ERROR;
00626     bDevice = pDrive->bDevice;
00627 
00628     if (SelectDevice(bDevice) == IDE_OK) {
00629 
00630         ClearEvent(&hIDEEvent);
00631 
00632         IDEOut(COMMAND_REG, COMMAND_DEVICE_INFO_P);
00633         if (WaitForInterrupt(DISKTIMEOUT) == IDE_OK) {
00634 
00635             if (gbIntStatus & STATUS_DATA_REQUEST) {
00636 
00637                 for (i = 0; i < IDE_SECTOR_SIZE; i = i + 2) {
00638                     pSectorBuffer[i] = pIDE[DATA_READ_REG_LOW];
00639                     if (pDrive->bIDEMode == MEM_8BIT_COMPACT_FLASH) {
00640                         pSectorBuffer[i + 1] = pIDE[DATA_READ_REG_LOW];
00641                     } else {
00642                         pSectorBuffer[i + 1] = pIDE[DATA_READ_REG_HIGH];
00643                     }
00644                 }
00645 
00646                 //
00647                 // Status register is read to clear
00648                 // pending interrupts.
00649                 //
00650                 bStatus = IDEIn(STATUS_REG);
00651 
00652                 pDrive->wFlags = 0;
00653 
00654                 wConfig = *(WORD *) & pSectorBuffer[0];
00655                 if ((wConfig & ATAPI_CFG_INTRQ) == ATAPI_USE_INTRQ) {
00656                     pDrive->wFlags |= IDE_SUPPORT_INTRQ_PACKET;
00657                 }
00658                 if ((wConfig & ATAPI_CFG_DEVICE) == ATAPI_IS_DIRECT_ACCESS) {
00659                     pDrive->wFlags |= IDE_ZIP_DEVICE;
00660                 }
00661                 if ((wConfig & ATAPI_CFG_DEVICE) == ATAPI_IS_CDROM) {
00662                     pDrive->wFlags |= (IDE_READ_ONLY | IDE_CDROM_DEVICE);
00663                 }
00664                 if ((wConfig & ATAPI_CFG_ATAPI) == ATAPI_IS_PACKET) {
00665                     pDrive->wFlags |= IDE_SUPPORT_PACKET;
00666                 }
00667 
00668                 if ((wConfig & ATAPI_CFG_12_BYTE_MSK) == ATAPI_IS_12_BYTE) {
00669                     pDrive->wFlags |= IDE_READY;
00670 
00671                     nError = ATAPIGetTotalSectors(pDrive, pSectorBuffer, &dwTotalSectors);
00672                     if (nError == IDE_OK) {
00673                         pDrive->dwTotalSectors = dwTotalSectors;
00674 
00675                         //
00676                         // ModeSense
00677                         //
00678                         ATAPI_CMD(0x5A);
00679                         aATAPICmd[2] = 0x2A;
00680                         aATAPICmd[7] = 0x08;
00681                         aATAPICmd[8] = 0x00;
00682                         ATAPISendCommand(pDrive, pSectorBuffer, &i);
00683 
00684                         //
00685                         // Set Speed to 150KByte
00686                         //
00687                         IDEATAPISetCDSpeed(bDevice, 150);
00688                     } else {
00689                         pDrive->dwTotalSectors = 0;
00690                     }
00691 
00692                     //ATAPITest(pDrive, pSectorBuffer);
00693                 }
00694             }
00695 
00696             if (gbIntStatus & STATUS_ERROR) {
00697                 bErrorReg = IDEIn(ERROR_REG);
00698             }
00699         }
00700 
00701     }
00702 
00703     return (nError);
00704 }
00705 #endif
00706 
00707 /************************************************************/
00708 /*  GetDeviceInfo                                           */
00709 /*                                                          */
00710 /*  PIO data in command protocol (see ATAPI-4 r17 p224 9.7) */
00711 /*                                                          */
00712 /*  Return: IDE_OK, IDE_ERROR                               */
00713 /************************************************************/
00714 static int GetDeviceInfo(LPDRIVE pDrive, BYTE * pSectorBuffer)
00715 {
00716     WORD i;
00717     int nError;
00718     BYTE bStatus;
00719     BYTE bErrorReg;
00720     BYTE bDevice;
00721     IDEDEVICEINFO *pInfo;
00722 
00723     nError = IDE_ERROR;
00724     bDevice = pDrive->bDevice;
00725 
00726     if (SelectDevice(bDevice) == IDE_OK) {
00727 
00728         ClearEvent(&hIDEEvent);
00729 
00730 #if 0
00731         IDEOut(FEATURE_REG, 0);
00732         IDEOut(SECTOR_COUNT_REG, 1);
00733         IDEOut(SECTOR_REG, 0);
00734         IDEOut(CYLINDER_LOW_REG, 0);
00735         IDEOut(CYLINDER_HIGH_REG, 0);
00736 #endif
00737 
00738         IDEOut(COMMAND_REG, COMMAND_DEVICE_INFO);
00739         if (WaitForInterrupt(DISKTIMEOUT) == IDE_OK) {
00740 
00741             if (gbIntStatus & STATUS_DATA_REQUEST) {
00742 
00743                 for (i = 0; i < IDE_SECTOR_SIZE; i = i + 2) {
00744                     pSectorBuffer[i] = pIDE[DATA_READ_REG_LOW];
00745                     if (pDrive->bIDEMode == MEM_8BIT_COMPACT_FLASH) {
00746                         pSectorBuffer[i + 1] = pIDE[DATA_READ_REG_LOW];
00747                     } else {
00748                         pSectorBuffer[i + 1] = pIDE[DATA_READ_REG_HIGH];
00749                     }
00750                 }
00751 
00752                 //
00753                 // Status register is read to clear
00754                 // pending interrupts.
00755                 //
00756                 bStatus = IDEIn(STATUS_REG);
00757 
00758                 pInfo = (IDEDEVICEINFO *) pSectorBuffer;
00759 
00760 #if (IDE_SUPPORT_CHS == 1)
00761                 pDrive->wCylinders = (WORD) pInfo->Cylinders;
00762                 pDrive->wHeads = (BYTE) pInfo->Heads;
00763                 pDrive->wSectorsPerTrack = (BYTE) pInfo->SectorsPerTrack;
00764                 pDrive->dwOneSide = pDrive->wCylinders * pDrive->wSectorsPerTrack;
00765 #endif
00766 
00767                 if (pInfo->LBASectors > 0) {
00768                     pDrive->wFlags = IDE_READY | IDE_SUPPORT_LBA;
00769                     pDrive->dwTotalSectors = pInfo->LBASectors;
00770                 } else {
00771 
00772 #if (IDE_SUPPORT_CHS == 1)
00773                     pDrive->wFlags = IDE_READY;
00774                     pDrive->dwTotalSectors = pInfo->Cylinders;
00775                     pDrive->dwTotalSectors *= pInfo->Heads;
00776                     pDrive->dwTotalSectors *= pInfo->SectorsPerTrack;
00777 #endif
00778 
00779                 }
00780 
00781                 nError = IDE_OK;
00782             }
00783 
00784             if (gbIntStatus & STATUS_ERROR) {
00785                 bErrorReg = IDEIn(ERROR_REG);
00786             }
00787         }
00788 
00789     }
00790 
00791     return (nError);
00792 }
00793 
00794 /************************************************************/
00795 /*  IsPacketDevice                                          */
00796 /*                                                          */
00797 /*  Check Command block register,                           */
00798 /*  see page 210, 9.1 Signature and persistence             */
00799 /*                                                          */
00800 /*  Return: TRUE, FALSE                                     */
00801 /************************************************************/
00802 #if (IDE_SUPPORT_ATAPI == 1)
00803 static int IsPacketDevice(void)
00804 {
00805     int nPacketDevice;
00806     BYTE bSectorCount;
00807     BYTE bSectorNumber;
00808     BYTE bCylinderLow;
00809     BYTE bCylinderHigh;
00810 
00811     nPacketDevice = FALSE;
00812 
00813     bSectorCount = IDEIn(SECTOR_COUNT_REG);
00814     bSectorNumber = IDEIn(SECTOR_REG);
00815     bCylinderLow = IDEIn(CYLINDER_LOW_REG);
00816     bCylinderHigh = IDEIn(CYLINDER_HIGH_REG);
00817 
00818 
00819     if ((bCylinderLow == 0x14) && (bCylinderHigh == 0xEB)) {
00820         nPacketDevice = TRUE;
00821     }
00822 
00823     return (nPacketDevice);
00824 }
00825 #else
00826 static int IsPacketDevice(void)
00827 {
00828     return (FALSE);
00829 }
00830 #endif
00831 
00832 /************************************************************/
00833 /*  DeviceDiag                                              */
00834 /*                                                          */
00835 /*  NON-data command protocol (see ATAPI-4 r17 p231 9.9)    */
00836 /*                                                          */
00837 /*  Return: IDE_OK, IDE_ERROR                               */
00838 /************************************************************/
00839 static int DeviceDiag(LPDRIVE pDrive)
00840 {
00841     int nError;
00842     BYTE bResult;
00843 
00844     nError = IDE_ERROR;
00845 
00846     if (SelectDevice(0) == IDE_OK) {
00847 
00848 #if 0
00849         IDEOut(FEATURE_REG, 0);
00850         IDEOut(SECTOR_COUNT_REG, 1);
00851         IDEOut(SECTOR_REG, 0);
00852         IDEOut(CYLINDER_LOW_REG, 0);
00853         IDEOut(CYLINDER_HIGH_REG, 0);
00854 #endif
00855 
00856         ClearEvent(&hIDEEvent);
00857 
00858         //
00859         // Check if we are a PACKET device
00860         //
00861         if (IsPacketDevice() == TRUE) {
00862             nError = IDE_OK;
00863             pDrive->wFlags = IDE_SUPPORT_PACKET;
00864         } else {
00865 
00866             IDEOut(COMMAND_REG, COMMAND_DIAG);
00867             if (WaitForInterrupt(INITTIMEOUT) == IDE_OK) {
00868 
00869                 bResult = IDEIn(ERROR_REG);
00870                 if (bResult == 0x01) {  // see ATAPI-4 r17 p72
00871                     nError = IDE_OK;
00872                 }
00873 
00874             }
00875         }
00876     }
00877 
00878     return (nError);
00879 }
00880 
00881 /************************************************************/
00882 /*  ReadSectors                                             */
00883 /*                                                          */
00884 /*  PIO data in command protocol, see ATAPI-4 r17 p224 9.7  */
00885 /*                                                          */
00886 /*  Return: IDE_OK, IDE_ERROR                               */
00887 /************************************************************/
00888 static int ReadSectors(BYTE bDevice, BYTE * pData, DWORD dwStartSector, WORD wSectorCount)
00889 {
00890     WORD i, x;
00891     int nError;
00892     BYTE bValue;
00893     BYTE bErrorReg;
00894     BYTE bStatus;
00895     LPDRIVE pDrive;
00896 
00897 #if (IDE_SUPPORT_CHS == 1)
00898     WORD wCHSSector;
00899     WORD wCHSHead;
00900     WORD wCHSCylinder;
00901 #endif
00902 
00903     pDrive = &sDrive[bDevice];
00904     nError = SelectDevice(bDevice);
00905 
00906 #if (IDE_SUPPORT_CHS == 0)
00907     //
00908     // NO CHS support
00909     //
00910     if ((pDrive->wFlags & IDE_SUPPORT_LBA) == 0) {
00911         //
00912         // If we have a CHS device, this is an ERROR
00913         //
00914         nError = IDE_ERROR;
00915     }
00916 #endif
00917 
00918     if (nError == IDE_OK) {
00919 
00920         ClearEvent(&hIDEEvent);
00921 
00922         if (pDrive->wFlags & IDE_SUPPORT_LBA) {
00923             //
00924             // LBA
00925             //
00926             bValue = (BYTE) ((bDevice << 4) | 0xE0 | (dwStartSector >> 24));
00927             IDEOut(DISK_HEAD_REG, bValue);
00928             IDEOut(LBA_16_23, (BYTE) (dwStartSector >> 16));
00929             IDEOut(LBA_8_15, (BYTE) (dwStartSector >> 8));
00930             IDEOut(LBA_0_7, (BYTE) (dwStartSector));
00931 
00932             IDEOut(SECTOR_COUNT_REG, (BYTE) (wSectorCount & 0xff));
00933             IDEOut(COMMAND_REG, COMMAND_READ_SECTORS);
00934 
00935 #if (IDE_SUPPORT_CHS == 1)
00936         } else {
00937             //
00938             // CHS
00939             //
00940             wCHSSector = (WORD) (dwStartSector % pDrive->wSectorsPerTrack) + 1;
00941             wCHSHead = (WORD) (dwStartSector / pDrive->dwOneSide);
00942             dwStartSector = dwStartSector % pDrive->dwOneSide;
00943             wCHSCylinder = (WORD) (dwStartSector / pDrive->wSectorsPerTrack);
00944 
00945             wCHSHead |= (bDevice << 4) | 0xA0;
00946 
00947             IDEOut(DISK_HEAD_REG, (BYTE) wCHSHead);
00948             IDEOut(SECTOR_REG, (BYTE) wCHSSector);
00949             IDEOut(CYLINDER_LOW_REG, (BYTE) (wCHSCylinder & 0x00FF));
00950             IDEOut(CYLINDER_HIGH_REG, (BYTE) (wCHSCylinder >> 8));
00951 
00952             IDEOut(SECTOR_COUNT_REG, (BYTE) (wSectorCount & 0xff));
00953             IDEOut(COMMAND_REG, COMMAND_READ_SECTORS);
00954 #endif
00955         }
00956 
00957         for (i = 0; i < wSectorCount; i++) {
00958             nError = WaitForInterrupt(DISKTIMEOUT);
00959             if (nError == IDE_OK) {
00960                 bStatus = gbIntStatus;
00961 
00962                 if (bStatus & STATUS_ERROR) {
00963                     bErrorReg = IDEIn(ERROR_REG);
00964                     nError = IDE_ERROR;
00965                     break;
00966                 }
00967 
00968                 for (x = 0; x < IDE_SECTOR_SIZE; x = x + 2) {
00969                     pData[x] = pIDE[DATA_READ_REG_LOW];
00970                     if (pDrive->bIDEMode == MEM_8BIT_COMPACT_FLASH) {
00971                         pData[x + 1] = pIDE[DATA_READ_REG_LOW];
00972                     } else {
00973                         pData[x + 1] = pIDE[DATA_READ_REG_HIGH];
00974                     }
00975                 }
00976 
00977                 pData += IDE_SECTOR_SIZE;
00978 
00979             } else {
00980                 bStatus = IDEIn(STATUS_REG);
00981                 bErrorReg = IDEIn(ERROR_REG);
00982             }
00983         }
00984 
00985         bStatus = IDEIn(STATUS_REG);
00986 
00987     }
00988     /* SelectDevice */
00989     return (nError);
00990 }
00991 
00992 #if (IDE_SUPPORT_WRITE == 1)
00993 /************************************************************/
00994 /*  WriteSectors                                            */
00995 /*                                                          */
00996 /*  PIO data out command protocol, see ATAPI-4 r17 p227 9.8 */
00997 /*                                                          */
00998 /*  Return: IDE_OK, IDE_ERROR                               */
00999 /************************************************************/
01000 static BYTE WriteSectors(WORD bDevice, BYTE * pData, DWORD dwStartSector, WORD wSectorCount)
01001 {
01002     WORD i;
01003     int x;
01004     int nError;
01005     BYTE bValue;
01006     BYTE bStatus;
01007     BYTE bErrorReg;
01008     LPDRIVE pDrive;
01009 
01010 #if (IDE_SUPPORT_CHS == 1)
01011     WORD wCHSSector;
01012     WORD wCHSHead;
01013     WORD wCHSCylinder;
01014 #endif
01015 
01016     pDrive = &sDrive[bDevice];
01017     nError = SelectDevice(bDevice);
01018 
01019 #if (IDE_SUPPORT_CHS == 0)
01020     //
01021     // NO CHS support
01022     //
01023     if ((pDrive->wFlags & IDE_SUPPORT_LBA) == 0) {
01024         //
01025         // If we found a CHS device, this is an ERROR
01026         //
01027         nError = IDE_ERROR;
01028     }
01029 #endif
01030 
01031     if (nError == IDE_OK) {
01032 
01033         if (pDrive->wFlags & IDE_SUPPORT_LBA) {
01034             //
01035             // LBA
01036             //
01037             bValue = (BYTE) ((bDevice << 4) | 0xE0 | (dwStartSector >> 24));
01038             IDEOut(DISK_HEAD_REG, bValue);
01039             IDEOut(LBA_16_23, (BYTE) (dwStartSector >> 16));
01040             IDEOut(LBA_8_15, (BYTE) (dwStartSector >> 8));
01041             IDEOut(LBA_0_7, (BYTE) (dwStartSector));
01042 
01043             IDEOut(SECTOR_COUNT_REG, (BYTE) (wSectorCount & 0xff));
01044             IDEOut(COMMAND_REG, COMMAND_WRITE_SECTORS);
01045 
01046 #if (IDE_SUPPORT_CHS == 1)
01047         } else {
01048             //
01049             // CHS
01050             //
01051             wCHSSector = (WORD) (dwStartSector % pDrive->wSectorsPerTrack) + 1;
01052             wCHSHead = (WORD) (dwStartSector / pDrive->dwOneSide);
01053             dwStartSector = dwStartSector % pDrive->dwOneSide;
01054             wCHSCylinder = (WORD) (dwStartSector / pDrive->wSectorsPerTrack);
01055 
01056             wCHSHead |= (bDevice << 4) | 0xA0;
01057 
01058             IDEOut(DISK_HEAD_REG, (BYTE) wCHSHead);
01059             IDEOut(SECTOR_REG, (BYTE) wCHSSector);
01060             IDEOut(CYLINDER_LOW_REG, (BYTE) (wCHSCylinder & 0x00FF));
01061             IDEOut(CYLINDER_HIGH_REG, (BYTE) (wCHSCylinder >> 8));
01062 
01063             IDEOut(SECTOR_COUNT_REG, (BYTE) (wSectorCount & 0xff));
01064             IDEOut(COMMAND_REG, COMMAND_WRITE_SECTORS);
01065 #endif
01066         }
01067 
01068         if (WaitDRQ(CONTROLLERTIMEOUT) == IDE_OK) {
01069 
01070             bStatus = IDEIn(STATUS_REG);
01071             for (i = 0; i < wSectorCount; i++) {
01072 
01073                 for (x = 0; x < IDE_SECTOR_SIZE; x = x + 2) {
01074                     if (pDrive->bIDEMode == MEM_8BIT_COMPACT_FLASH) {
01075                         IDEOut(DATA_WRITE_REG_LOW, pData[x]);
01076                         IDEOut(DATA_WRITE_REG_LOW, pData[x + 1]);
01077                     } else {
01078                         IDEOut(DATA_WRITE_REG_HIGH, pData[x + 1]);
01079                         IDEOut(DATA_WRITE_REG_LOW, pData[x]);
01080                     }
01081                 }
01082 
01083                 pData += IDE_SECTOR_SIZE;
01084 
01085                 nError = WaitForInterrupt(DISKTIMEOUT);
01086                 if (nError == IDE_OK) {
01087                     bStatus = gbIntStatus;
01088 
01089                     if ((bStatus & STATUS_ERROR) == STATUS_ERROR) {
01090                         bErrorReg = IDEIn(ERROR_REG);
01091                         nError = IDE_ERROR;
01092                         break;
01093                     }
01094                 } else {
01095                     //
01096                     // Error
01097                     //
01098                     nError = IDE_ERROR;
01099                     break;
01100                 }
01101             }
01102 
01103         } else {
01104             //
01105             // Device: Set error status (D)
01106             //
01107             WaitForInterrupt(DISKTIMEOUT);
01108             bErrorReg = IDEIn(ERROR_REG);
01109         }                       /* endif WaitDRQ */
01110 
01111     }
01112     /* SelectDevice */
01113     return (nError);
01114 }
01115 #endif
01116 
01117 /************************************************************/
01118 /*  CFChange                                                */
01119 /************************************************************/
01120 THREAD(CFChange, arg)
01121 {
01122     BYTE bNewStatus;
01123     BYTE *pSectorBuffer;
01124 
01125     while (1) {
01126 
01127         NutEventWaitNext(&hCFChangeInt, 0);
01128         //
01129         // Wait a while, that the cf contact is stable and not to bounce.
01130         //
01131         NutSleep(2000);
01132 
01133         bNewStatus = (PINE & BV(CF_IRQ));
01134         if (bNewStatus != gbCFMountStatus) {
01135 
01136             if (bNewStatus == CF_AVAILABLE) {
01137                 gbCFMountStatus = CF_AVAILABLE;
01138                 //
01139                 // We must mount the new CF card.
01140                 //
01141                 HardwareReset(&sDrive[0]);
01142 
01143                 pSectorBuffer = (BYTE *) NutHeapAlloc(IDE_SECTOR_SIZE);
01144                 if (pSectorBuffer != NULL) {
01145                     IDEMountDevice(IDE_DRIVE_C, pSectorBuffer);
01146                     NutHeapFree(pSectorBuffer);
01147 
01148                     if (pUserMountFunc != NULL) {
01149                         pUserMountFunc(IDE_DRIVE_C);
01150                     }
01151                 }
01152 
01153                 NutEnterCritical();
01154                 EICR &= ~CF_INT_SENS_MASK;
01155                 EICR |= CF_INT_RISING_EDGE;
01156                 NutExitCritical();
01157 
01158             } else {
01159                 gbCFMountStatus = CF_NOT_AVAILABLE;
01160                 //
01161                 // The user has removed the CF card,
01162                 // now UnMount the device.
01163                 //
01164                 IDEUnMountDevice(IDE_DRIVE_C);
01165 
01166                 if (pUserUnMountFunc != NULL) {
01167                     pUserUnMountFunc(IDE_DRIVE_C);
01168                 }
01169 
01170                 NutEnterCritical();
01171                 EICR &= ~CF_INT_SENS_MASK;
01172                 EICR |= CF_INT_FALLING_EDGE;
01173                 NutExitCritical();
01174             }
01175         }                       /* endif bValue != gbCFMountStatus */
01176     }                           /* end while */
01177 }
01178 
01179 /*==========================================================*/
01180 /*  DEFINE: All code exported                               */
01181 /*==========================================================*/
01182 /************************************************************/
01183 /*  IDEInit                                                 */
01184 /************************************************************/
01185 int IDEInit(int nBaseAddress, int nIDEMode, IDE_MOUNT_FUNC * pMountFunc, IDE_MOUNT_FUNC * pUnMountFunc)
01186 {
01187     int i;
01188     int nError;
01189     BYTE bValue;
01190 
01191     pUserMountFunc = pMountFunc;
01192     pUserUnMountFunc = pUnMountFunc;
01193 
01194     //
01195     // If nBaseAddress is 0, we use the default address
01196     //
01197     if (nBaseAddress == 0) {
01198         nBaseAddress = IDE_BASE_ADDRESS;
01199     }
01200     //
01201     // With MCUCR 0xC0 and XMCRA 0x02 we set:
01202     //
01203     // Wait two cycles during read/write and
01204     // wait one cycle before driving out new address.
01205     // This setting is for 0x1100 - 0xffff
01206     //
01207 #ifdef __AVR_ENHANCED__
01208     XMCRA = _BV(SRW11);
01209 #endif
01210 
01211     //
01212     // Enable the IDE Reset
01213     //
01214     DDRD = 0x20;
01215 
01216 
01217     for (i = 0; i < IDE_MAX_SUPPORTED_DEVICE; i++) {
01218         memset((BYTE *) & sDrive[i], 0x00, sizeof(DRIVE));
01219 
01220         sDrive[i].bDevice = (BYTE) i;
01221         sDrive[i].bIDEMode = (BYTE) nIDEMode;
01222     }
01223 
01224     IDESemaInit();
01225 
01226     pIDE = (unsigned char *) nBaseAddress;
01227 
01228     ClearEvent(&hIDEEvent);
01229 
01230     NutEnterCritical();
01231 
01232     //
01233     // Clear interrupt status
01234     //
01235     gbIntStatus = 0;
01236 
01237     //
01238     // Install IDE interrupt
01239     //
01240     nError = NutRegisterIrqHandler(&sig_INTERRUPT7, IDEInterrupt, NULL);
01241     if (nError == FALSE) {
01242         EICR |= IDE_INT_RISING_EDGE;
01243         sbi(EIMSK, IDE_IRQ);
01244     }
01245 
01246     switch (nIDEMode) {
01247     case IDE_HARDDISK:{
01248             break;
01249         }
01250 
01251         //
01252         // If your drive does not work correct with 14.7456Mhz,
01253         // try to devide the clock by 2.
01254         //
01255         // Important: You must correct the baudrate in your app.
01256         // if you set 115200, you get only 57600.
01257         //
01258     case IDE_HARDDISK_7MHZ:{
01259 #if defined(CLKPR) /* AT90MEGA128 uses a clock prescaler register */
01260             CLKPR = _BV(CLKPCE); // Enable clock speed change
01261             CLKPR = 2; // Run at half the clock speed
01262 #else
01263             XDIV = 0xff;
01264 #endif
01265             break;
01266         }
01267     case IDE_COMPACT_FLASH:{
01268             break;
01269         }
01270     case MEM_8BIT_COMPACT_FLASH:{
01271             //
01272             // Now we will support to change the CF-Card in
01273             // a running system, therefore we must install
01274             // a INT handler and some other parts :-)
01275             //
01276 
01277             //
01278             // Clear CF_INT_SENS_MASK.
01279             //
01280             EICR &= ~CF_INT_SENS_MASK;
01281 
01282             //
01283             // Check the status of the compact flash.
01284             //
01285             bValue = (PINE & BV(CF_IRQ));
01286             if (bValue == CF_AVAILABLE) {
01287                 gbCFMountStatus = CF_AVAILABLE;
01288 
01289                 //
01290                 // The rising edge between two samples
01291                 // of INTX generates an interrupt request.
01292                 //
01293                 EICR |= CF_INT_RISING_EDGE;
01294             } else {
01295                 gbCFMountStatus = CF_NOT_AVAILABLE;
01296 
01297                 //
01298                 // The falling edge between two samples
01299                 // of INTX generates an interrupt request.
01300                 //
01301                 EICR |= CF_INT_FALLING_EDGE;
01302             }
01303 
01304             nError = NutRegisterIrqHandler(&sig_INTERRUPT6, CFInterrupt, NULL);
01305             if (nError == FALSE) {
01306                 NutThreadCreate("cfchange", CFChange, NULL, 640);
01307                 sbi(EIMSK, CF_IRQ);
01308             }
01309 
01310             break;
01311         }
01312     }
01313     NutExitCritical();
01314 
01315     HardwareReset(&sDrive[0]);
01316 
01317     nError = IDE_OK;
01318 
01319     return (nError);
01320 }
01321 
01322 /************************************************************/
01323 /*  IDEMountDevice                                          */
01324 /************************************************************/
01325 int IDEMountDevice(BYTE bDevice, BYTE * pSectorBuffer)
01326 {
01327     int nError;
01328     LPDRIVE pDrive;
01329 
01330     pDrive = NULL;
01331 
01332     IDELock();
01333 
01334     if (bDevice >= IDE_MAX_SUPPORTED_DEVICE) {
01335         nError = IDE_ERROR;
01336     } else {
01337         pDrive = &sDrive[bDevice];
01338 
01339         pDrive->wFlags = 0;
01340 
01341 #if (IDE_SUPPORT_CHS == 1)
01342         //
01343         // CHS values
01344         //
01345         pDrive->wCylinders = 0;
01346         pDrive->wHeads = 0;
01347         pDrive->wSectorsPerTrack = 0;
01348 #endif
01349 
01350         //
01351         // LBA value
01352         //
01353         pDrive->dwTotalSectors = 0;
01354 
01355         nError = DeviceDiag(pDrive);
01356         if (pDrive->wFlags & IDE_SUPPORT_PACKET) {
01357 #if (IDE_SUPPORT_ATAPI == 1)
01358             pDrive->wSectorSize = ATAPI_SECTOR_SIZE;
01359             nError = GetDeviceInfoPacket(pDrive, pSectorBuffer);
01360             if (pDrive->wFlags & IDE_READY) {
01361                 nError = IDE_OK;
01362             }
01363 #endif
01364         } else {
01365             if (nError != IDE_OK) {
01366                 //
01367                 // Try it again
01368                 //
01369                 nError = DeviceDiag(pDrive);
01370             }
01371 
01372             if (nError == IDE_OK) {
01373                 pDrive->wSectorSize = IDE_SECTOR_SIZE;
01374                 nError = GetDeviceInfo(pDrive, pSectorBuffer);
01375                 if (pDrive->wFlags & IDE_READY) {
01376                     nError = IDE_OK;
01377                 }
01378             }
01379         }
01380 
01381     }                           /* (bDevice >= IDE_MAX_SUPPORTED_DEVICE) */
01382 
01383     IDEFree();
01384 
01385     return (nError);
01386 }
01387 
01388 /************************************************************/
01389 /*  IDEGetSectorSize                                        */
01390 /************************************************************/
01391 int IDEGetSectorSize(BYTE bDevice)
01392 {
01393     int nSectorSize;
01394     LPDRIVE pDrive;
01395 
01396     nSectorSize = 0;
01397 
01398     IDELock();
01399 
01400     if (bDevice >= IDE_MAX_SUPPORTED_DEVICE) {
01401         nSectorSize = 0;
01402     } else {
01403         pDrive = &sDrive[bDevice];
01404         nSectorSize = pDrive->wSectorSize;
01405     }
01406 
01407     IDEFree();
01408 
01409     return (nSectorSize);
01410 }
01411 
01412 /************************************************************/
01413 /*  IDEIsCDROMDevice                                        */
01414 /************************************************************/
01415 int IDEIsCDROMDevice(BYTE bDevice)
01416 {
01417     int nIsCDROM;
01418     LPDRIVE pDrive;
01419 
01420     nIsCDROM = FALSE;
01421 
01422     IDELock();
01423 
01424     if (bDevice >= IDE_MAX_SUPPORTED_DEVICE) {
01425         nIsCDROM = FALSE;
01426     } else {
01427         pDrive = &sDrive[bDevice];
01428         if ((pDrive->wFlags & IDE_READY) && (pDrive->wFlags & IDE_CDROM_DEVICE)) {
01429             nIsCDROM = TRUE;
01430         }
01431     }
01432 
01433     IDEFree();
01434 
01435     return (nIsCDROM);
01436 }
01437 
01438 /************************************************************/
01439 /*  IDEIsZIPDevice                                          */
01440 /************************************************************/
01441 int IDEIsZIPDevice(BYTE bDevice)
01442 {
01443     int nIsZIP;
01444     LPDRIVE pDrive;
01445 
01446     nIsZIP = FALSE;
01447 
01448     IDELock();
01449 
01450     if (bDevice >= IDE_MAX_SUPPORTED_DEVICE) {
01451         nIsZIP = FALSE;
01452     } else {
01453         pDrive = &sDrive[bDevice];
01454         if ((pDrive->wFlags & IDE_READY) && (pDrive->wFlags & IDE_ZIP_DEVICE)) {
01455             nIsZIP = TRUE;
01456         }
01457     }
01458 
01459     IDEFree();
01460 
01461     return (nIsZIP);
01462 }
01463 
01464 /************************************************************/
01465 /*  IDEUnMountDevice                                        */
01466 /************************************************************/
01467 int IDEUnMountDevice(BYTE bDevice)
01468 {
01469     int nError = 0;
01470     LPDRIVE pDrive;
01471 
01472     pDrive = NULL;
01473 
01474     IDELock();
01475 
01476     if (bDevice >= IDE_MAX_SUPPORTED_DEVICE) {
01477         nError = IDE_ERROR;
01478     } else {
01479         pDrive = &sDrive[bDevice];
01480 
01481         pDrive->wFlags = 0;
01482     }
01483 
01484     IDEFree();
01485 
01486     return (nError);
01487 }
01488 
01489 /************************************************************/
01490 /*  IDEGetTotalSectors                                      */
01491 /************************************************************/
01492 DWORD IDEGetTotalSectors(BYTE bDevice)
01493 {
01494     DWORD dwTotalSectors;
01495     LPDRIVE pDrive;
01496 
01497     dwTotalSectors = 0;
01498 
01499     IDELock();
01500 
01501     if (bDevice >= IDE_MAX_SUPPORTED_DEVICE) {
01502         dwTotalSectors = 0;
01503     } else {
01504         pDrive = &sDrive[bDevice];
01505         dwTotalSectors = pDrive->dwTotalSectors;
01506 
01507         dwTotalSectors -= 64;
01508     }
01509 
01510     IDEFree();
01511 
01512     return (dwTotalSectors);
01513 }
01514 
01515 /************************************************************/
01516 /*  IDEReadSectors                                          */
01517 /************************************************************/
01518 int IDEReadSectors(BYTE bDevice, void *pData, DWORD dwStartSector, WORD wSectorCount)
01519 {
01520     WORD i;
01521     int nError;
01522     WORD wReadCount;
01523     LPDRIVE pDrive = 0;
01524     BYTE *pByte;
01525 
01526     nError = IDE_OK;
01527 
01528     IDELock();
01529 
01530     if (bDevice >= IDE_MAX_SUPPORTED_DEVICE) {
01531         nError = IDE_DRIVE_NOT_FOUND;
01532     } else {
01533         pDrive = &sDrive[bDevice];
01534         if ((pDrive->wFlags & IDE_READY) == 0) {
01535             nError = IDE_DRIVE_NOT_FOUND;
01536         } else {
01537             if ((dwStartSector + wSectorCount) > pDrive->dwTotalSectors) {
01538                 nError = IDE_PARAM_ERROR;
01539             }
01540         }
01541     }
01542 
01543     if ((pDrive->wFlags & IDE_SUPPORT_PACKET) && ((wSectorCount > 1))) {
01544         //
01545         // Sorry, in this version we support
01546         // only 1 sector for PACKET devices.
01547         //
01548         nError = IDE_PARAM_ERROR;
01549     }
01550 
01551     if ((pDrive->wFlags & IDE_SUPPORT_PACKET) && (nError == IDE_OK)) {
01552 #if (IDE_SUPPORT_ATAPI == 1)
01553         //
01554         // ATAPI
01555         //
01556         ATAPI_CMD(ATAPI_CMD_READ12);
01557         i = 5;
01558         while (dwStartSector) {
01559             aATAPICmd[i--] = (BYTE) dwStartSector;
01560             dwStartSector >>= 8;
01561         }
01562         //
01563         // Reading one sector only
01564         //
01565         aATAPICmd[9] = 1;
01566         nError = ATAPISendCommand(pDrive, pData, &i);
01567         if ((nError != IDE_OK) || (i != pDrive->wSectorSize)) {
01568             nError = IDE_ERROR;
01569         }
01570 #else
01571         nError = IDE_ERROR;
01572 #endif
01573     } else {
01574         if (nError == IDE_OK) {
01575             pByte = (BYTE *) pData;
01576             while (wSectorCount > 0) {
01577 
01578                 if (wSectorCount < 256) {
01579                     wReadCount = wSectorCount;
01580                 } else {
01581                     wReadCount = 256;
01582                 }
01583 
01584                 nError = ReadSectors(bDevice, pByte, dwStartSector, wReadCount);
01585                 if (nError != IDE_OK) {
01586                     break;
01587                 }
01588 
01589                 dwStartSector += wReadCount;
01590                 wSectorCount -= wReadCount;
01591                 pByte += (wReadCount * pDrive->wSectorSize);
01592             }
01593         }
01594     }
01595 
01596     IDEFree();
01597 
01598     return (nError);
01599 }
01600 
01601 #if (IDE_SUPPORT_WRITE == 1)
01602 /************************************************************/
01603 /*  IDEWriteSectors                                         */
01604 /************************************************************/
01605 int IDEWriteSectors(BYTE bDevice, void *pData, DWORD dwStartSector, WORD wSectorCount)
01606 {
01607     int nError;
01608     WORD wWriteCount;
01609     LPDRIVE pDrive;
01610     BYTE *pByte;
01611 
01612     nError = IDE_OK;
01613     pDrive = NULL;
01614 
01615     IDELock();
01616 
01617     if (bDevice >= IDE_MAX_SUPPORTED_DEVICE) {
01618         nError = IDE_DRIVE_NOT_FOUND;
01619     } else {
01620         pDrive = &sDrive[bDevice];
01621 
01622         if ((dwStartSector + wSectorCount) > pDrive->dwTotalSectors) {
01623             nError = IDE_PARAM_ERROR;
01624         }
01625         if ((pDrive->wFlags & IDE_READY) == 0) {
01626             nError = IDE_DRIVE_NOT_FOUND;
01627         }
01628         if (pDrive->wFlags & IDE_READ_ONLY) {
01629             nError = IDE_NOT_SUPPORTED;
01630         }
01631     }
01632 
01633     if (nError == IDE_OK) {
01634         pByte = (BYTE *) pData;
01635         while (wSectorCount > 0) {
01636 
01637             if (wSectorCount < 256) {
01638                 wWriteCount = wSectorCount;
01639             } else {
01640                 wWriteCount = 256;
01641             }
01642 
01643             nError = WriteSectors(bDevice, pByte, dwStartSector, wWriteCount);
01644             if (nError != IDE_OK) {
01645                 break;
01646             }
01647 
01648             dwStartSector += wWriteCount;
01649             wSectorCount -= wWriteCount;
01650             pByte += (wWriteCount * IDE_SECTOR_SIZE);
01651         }
01652     }
01653 
01654     IDEFree();
01655 
01656     return (nError);
01657 }
01658 #endif
01659 
01660 #if (IDE_SUPPORT_ATAPI == 1)
01661 /************************************************************/
01662 /*  IDEATAPISetCDSpeed                                      */
01663 /************************************************************/
01664 int IDEATAPISetCDSpeed(BYTE bDevice, WORD wSpeed)
01665 {
01666     WORD i;
01667     int nError;
01668     LPDRIVE pDrive;
01669 
01670     nError = IDE_OK;
01671     pDrive = NULL;
01672 
01673     if (bDevice >= IDE_MAX_SUPPORTED_DEVICE) {
01674         nError = IDE_DRIVE_NOT_FOUND;
01675     } else {
01676         pDrive = &sDrive[bDevice];
01677         if ((pDrive->wFlags & IDE_READY) == 0) {
01678             nError = IDE_DRIVE_NOT_FOUND;
01679         }
01680         if ((pDrive->wFlags & IDE_SUPPORT_PACKET) == 0) {
01681             nError = IDE_NOT_SUPPORTED;
01682         }
01683     }
01684 
01685     if (nError == IDE_OK) {
01686         ATAPI_CMD(0xBB);
01687         aATAPICmd[2] = (BYTE) ((wSpeed >> 8) & 0x00FF);
01688         aATAPICmd[3] = (BYTE) (wSpeed & 0x00FF);
01689         nError = ATAPISendCommand(pDrive, NULL, &i);
01690     }
01691 
01692     return (nError);
01693 }
01694 #endif