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

📄 hdd.c

📁 MMURTL(tm) Computer Operating System Ver x0.8, source code.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* MFM & IDE Hard Disk Device Driver for MMURTL.
   This driver does not depend on the data stored
   in CMOS RAM for drive geometry.  Three routines
   determine number of sectors per track,
   number of cylinders, and number of heads
   by actually trying to seek and/or read them.
   This eliminates dependence on system proprietary
   CMOS locations.
*/

#define U32 unsigned long
#define S32 long
#define U16 unsigned int
#define S16 int
#define U8 unsigned char
#define S8 char

/* MMURTL OS PROTOTYPES */

extern far AllocExch(U32  *pExchRet);
extern far U32  InitDevDr(U32  dDevNum,
				    	  S8  *pDCBs,
					  	  U32  nDevices,
					  	  U32  dfReplace);

extern far U32  UnMaskIRQ(U32  IRQNum);
extern far U32  MaskIRQ(U32  IRQNum);
extern far U32  SetIRQVector(U32  IRQNum, S8  *pIRQ);
extern far U32  EndOfIRQ(U32  IRQNum);
extern far U32  SendMsg(U32  Exch, U32  msg1, U32  msg2);
extern far U32  ISendMsg(U32  Exch, U32  msg1, U32  msg2);
extern far U32  WaitMsg(U32  Exch, U32  *pMsgRet);
extern far U32  CheckMsg(U32  Exch, U32  *pMsgRet);
extern far U32  Alarm(U32  Exch, U32  count);
extern far U32  KillAlarm(U32  Exch);
extern far U32  Sleep(U32  count);
extern far void MicroDelay(U32  us15count);
extern far void OutByte(U8 Byte, U16 wPort);
extern far void OutWord(U16 Word, U16 wPort);
extern far U8 InByte(U16 wPort);
extern far U16 InWord(U16 wPort);
extern far U8 ReadCMOS(U16 Address);
extern far void CopyData(U8 *pSource, U8 *pDestination, U32 dBytes);
extern far InWords(U32 dPort, U8 *pDataIn, U32 dBytes);
extern far OutWords(U32 dPort, U8 *pDataOut, U32 dBytes);

/* Near External for troubleshooting */

extern long xprintf(char *fmt, ...);


/* LOCAL PROTOTYPES */

void interrupt hdisk_isr(void); 	/* The HD interrupt function */
U32  hdisk_setup(void);
U32  hd_format_track(U32 dLBA, U32 dnBlocks);
void hd_reset(void);
U32  send_command(U8  parm);
U32  hd_wait (void);
U32  check_busy(void);
U32  hd_seek(U32 dLBA);
U32  hd_recal(U8 drive);
U32  hd_write(U32 dLBA, U32 dnBlocks, U8 *pDataOut);
U32  hd_read(U32 dLBA, U32 dnBlocks, U8 *pDataIn);
U32  hd_status(U8 LastCmd);
U32  setupseek(U32 dLBA, U32 nBlks);
U32  hd_init(U8 drive);
U32 ReadSector(U32 Cylinder, U32 HdSect, U8 *pDataRet);

/* The following 3 calls are required in every MMURTL device driver */

U32  hddev_op(U32  dDevice,
 		    U32  dOpNum,
		    U32  dLBA,
		    U32  dnBlocks,
		    U8  *pData);

U32  hddev_stat(U32  dDevice,
			  S8 * pStatRet,
			  U32  dStatusMax,
			  U32  *pdSatusRet);

U32  hddev_init(U32  dDevNum,
			  S8  *pInitData,
			  U32   sdInitData);

/* LOCAL DEFINITIONS */

#define ok 0

/* Error Codes to return */

#define ErcNoMsg		20
#define ErcNotInstalled 504

#define ErcBadBlock		651
#define ErcAddrMark		652
#define ErcBadECC		653
#define ErcSectNotFound	654
#define ErcNoDrive0		655
#define ErcNotSupported 656
#define ErcBadHDC		658
#define ErcBadSeek		659
#define ErcHDCTimeOut	660
#define ErcOverRun		661
#define ErcBadLBA		662
#define ErcInvalidDrive	663
#define ErcBadOp		664
#define ErcBadRecal		665
#define ErcSendHDC		666
#define ErcNotReady		667
#define ErcBadCmd		668
#define ErcNeedsInit	669
#define ErcTooManyBlks	670		/* The controller can only do 128 max */
#define ErcZeroBlks		671		/* 0 Blocks not allowed for this cmd */
#define ErcWriteFault	672		/* WriteFault bit set... bummer */

#define ErcMissHDDInt   675

#define ErcHDDMsgBogus  676
#define ErcHDDIntMsg	677
#define ErcHDDAlarmMsg  678

/* Commands accepted by this HD driver */

#define CmdNull     0
#define CmdRead     1
#define CmdWrite    2
#define CmdVerify   3
#define CmdFmtBlk   4
#define CmdFmtTrk   5
#define CmdSeekTrk  6
#define CmdSetMedia 7   /* Not used unless mountable */
#define CmdResetHdw 8   /* Used to reset controller hardware */

/* CmdReadSect is the only device specific call in the IDE/MFM hard
   disk device driver.  This allows you to read ONE sector
   specified by Cylinder, head and Sector number.
   Cylinder is HiWord of dLBA in DeviceOp call,
   Head is LoWord of dLBA in DeviceOp call, and
   Sector number is LowWord in dnBlocks.
*/

#define CmdReadSect 256 /* only device specific call in HDD */

/* HDC port definitions */

#define HD_PORT 0x1f0

/* When writing to the port+X (where X =):
	 0 - write data       (1F0h - 16 bit)
	 1 - pre-comp         (1F1h)
	 2 - sector count     (1F2h)
	 3 - sector number    (1F3h)
	 4 - low cyl          (1F4h)
	 5 - high cyl         (1F5h)
	 6 - size/drive/head  (1F6h)
	 7 - command register (1F7h)

When reading from the port+X (where X =):
	 0 - read data       (1F0h - 16 bit)
	 1 - error register  (1F1h)
	 2 - sector count    (1F2h)
	 3 - sector number   (1F3h)
	 4 - low cyl         (1F4h)
	 5 - high cyl        (1F5h)
	 6 - size/drive/head (1F6h)
	 7 - status register (1F7h)
*/

#define HD_REG_PORT 0x3f6

/* This is a byte wide write only control port
   that allows reset and defines some special
   characteristics of the hard drives.
	Bit		Desc
	0		Not used
	1		Not used
	2		Reset Bit - Set, wait 50us, then Reset
	3		Mucho Heads Flag. Set = More than 8 heads
	4		Not used
	5		Not used
	6		Disable retries
	7		Disable retries (same as six, either one set)
*/

/* HDC Status Register Bit Masks (1F7h) */

#define BUSY        0x80  /* busy.. can't talk now! */
#define READY       0x40  /* Drive Ready  */
#define WRITE_FAULT 0x20  /* Bad news */
#define SEEKOK      0x10  /* Seek Complete */
#define DATA_REQ    0x08  /* Sector buffer needs servicing */
#define CORRECTED   0x04  /* ECC corrected data was read */
#define REV_INDEX   0x02  /* Set once each disk revolution */
#define ERROR       0x01  /* data address mark not found */

/* HDC Error Register Bit Masks (1F1h) */

#define BAD_SECTOR  0x80  /* bad block */
#define BAD_ECC     0x40  /* bad data ecc */
#define BAD_IDMARK  0x10  /* id not found */
#define BAD_CMD     0x04  /* aborted command */
#define BAD_SEEK    0x02  /* trk 0 not found on recalibrate, or bad seek */
#define BAD_ADDRESS 0x01  /* data address mark not found */


/* HDC internal command bytes (HDC_Cmd[7]) */

#define HDC_RECAL      0x10	  /* 0001 0000 */
#define HDC_READ       0x20   /* 0010 0000 */
#define HDC_READ_LONG  0x22   /* 0010 0010 */
#define HDC_WRITE      0x30   /* 0011 0000 */
#define HDC_WRITE_LONG 0x32   /* 0011 0010 */
#define HDC_VERIFY     0x40   /* 0100 0000 */
#define HDC_FORMAT     0x50   /* 0101 0000 */
#define HDC_SEEK       0x70   /* 0111 0000 */
#define HDC_DIAG       0x90   /* 1001 0000 */
#define HDC_SET_PARAMS 0x91   /* 1001 0001 */

/* L O C A L   D A T A  */

U8  hd_Cmd[8];		/* For all 8 command bytes */

U8  fDataReq;		/* Flag to indicate is fDataRequest is active */
U8  statbyte;		/* From HDC status register last time it was read */

U8  hd_control;		/* Current control byte value */
U8  hd_command;		/* Current Command */
U8  hd_drive;		/* Current Physical Drive, 0 or 1 */
U8  hd_head;		/* Calculated from LBA - which head */
U8  hd_nsectors;	/* Calculated from LBA - n sectors to read/write */
U8  hd_sector;		/* Calculated from LBA - Starting sector */

/* Current type drive 0 & 1 found in CMOS or Set by caller. */
/* Current number of heads, cylinders, and sectors set by caller */

U8  hd0_type;
U8  hd0_heads;
U8  hd0_secpertrk;
U16 hd0_cyls;

U8  hd1_type;
U8  hd1_heads;
U8  hd1_secpertrk;
U16 hd1_cyls;

#define sStatus 64

struct statstruct{
  U32 erc;
  U32 blocks_done;
  U32 BlocksMax;
  U8 fNewMedia;
  U8 type_now;		/* current fdisk_table for drive selected */
  U8 resvd0[2];		/* padding for DWord align  */
  U32 nCyl;			/* total physical cylinders */
  U32 nHead;		/* total heads on device    */
  U32 nSectors;		/* Sectors per track        */
  U32 nBPS;			/* Number of bytes per sect.  32 bytes out to here.*/

  U32 LastRecalErc0;
  U32 LastSeekErc0;
  U8  LastStatByte0;
  U8  LastErcByte0;
  U8  fIntOnReset;	/* Interrupt was received on HDC_RESET */
  U8  filler0;

  U32 LastRecalErc1;
  U32 LastSeekErc1;
  U8  LastStatByte1;
  U8  LastErcByte1;
  U8  ResetStatByte;	/* Status Byte immediately after RESET */
  U8  filler1;

  U32 resvd1[2];	/* out to 64 bytes */

  } hdstatus;

struct statstruct HDStatTmp;

struct dcbtype {
	S8   Name[12];
	S8   sbName;
	S8   type;
	S16  nBPB;
	U32  last_erc;
	U32  nBlocks;
	S8  *pDevOp;
	S8  *pDevInit;
	S8  *pDevSt;
	U8   fDevReent;
	U8   fSingleUser;
	S16  wJob;
	U32  OS1;
	U32  OS2;
	U32  OS3;
	U32  OS4;
	U32  OS5;
	U32  OS6;
	};

struct dcbtype hdcb[2];		/* two HD device control blocks */

/* Exch and msgs space for HD ISR */

U32 hd_exch;

U32 hd_msg;
U32 hd_msg2;

long HDDInt;

/*======================================================*/
/*=================== START OF CODE ====================*/
/*======================================================*/

/*********************************************************
    This is called ONCE to initialize the HD Driver.
*********************************************************/

U32  hdisk_setup(void)
{
U32  erc;

  /* first we set up the 2 DCBs in anticipation of calling InitDevDr */

 hdcb[0].Name[0]  = 'H';
 hdcb[0].Name[1]  = 'D';
 hdcb[0].Name[2]  = '0';
 hdcb[0].sbName   = 3;
 hdcb[0].type     = 1;		 /* Random */
 hdcb[0].nBPB     = 512;
 hdcb[0].nBlocks  = 524288;   /* largest disk handled - 2Gb disks*/
 hdcb[0].pDevOp   = &hddev_op;
 hdcb[0].pDevInit = &hddev_init;
 hdcb[0].pDevSt   = &hddev_stat;

 hdcb[1].Name[0]  = 'H';
 hdcb[1].Name[1]  = 'D';
 hdcb[1].Name[2]  = '1';
 hdcb[1].sbName   = 3;
 hdcb[1].type     = 1;			/* Random */
 hdcb[1].nBPB     = 512;
 hdcb[1].nBlocks  = 524288;	/* largest device handled - 2Gb disks*/
 hdcb[1].pDevOp   = &hddev_op;
 hdcb[1].pDevInit = &hddev_init;
 hdcb[1].pDevSt   = &hddev_stat;

/* These are defaulted to non zero values to
   ensure we don't get a divide by zero during initial calculations
   on the first read.
*/
 hd0_type =	ReadCMOS(0x19);
 hd0_heads = 16;			/* Max */
 hd0_secpertrk = 17;		/* most common */
 hd0_cyls = 1024;			/* Max */

 hd1_type =	ReadCMOS(0x1A);
 hd1_heads = 16;
 hd1_secpertrk = 17;
 hd1_cyls = 1024;

 erc = AllocExch(&hd_exch);		/* Exhange for HD Task to use */

 SetIRQVector(14, &hdisk_isr);
 UnMaskIRQ(14);

/* Documentation lists the fixed disk types at CMOS 11h and 12h,
   and also shows them at 19h and 1Ah.  We don't actually read them
   because they are not dependable. They vary from BIOS to BIOS.
   We have to make this sucker work the hard way.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -