📄 ide_disk.c
字号:
/*
**************************************************************
*
* hyperstone MS-DOS FAT File System Drivers
*
* Low Level IDE Disk Access Routines
*
* Christoph Baumhof 2000-03-21
* Reinhard K乭ne 2000-03-21
* Mihajlo Varga 2000-03-21
*
* Copyright (C) 1997-2000 hyperstone electronics GmbH Konstanz
*
* 2000-03-21 initial release
*
* $Id$
*
* $Log$
*
**************************************************************
*
* Changes:
*
**************************************************************
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <io.h>
#include <sys/hyrtk.h>
#include "hy_dos.h"
#include "hybios.h"
#ifdef __DSC_CFA__
#define DSC_TIMING 0x3F8
#define REG0SEL ( (1 << 21) | DSC_TIMING)
#define REG2SEL ( (2 << 13) | REG0SEL)
#undef outpw
#undef inp
#undef inph
static inline int outpw(unsigned int addr, int value) {
*(volatile unsigned char *)addr = value;
return 0;
}
static inline int outph(unsigned int addr, int value) {
*(volatile unsigned short *)addr = value;
return 0;
}
static inline int inp (unsigned int addr) {
return * (volatile unsigned char *) addr;
}
static inline int inph (unsigned int addr) {
return * (volatile unsigned short*) addr;
}
#define Outpw(portid, value) \
({ register unsigned int dummy0 asm("L14"); \
register unsigned int dummy1 asm("L15"); \
\
dummy0 = portid; \
dummy1 = value; \
asm volatile ("STW.IOD %1, %0, 0" \
: "l=" (dummy1) \
: "l" (dummy0), "l" (dummy1));\
dummy1; \
})
#define Inpw(portid) \
({ register unsigned int dummy asm("L15"); \
\
dummy = portid; \
asm volatile ("LDW.IOD %0, %0, 0" \
: "=l" (dummy) \
: "l" (dummy) \
: "L15"); \
dummy; \
})
#else
#define outph outpw
#endif
struct hd_geometry _hd_ident[MAX_CHANNEL_NUM*2];
struct _drive_tab {
unsigned int xHD_DATA;
unsigned int xHD_ERROR;
unsigned int xHD_NSECTOR;
unsigned int xHD_SECTOR;
unsigned int xHD_LCYL;
unsigned int xHD_HCYL;
unsigned int xHD_CURRENT;
unsigned int xHD_STATUS;
unsigned int xHD_CMD;
unsigned int xHD_ALTSTATUS;
};
struct drive_tab_hardware {
unsigned int cs1; /* first register file */
unsigned int cs2; /* second register file */
unsigned int addroffs; /* register select */
unsigned int timeing; /* timing */
unsigned int word_access;/* 16 bit select */
unsigned int irq; /* used interrupt channel */
int drive; /* 0 = Master, 1= Slave */
};
static struct _drive_tab drive_tab[MAX_CHANNEL_NUM*2];
static struct drive_tab_hardware hardware_drv;
static int _init_hardware_tab(struct drive_tab_hardware * hw, int IO16) {
int index;
index = hw->drive;
drive_tab[index].xHD_DATA = hw->cs1 | (HD_DATA << hw->addroffs) | hw->timeing |
hw->word_access;
drive_tab[index].xHD_ERROR = hw->cs1 | (HD_ERROR << hw->addroffs) | hw->timeing;
drive_tab[index].xHD_NSECTOR= hw->cs1 | (HD_NSECTOR << hw->addroffs) | hw->timeing;
drive_tab[index].xHD_SECTOR = hw->cs1 | (HD_SECTOR << hw->addroffs) | hw->timeing;
drive_tab[index].xHD_LCYL = hw->cs1 | (HD_LCYL << hw->addroffs) | hw->timeing;
drive_tab[index].xHD_HCYL = hw->cs1 | (HD_HCYL << hw->addroffs) | hw->timeing;
drive_tab[index].xHD_CURRENT= hw->cs1 | (HD_CURRENT << hw->addroffs) | hw->timeing;
drive_tab[index].xHD_STATUS = hw->cs1 | (HD_STATUS << hw->addroffs) | hw->timeing;
drive_tab[index].xHD_CMD = hw->cs2 | (HD_CMD << hw->addroffs) | hw->timeing;
drive_tab[index].xHD_ALTSTATUS = hw->cs2 | (HD_ALTSTATUS << hw->addroffs) | hw->timeing;
return 0;
}
static unsigned int drivebusy(int drive) {
return inp(drive_tab[drive].xHD_ALTSTATUS) & BUSY_STAT ? 1 : 0;
}
static unsigned int drivebusy_drdy(int drive) {
return (inp(drive_tab[drive].xHD_ALTSTATUS) & (READY_STAT | SEEK_STAT)) == (READY_STAT | SEEK_STAT) ? 0 : 1;
}
static unsigned int drivebusy_drq(int drive) {
return (inp(drive_tab[drive].xHD_ALTSTATUS) & (READY_STAT | SEEK_STAT | DRQ_STAT)) == (READY_STAT | SEEK_STAT | DRQ_STAT) ? 0 : 1;
}
static unsigned int testAltSTAT(int drive, int status)
{
int alt_status;
alt_status = inp(drive_tab[drive].xHD_ALTSTATUS);
while ((alt_status & BUSY_STAT) == BUSY_STAT)
{
DelayBy(100);
alt_status = inp(drive_tab[drive].xHD_ALTSTATUS);
}
return (alt_status & status) == status ? 1 : 0;
}
/*
drive physical drive
*/
static unsigned reset_IDE_DRIVE(int drive) {
int testval;
if (drive >= MAX_CHANNEL_NUM*2)
return 1;
/* ATA device present: plausibility test */
testval = 0x55;
outpw(drive_tab[drive].xHD_LCYL, testval);
outpw(drive_tab[drive].xHD_HCYL, ~testval);
testval = inp(drive_tab[drive].xHD_LCYL) & 0xFF;
if (testval != 0x55)
return 2;
testval = 0xAA;
outpw(drive_tab[drive].xHD_LCYL, testval);
outpw(drive_tab[drive].xHD_HCYL, ~testval);
testval = inp(drive_tab[drive].xHD_LCYL) & 0xFF;
if (testval != 0xAA)
return 3;
outpw(drive_tab[drive].xHD_CMD, 0x0E); /* SRST = 1 */
DelayBy(10000);
outpw(drive_tab[drive].xHD_CMD, 0x0A); /* SRST = 0 */
while (drivebusy(drive));
/* outpw(drive_tab[drive].xHD_CMD, 0x08);*/ /* Enable IRQ */
/* while(drivebusy()); */
return 0;
}
static unsigned _Reset_IDE_DRIVE(struct diskinfo_t *dinfo) {
return reset_IDE_DRIVE(dinfo->drive);
}
static void ReadSectors(unsigned int drive, unsigned short *buffer,
unsigned int NumberOfSectors);
static void WriteSectors(unsigned int drive, unsigned short *buffer,
unsigned int NumberOfSectors);
int r_w_Disk(int drive, unsigned long LogNumber,
unsigned long sect_cnt, unsigned short *buffer, int rw) {
unsigned long iCount;
#ifdef __DSC_CFA__
Outpw(REG0SEL, 1); /* enable PCMCIA */
Outpw(REG2SEL, Inpw(REG2SEL) & ~(1<<2)); /* enable PCMCIA Wait Pin */
UpdateBCR( (0x05 << 24) | 0x0a, (0x0a<<24) | 5);
// mem2: 1 setup, 6 access, 2 hold
UpdateMCR( 3 << 4, 1 << 26);
// mem2: 8 bit, wait pin enable
#endif
while (drivebusy(drive));
if (_hd_ident[drive].lba & LBA_capability) {
outpw(drive_tab[drive].xHD_CURRENT, ((LogNumber >> 24) & 0x0F) | 0xE0);
outpw(drive_tab[drive].xHD_SECTOR, LogNumber & 0xFF); /* Sector Nr. */
outpw(drive_tab[drive].xHD_LCYL, (LogNumber >> 8) & 0xFF);
outpw(drive_tab[drive].xHD_HCYL, (LogNumber >> 16) & 0xFF);
}
else {
iCount = LogNumber / (_hd_ident[drive].heads * _hd_ident[drive].sectors);
outpw(drive_tab[drive].xHD_LCYL, iCount & 0xFF);
outpw(drive_tab[drive].xHD_HCYL, (iCount >> 8) & 0xFF);
iCount = (LogNumber % _hd_ident[drive].sectors)+1;
outpw(drive_tab[drive].xHD_SECTOR, iCount); /* Sector Nr. */
iCount = (LogNumber/_hd_ident[drive].sectors) % _hd_ident[drive].heads;
outpw(drive_tab[drive].xHD_CURRENT, 0xA0 | iCount);
}
for (; sect_cnt; ) {
unsigned long tmp_sect;
if (sect_cnt > 256) {
sect_cnt -= 256;
tmp_sect = 256;
}
else {
tmp_sect = sect_cnt;
sect_cnt = 0;
}
outpw(drive_tab[drive].xHD_NSECTOR, tmp_sect & 0xFF);
if (rw == READ)
{
#if 0
int j;
outpw(drive_tab[drive].xHD_STATUS, WIN_READ);
for (j=0; j < tmp_sect; j++)
{
if (!testAltSTAT(drive, READY_STAT | SEEK_STAT | DRQ_STAT))
break;
#ifdef __DSC_CFA__
UpdateMCR(1 << 5, 1 << 4);
#endif
for (iCount=0; iCount < SECTOR_SHORTS; iCount++)
*buffer++ = CvtByteOrder16(inph(drive_tab[drive].xHD_DATA));
#ifdef __DSC_CFA__
UpdateMCR(3 << 4, 0);
#endif
}
#else
ReadSectors(drive, buffer, tmp_sect);
#endif
}
if (rw == WRITE)
{
#if 0
int j;
unsigned short data16;
/* write sector(s) */
while (drivebusy(drive));
outpw(drive_tab[drive].xHD_STATUS, WIN_WRITE);
for (j=0; j < tmp_sect; j++)
{
if (!testAltSTAT(drive, READY_STAT | SEEK_STAT | DRQ_STAT))
break;
#ifdef __DSC_CFA__
UpdateMCR(1 << 5, 1 << 4);
#endif
for (iCount=0; iCount < SECTOR_SHORTS; iCount++)
{
data16 = CvtByteOrder16(*buffer++);
outph(drive_tab[drive].xHD_DATA, data16);
}
#ifdef __DSC_CFA__
UpdateMCR(3 << 4, 0);
#endif
}
#else
WriteSectors(drive, buffer, tmp_sect);
#endif
}
}
return 0;
}
static void ReadSectors(unsigned int drive, unsigned short *buffer,
unsigned int NumberOfSectors)
{
int iCount, j, DataReg;
outpw(drive_tab[drive].xHD_STATUS, WIN_READ);
DataReg = drive_tab[drive].xHD_DATA;
for (j=0; j < NumberOfSectors; j++)
{
if (!testAltSTAT(drive, READY_STAT | SEEK_STAT | DRQ_STAT))
break;
#ifdef __DSC_CFA__
UpdateMCR(1 << 5, 1 << 4);
#endif
for (iCount=SECTOR_SHORTS/2; iCount > 0; iCount--)
{
*buffer++ = CvtByteOrder16(inph(DataReg));
*buffer++ = CvtByteOrder16(inph(DataReg));
}
#ifdef __DSC_CFA__
UpdateMCR(3 << 4, 0);
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -