⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ide_disk.c

📁 德国Hyperstone公司dsp的CF卡驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 **************************************************************
 *
 *  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 + -