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

📄 fdd.c

📁 MMURTL(tm) Computer Operating System Ver x0.8, source code.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Floppy Disk Device Driver for MMURTL */

/*
  MMURTL Operating System Source Code
  Copyright 1991,1992,1993, Richard A. Burgess
  ALL RIGHTS RESERVED
  Version x0.8
*/

#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 SpawnTask(S8  *pEntry,
		             U32 dPriority,
                     U32 fDebug,
                     S8  *pStack,
           		     U32 fOSCode);

extern far U32 AllocExch(U32 *pExchRet);

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

extern far DmaSetUp(S8  *pPhyMem,
					U32 sdMem,			/* size */
					U32 dChannel,		/* channel 2 floppy */
					U32 dType,			/* 0=Verfify, 1=IN,  2=OUT */
					U32 dMode);		/* FDC uses 1 (single cycle) */

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, S8  *pMsgRet);
extern far U32 CheckMsg(U32 Exch, S8  *pMsgRet);
extern far U32 GetTimerTick(U32 *pTickRet);
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);


/* THE FLOPPY INTERRUPT FUNCTION PROTOTYPE */

void interrupt fdisk_isr(void);

/*  PROTOTYPE FOR Floppy motor control task and associated stuff */

extern void FDMotorTask(void);
void fdmotor_task(void);
void fd_select(U32 drive);
void fd_motoroff(U32 drive);

/* THE REST OF THE PROTOTYPES */

U32 fdisk_setup(void);
U32 RdWrtVerf(U32 op);
U32 format_track(void);
U32 Set_Media(U32 drive, U32 type);
U32 FDC_reset(void);
U8  cmos_type (U8 drive_nr);
U32 send_fdc(U8 parm);
U8  GetParm(U8 index);
U32 wait_int (void);
U32 seek(void);
U32 recal(void);
U32 read_data(U8 *pDataRet);
U32 results(U32 expect);
void purge_fdc (void);
void wait_for_head(void);
U32 med_change(void);
U32 get_fdc_status(void);

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

U32 dev_op(U32 dDevice,
 		    U32 dOpNum,
		    U32 dLBA,
		    U32 dnBlocks,
		    S8  *pData);

U32 dev_stat(U32 dDevice,
			  S8 * pStatRet,
			  U32 dStatusMax,
			  U32 *pdSatusRet);
U32 dev_init(U32 dDevNum,
			  S8  *pInitData,
			  U32  sdInitData);

/* Near External for troubleshooting */

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

/* LOCAL DEFINITIONS */

#define ok    0
#define TRUE  1
#define FALSE 0

#define RATE_500 		0x00
#define RATE_300 		0x01
#define RATE_250 		0x02
#define RATE_1000       0x03
#define INT_FLAG 		0x80

/* Error Codes to return */

#define ErcNotInstalled 504
#define ErcAddrMark		602
#define ErcReadOnly		603
#define ErcSectNotFound	604
#define ErcNewMedia		605
#define ErcNotMounted	606
#define ErcCRC			607
#define ErcBadFDC		608
#define ErcBadSeek		609
#define ErcFDCTimeOut	610
#define ErcOverRun		611
#define ErcBadLBA		612
#define ErcDriveType	613
#define ErcBadOp		614
#define ErcBadRecal		615
#define ErcSendFDC		616
#define ErcResults		617
#define ErcBadCmd		618
#define ErcReadyLine	619

/* Commands accepted by driver */

#define CmdNull     0
#define CmdRead     1
#define CmdWrite    2
#define CmdVerify   3
#define CmdFmtBlk   4
#define CmdFmtTrk   5
#define CmdSeekTrk  6

/* FDC port definitions */

#define DOR_PORT	0x3f2
#define MSR_PORT	0x3f4
#define DATA_PORT	0x3f5
#define DIR_PORT	0x3f7
#define DRR_PORT	0x3f7

/* FDC Return Status bit definitions */

#define BUSY  		0x10	/* was BIT4 */
#define DSKCHANGE_BIT 0x80
#define BIT7 		0x80
#define BIT6 		0x40
#define BIT5 		0x20
#define BIT4 		0x10
#define BIT3 		0x08
#define BIT2 		0x04
#define BIT1 		0x02
#define BIT0 		0x01

#define RQM			0x80
#define DIO			0x40

/* FDC commands */

#define FDC_READ	0xe6
#define FDC_WRITE	0xc5
#define FDC_FORMAT	0x4d

/* FDC DOR register bits */

#define FD_MOTOR0	0x10
#define FD_MOTOR1   0x20
#define FD_INTS		0x08
#define FD_RESET	0x04
#define FD_DRV1SEL	0x01
#define FD_MOTMASK	0xf0		/* mask to see motor bits */

/* L O C A L   C O N S T A N T S */

/* The drive table contains parameters for each disk
   type.  The values are:
   0  - FDC SPECIFY Command byte 1
   1  - FDC SPECIFY Command byte 2
   2  - Unused
   3  - Bytes per Sector (coded 0=128, 1=256, 2=512, 3=1024);
   4  - number of sectors per track (Last sector)
   5  - Intersector Gap Size
   6  - Data Length (FFh = 512)
   7  - GAP 3 for Format Command
   8  - Fill Byte for Format command
   9  - Head settle time in milliseconds
   10 - Motor start time in milliseconds/10 (mult value by 10 to use)
   11 -	max cylinder index (number of cyls - 1)
   12 -	Xfer rate Command
   13 - Unused
   14 - Double Step Flag (e.g., 360K in a 1.2Mb drive)
   15 - Unused
*/


U8 fdisk_table[5][16]= {

 /* 0 = NO DRIVE - first two params set to allow FDC_reset */
  {0x0af,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0},

 /* 1 = 360 kb drive */
 {0x0af, 2, 0, 2, 9, 0x2a, -1, 0x50, 0x0f6, 15, 8, 39, RATE_250, 0, 0, 0},

 /* 2 = 1.2 mb drive */
 {0xaf, 2, 0, 2, 15, 0x1b, -1, 0x54, 0x0f6, 15, 8, 79, RATE_500, 0, 0, 0},

 /* 3 = 720 type drive */
 {0x0af, 2, 0, 2, 9, 0x2a, -1, 0x50, 0x0f6, 15, 8, 79, RATE_250, 0, 0, 0},

 /* 4 = 1.44 mb drive */
 {0xaf, 2, 0, 2, 18, 0x1b, -1, 0x6c, 0x0f6, 15, 8, 79, RATE_500, 0, 0, 0},

};

U32 MotorStk[75];
U32 MotorStkTop;

U8 fd_fdc_command;
U8 fd_drive;
U8 fd_nr_sectors;
U8 fd_head;
U8 fd_sector;
U8 fd_track;
U8 seek_status;
U8 fwrite;
S8  *fd_pData;

/* current fdisk_table[x] for drive 0 & 1 */

U8 type0
U8 type1

/* Record for 64 byte status and init record */

#define sStatus 64

struct statstruct{
  U32 erc;
  U32 blocks_done;
  U32 BlocksMax;
  U8 fNewMedia;
  U8 type_now;		/* current fdisk_table for drive selected */
  U8 resvd1[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 */
  U8 params[16]; 	/* begin device specific fields */
  U8 STATUS[8];		/* status returned from FDC (for user status) */
  U32 resvd3;
  U32 resvd4;		/* 64 bytes total */
  } fdstatus;

struct statstruct FDStatTmp;

U8 FDC_STATUS[8];	/* status returned from FDC */
U8 LAST_TRACK[3];  /* last track number */

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

struct dcbtype fdcb[2];		/* two floppy device control blcocks */


/* Exch, msgs space, and vars for FD Motor task */
U8 dor_crnt;		/* last value sent to DOR port */

U8 motor0_want;		/* desired motor0 state, TRUE = want ON */
U8 motor1_want;		/* desired motor1 state, TRUE = want ON */
U32 fd_tick;		/* Set to tick everytime we select a floppy */
U32 fd_newtick;		/* used to check tick time */

/* Exch and msgs space for FD ISR */
U32 fd_exch;
U32 fd_msg[2];

U32 rgSectorMax[10] = {0, 720, 2400, 1440, 2880,
						0, 0, 0, 0, 0};		/* set max sectors */

U8 sectbuf[518];	/* sector buffer for DMA */

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

void enable_ints(void)
{
;
#asm
	STI
#endasm
}

void disable_ints(void)
{
;
#asm
	CLI
#endasm
}


/********************************************************************
 This small function becomes a thread (task) just to control the motor.
 The floppy motors are controlled serarately from the rest
 of the floppy drive electronics. A single port controls both
 floppies.  After a floppy is used you don't want to shut it right
 off or you can forget about any dreams of decent throughput.
 This wakes up every 3 seconds and checks to see if there was
 any floppy activity in the past 3 seconds. If not, we shut off
 the motor(s).
**********************************************************************/

void fdmotor_task(void)
{
	enable_ints();

MotorLoop:

	Sleep(300);							/* 3 seconds */

	GetTimerTick(&fd_newtick);

	if ((fd_newtick - fd_tick) > 300) {	/* not used in last 3 seconds */

		if ((!motor0_want) && (dor_crnt & FD_MOTOR0)) { /* They want 0 off */
			disable_ints();
			dor_crnt &= ~FD_MOTOR0;
			OutByte( dor_crnt, DOR_PORT);
			enable_ints();
		}

		if ((!motor1_want) && (dor_crnt & FD_MOTOR1)) { /* They want 1 off */
			disable_ints();
			dor_crnt &= ~FD_MOTOR1;
			OutByte( dor_crnt, DOR_PORT);
			enable_ints();
		}

	}

	goto MotorLoop;
}

/*******************************************
 Set desired motor status flags and drive
 select bit.  If drive select bit has changed
 this sends the current DOR value to select
 the correct drive. If the motor bit we wanted
 isn't on, we will also send the command.
 We DO NOT mess with the other motor bit.
*******************************************/

void fd_select(U32 drive)
{
U8 fsend;
U8 fdelay;

	GetTimerTick(&fd_tick);		/* update last time selected */

	fsend = FALSE;
	fdelay = FALSE;

	if (drive) {					/* drive 1 */
		if (!(dor_crnt & 0x01)) {
			fsend = TRUE;
			dor_crnt |= 0x01;		/* select 1 */
		}
		if (!(dor_crnt & FD_MOTOR1)) {
			fsend = TRUE;
			fdelay = TRUE;
			dor_crnt |= FD_MOTOR1;	/* motor 1 on */
		}
	}
	else {
   		if (dor_crnt & 0x01) {
			fsend = TRUE;
			dor_crnt &= 0xFE;		/* select 0 (turn 1 off) */
		}
		if (!(dor_crnt & FD_MOTOR0)) {

⌨️ 快捷键说明

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