summaryrefslogtreecommitdiff
path: root/cpu/amd/geode_lx/gplvsa_ii/legacy/ide.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/amd/geode_lx/gplvsa_ii/legacy/ide.c')
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/ide.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/ide.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/ide.c
new file mode 100755
index 0000000..9e6d00c
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/ide.c
@@ -0,0 +1,158 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* This file contains code for power-managing the ATA drives.
+
+
+#include "vsa2.h"
+#include "isa.h"
+
+extern UCHAR pascal in_8(USHORT);
+extern void pascal out_8(USHORT, UCHAR);
+
+
+// NOTE: Win95 touches CD-ROMs every 4.2 seconds for AutoDetect
+
+#define HDD0 1
+#define HDD1 2
+#define HDD2 4
+#define HDD3 8
+
+#define IDE_BSY 0x80 // Status register
+#define IDE_RDY 0x40 // Status register
+#define IDE_MSK IDE_BSY+IDE_RDY
+
+#define IDE_CMD_SPINDOWN 0xE0 // Spindown Command
+#define IDE_CMD_SPINUP 0xE1 // Spinup Command
+#define IDE_CMD_CHECK_POWER_MODE 0xE5 // Get Power Management State Command
+#define IDE_CMD_SLEEP 0xE6
+
+UCHAR DrivesPresent = 0, DrvHd;
+
+
+//*************************************************************************
+// Issues specified command to one or more drive units
+//*************************************************************************
+void pascal IDE_Command(UCHAR DriveUnit, UCHAR Command)
+{ UCHAR DriveSelect, Mask = 1;
+ USHORT IO_Port;
+ ULONG Timeout;
+
+ // Only spindown drives that are present
+ DriveUnit &= DrivesPresent;
+
+ while (DriveUnit) {
+
+ // Is drive present ?
+ if (DriveUnit & Mask) {
+
+ // Yes, determine I/O port
+ IO_Port = PRIMARY_IDE;
+ if (Mask & (HDD2+HDD3)) {
+ IO_Port = SECONDARY_IDE;
+ }
+
+ // Determine master/slave
+ DriveSelect = 0xA0; // Master drive
+ if (Mask & (HDD1+HDD3)) {
+ DriveSelect = 0xB0; // Slave drive
+ }
+
+ // Wait for IDE channel READY
+ for (Timeout=0xFFFFF; Timeout; Timeout--) {
+ if ((IDE_MSK & in_8(IO_Port+1)) == IDE_RDY)
+ break;
+ }
+
+ DrvHd = in_8(IO_Port); // Save Drive/Head register
+
+ out_8(IO_Port, DriveSelect); // Select drive to spin down
+ out_8(IO_Port+1, Command); // Issue command to the the drive
+
+ for (Timeout=0xFFFFF; Timeout; Timeout--) {
+ if (!(in_8(IO_Port+1) & IDE_BSY))
+ break;
+ }
+
+ in_8(IO_Port+1); // Clear IRQ
+
+ DriveUnit &= ~Mask;
+ }
+
+ // Next drive
+ Mask <<= 1;
+ }
+}
+
+//*************************************************************************
+// Spins down specified drive(s)
+//*************************************************************************
+void pascal SpinDownHardDrive(UCHAR DriveUnit)
+{
+ IDE_Command(DriveUnit, IDE_CMD_SPINDOWN);
+}
+
+
+//*************************************************************************
+// Puts drive(s) into sleep mode
+//*************************************************************************
+void pascal DriveSleep(UCHAR DriveUnit)
+{
+// IDE_Command(DriveUnit, IDE_CMD_SLEEP);
+}
+
+//*************************************************************************
+// Determines what hard drives are present
+// Input: I/O address of IDE Drive/Head register
+//*************************************************************************
+UCHAR Check_IDE_Channel(USHORT IDE_DrvHd)
+{ UCHAR HDD_Status, DrivesPresent=0;
+
+ DrvHd = in_8(IDE_DrvHd); // Save Drive/Head register
+
+ out_8(IDE_DrvHd, (UCHAR)(DrvHd & ~0x10)); // Select master drive
+ HDD_Status = in_8(IDE_DrvHd);
+ if (in_8(IDE_DrvHd+1) == 0x50) { // Is drive present ?
+ DrivesPresent |= HDD0;
+
+ out_8(IDE_DrvHd, (UCHAR)(DrvHd | 0x10)); // Select slave drive
+ HDD_Status = in_8(IDE_DrvHd);
+ if (in_8(IDE_DrvHd+1) == 0x50) { // Is drive present ?
+ DrivesPresent |= HDD1;
+ }
+ }
+
+ // Restore Drive/Head register
+ out_8(IDE_DrvHd, DrvHd);
+ return DrivesPresent;
+}
+
+
+//*************************************************************************
+// Determines what hard drives are present
+// Input: I/O address of IDE Drive/Head register
+//*************************************************************************
+UCHAR GetDrivesPresent(void)
+{
+ DrivesPresent = Check_IDE_Channel(PRIMARY_IDE);
+ DrivesPresent |= Check_IDE_Channel(SECONDARY_IDE) << 2;
+
+ return DrivesPresent;
+}