 /********************************************************\  *              IBM Hard Disk driver (using BIOS calls)   * *                                                        * * Copyright (c) Quantum Software Systems Ltd. 1983       * \********************************************************//* * Define physical Drive characteristics for 20 Mb hard disk */#define SCTRS_PER_TRACK	17#asm "NUM_CYLINDERS		= 612"#asm "NUM_HEADS			= 4"#asm "SCTRS_PER_TRACK	= 17"#define HARD_DISK_EVENT	6/* * Note: Only DMA Channels 1 or 3 may be used */#define READ_BLK		2#define WRITE_BLK		3#define TYPE_HARD  		1#asm "TYPE_HARD = 1"#define FBLK_SIZE		512 /*****************************************************\ *	Header Information (16 bytes)"                     * *	NOTE: This must be the first file linked           * \*****************************************************/#asm "		seg 1"#asm "	w	data	TYPE_HARD"#asm "	w	data	<Disk_init>"#asm "	w	data	<Blk_read>"#asm "	w	data	<Blk_write>"#asm "		rmb 8"/* *	default disk table parameters (16 bytes)" */#asm "b data TYPE_HARD"#asm "b data 0"											/* physical drive */#asm "w data 0"											/* block offset */#asm "w data 0"											/* sectors/disk */#asm "w data 0"											/* sectors/cylinder */#asm "b data SCTRS_PER_TRACK"							/* sectors/track */#asm "b data 1"											/* Sector base */#asm "w data 320h"										/* I/O Port */#asm "b data 5"											/* Interrupt */#asm "w data NUM_CYLINDERS"								/* number of tracks */#asm "b data 0"#asm " seg 3"struct disk_entry {	char disk_type;	char disk_drv;	unsigned blk_offset;	unsigned num_sctrs;	unsigned sctr_cyl;	char sctr_trk;	char sctr_base;	unsigned ctl_addr;	char ctl_int;	unsigned num_tracks;	char disk_filler[1];	} ;#asm "BLK_OFFSET	= 2"#asm "NUM_SCTRS		= 4"#asm "SCTR_CYL		= 6"#asm "SCTR_TRK		= 8"#asm "SCTR_BASE		= 9"struct disk_entry *disktab;unsigned drive;unsigned track, head, sector;char mode = 0;unsigned int15_save[2];/* * Initialize the hard disk controller. * disk_init is called when the driver is mounted. */disk_init(dtab,index) {	register struct disk_entry *dp;	disktab = dtab;	dp = disktab;	dp += index;	init_int();	if(@&dp->sctr_cyl != 0) /* Overridden by MOUNT */		return(0);	asm("mov dl,#80h");	asm("mov ah,#8");		/* get disk parameters */	asm("int 13h");	asm("b mov <head>,dh");	asm("b mov <track>,ch");	asm("b mov <sector>,cl");	asm("b and <sector>,#3fh");	asm("shl cx");	asm("shl cx");	asm("and ch,#3");	asm("b mov <track>+1,ch");	++head;	++track;	dp = disktab;	dp += index;	@&dp->sctr_trk = sector;	@&dp->sctr_cyl = head * sector;	@&dp->num_tracks = track;	if(@&dp->num_sctrs == 0)		@&dp->num_sctrs = head * track * sector;	return(0);	}/* * Read a block (512 bytes) from the disk corresponding to * the block number (1..NUM_BLKS) into memory in segment 'seg' * at address 'dbuf' */blk_read(drv, blk, dbuf, seg) {	if(map_sector(--drv, blk)) /* results in head, track, sector */		return(-1);	mode = READ_BLK;	return(r_w_blk(dbuf, seg));	}/* * Write a block (512 bytes) to the disk corresponding to * the block number (1..NUM_BLKS) from memory in segment 'seg' * at address 'dbuf' */blk_write(drv, blk, dbuf, seg) {	if(map_sector(--drv, blk)) /* results in head, track, sector */		return(-1);	mode = WRITE_BLK;	return(r_w_blk(dbuf, seg));	}r_w_blk(dbuf, seg) {	asm("mov dl,<drive>");	asm("or dl,#80h");	asm("mov dh,<head>");	asm("mov ax,<track>");	asm("mov ch,al");			/* bottom 8 bits of track */	asm("shr ax");	asm("shr ax");	asm("and al,#0c0h");	asm("mov cl,<sector>");	asm("or cl,al");			/* top 2 bits of track */	asm("mov al,#1");	asm("mov es,16[bp]");	asm("mov bx,14[bp]");	asm("mov ah,<mode>");	asm("int 13h");	asm("mov al,ah");	/* return status */	asm("mov ah,#0");	}/* * Convert block number into head, track, and sector * * Rely on the fact that the extra-segment points to the * data segment of the file system. 'disktab' is the address * of the disk table in that address space. */map_sector(drv, blk)unsigned blk;int drv;	{	register struct disk_entry *dp;	dp = disktab;	dp += drv;	if(@&dp->disk_type != TYPE_HARD)		return(-1);	drive = @&dp->disk_drv & 0x07;	if(--blk >= @&dp->num_sctrs)		return(-1);	if(@&dp->sctr_cyl == 0  ||  @&dp->sctr_trk == 0)		return(-1);/*	track = blk / @&dp->sctr_cyl;	blk -= (track * @&dp->sctr_cyl);	/* get remainder */	head = blk / @&dp->sctr_trk;	sector = blk - (head * @&dp->sctr_trk) + @&dp->sctr_base;*/	asm("mov ax,BLK_OFFSET[es:di]");	asm("xor dx,dx");	asm("add ax,16[bp]");	asm("adc dx,#0");	asm("div SCTR_CYL[es:di]");		/* assume 16 bit result in AX */	asm("mov <track>,ax");	asm("mov ax,dx");				/* now div remainder to get head */	asm("xor dx,dx");	asm("mov cl,SCTR_TRK[es:di]");	asm("xor ch,ch");	asm("div cx");	asm("mov <head>,ax");	asm("mov al,SCTR_BASE[es:di]");	asm("xor ah,ah");	asm("add ax,dx");				/* remainder from last div in DX */	asm("mov <sector>,ax");	return(0);	}attach(port) {	asm("push 14[bp]");	asm("call attach");	asm("add sp,#2");	}#asm "SIGNAL = 71h"#asm "DISKEVENT = 7"#asm "		seg 1"#asm "		export trap_int15"#asm "trap_int15:"#asm "		cmp ax,#9000h"#asm "		je hard_wait"#asm "		cmp ax,#9100h"#asm "		je hard_int"#asm "	abs	jmp @cs:<int15_save>"#asm "		export hard_wait"#asm "hard_wait:"#asm "		push ax"#asm "		push es"#asm "		push ds"#asm "		mov ax,cs"#asm "		mov ds,ax"#asm "		mov ax,#DISKEVENT"#asm "		push ax"#asm "		call <await>"#asm "		add sp,#2"#asm "		mov ax,#40h"#asm "		mov es,ax"#asm "	b	mov es:08Eh,#0ffh ; indicate interrupt occured"#asm "		pop ds"#asm "		pop es"#asm "		pop ax"#asm "		iret"#asm "hard_int:"#asm "		iret"/* * Initialize the hard disk interrupt and trap int 15 */static init_int() {	asm("push es");	asm("cli");	asm("xor ax,ax");	asm("mov es,ax");	asm("mov ax,es:4*15h");	asm("mov <int15_save>,ax");	asm("mov ax,es:4*15h+2");	asm("mov <int15_save>+2,ax");	asm("mov es:4*15h,#trap_int15");	asm("mov es:4*15h+2,cs");	asm("mov es:4*0F6h,#diskint");  /* catch physical disk interrupts */	asm("mov es:4*0F6h+2,cs");	asm("b in 0a1h");	asm(" and al,#~40h");	asm(" jmp .");	asm("b out 0a1h");	asm("sti");	asm("pop es");	}#asm " seg 1"#asm " export diskint"#asm "diskint: "#asm " push ax"#asm " mov al,#20h"#asm "b out 0a0h"#asm " jmp ."#asm "b out 020h"#asm "signal: "#asm " push bp"#asm " push bx"#asm " push cx"#asm " push dx"#asm " push si"#asm " push di"#asm " push es"#asm " push ds"#asm " mov ax,#DISKEVENT"#asm " int SIGNAL			;signal will not return here" /********************************************************** *              Support routines                           * **********************************************************/#asm "		seg 1"#asm "<Disk_init>:"#asm "		call	prologue"#asm "		push ds"#asm "		push es"#asm "		mov ax,ds"#asm "		mov es,ax"#asm "		mov ax,cs"#asm "		mov ds,ax"#asm "		push 18[bp]"#asm "		push 16[bp]"#asm "		call <disk_init>"#asm "		add sp,#4"#asm "		pop	es"#asm "		pop ds"#asm "		jmp	Epilogue"#asm "<Blk_write>:		"#asm "		call	prologue"#asm "		push ds"#asm "		push es"#asm "		mov ax,ds"#asm "		mov es,ax"#asm "		mov ax,cs"#asm "		mov ds,ax"#asm "		push 22[bp]"#asm "		push 20[bp]"#asm "		push 18[bp]"#asm "		push 16[bp]"#asm "		call <blk_write>"#asm "		add sp,#8"#asm "		pop	es"#asm "		pop ds"#asm "		jmp	Epilogue"#asm "<Blk_read>:		"#asm "		call	prologue"#asm "		push ds"#asm "		push es"#asm "		mov ax,ds"#asm "		mov es,ax"#asm "		mov ax,cs"#asm "		mov ds,ax"#asm "		push 22[bp]"#asm "		push 20[bp]"#asm "		push 18[bp]"#asm "		push 16[bp]"#asm "		call <blk_read>"#asm "		add sp,#8"#asm "		pop	es"#asm "		pop ds"#asm "		jmp	Epilogue"#asm "attach:"#asm "		mov ax,#4"#asm "		int 70h"#asm "		ret"#asm "<await>:"#asm "		mov ax,#6"#asm "		int 70h"#asm "		ret"#asm "prologue:"#asm "		pop	ax		;save return address in ax"#asm "		push bp"#asm "		push bx"#asm "		push cx"#asm "		push dx"#asm "		push si"#asm "		push di"#asm "		mov	bp,sp"#asm "		push ax"#asm "		ret		;go back to the function with everything saved"#asm "Epilogue:"#asm "		mov	sp,bp"#asm "		pop	di"#asm "		pop	si"#asm "		pop	dx"#asm "		pop	cx"#asm "		pop	bx"#asm "		pop	bp"#asm "	abs	ret"#asm "epilogue:"#asm "		mov	sp,bp"#asm "		pop	di"#asm "		pop	si"#asm "		pop	dx"#asm "		pop	cx"#asm "		pop	bx"#asm "		pop	bp"#asm "		ret"#asm "		seg 3"#asm "TEMP:"#asm "		rmb 2"#asm "SAVE:"#asm "		rmb 2"