[comp.os.minix] Compiling Minix with MSC

hgm@beta.UUCP (Harry McGavran) (07/13/87)

I am posting this response to Eric Roskos, uw-beaver!tikal!amc!ipmoea!ericr,
because the troubles he is having with developing a MSC environment for MINIX
I have seen before, and thought my experience might be helpful to others
as well.

Eric writes:
>1) What are the "absread" and "abswrite" functions that are used in build.c
>to write the boot disk out under DOS?	I had assumed that they were just
>simple calls to the DOS absolute disk I/O routines, (not the BIOS, the DOS
>ones), but after finding it didn't work and doing several days of debugging
>on it, I've reached the conclusion that these apparently write the disk
>sectors out in a different physical sequence than the Minix boot code tries
>to read in.  ............


The "absread" and "abswrite" I assumed were to be used in build were
to be scarfed from diskio.asm. Those routines simply failed under DOS,
but INT 25 and INT 26 are known to have subtle effects, something I had
suffered through a long time ago. I wrote a couple absolute disk io
routines myself to avoid having to remember what the subtle problems were
every time, so I just switched to those. The calling sequence was different
so I changed the build source to conform to my library, rather than the
other way around, since I used these routines in lots of places in my other
codes. It also meant changing the code for the error handling from these
routines in build as well.


Code replaced in build:
-------------------------------

read_block (blocknr,user)
int blocknr;
char user[SECTOR_SIZE];
{
  /* read the requested MINIX-block in core */
  int retries,err,i;
  char *p;
  unsigned int flags;

  retries = MAX_RETRIES;
  do
      err = abs_read(drive, 1, blocknr, buff, &flags) & 1;
  while (err && --retries);

  if (!retries)
    dexit ("reading",drive,blocknr,flags);

  p=buff; i=SECTOR_SIZE;
  while (i--) *(user++) = *(p++);
}



write_block (blocknr,user)
int blocknr;
char user[SECTOR_SIZE];
{
  /* write the requested MINIX-block to disk */
  int retries,err,i;
  char *p;
  unsigned int flags;

  p=buff; i=SECTOR_SIZE;
  while (i--) *(p++) = *(user++);

  retries = MAX_RETRIES;
  do
      err = abs_write(drive, 1, blocknr, buff, &flags) & 1;
  while (err && --retries);

  if (!retries)
    dexit ("writing",drive,blocknr,flags);
}

dexit (s,drive,sectnum,err)
int sectnum, err,drive;
char *s;
{ extern char *derrtab[];
  printf ("Error %s drive %c, sector: %d, code: 0x%x, %s\n",
	   s, drive+'A',sectnum, err, derrtab[(err&0xff)+1] );
  exit (2);
}
------------------------------


That fixed the problem. Routines follow.
(The include file specified the memory model, you can figure out
for yourself what it contains, it just handles the offsets for
the argument lists automatically. As I recall, for MINIX, just setting
off EQU 02H, should be sufficient for model.h)	I had to edit these
sources in from another location, so hopefully I didn't make any errors.
I checked a couple times and it looks ok, but to be safe you should
check for yourself. The code is pretty simple and fairly well commented.

absread replacement:
-----------------------------
	name  abs_read

	include model.h

;do an absolute disk read
;ds:bx will contain the data read
;carry_flag =  abs_read(drive, #_sec_2_read, start_sec, buffer, ret_flags);

if	@large_code
abs_read_TEXT	segment byte public 'CODE'
		assume cs:abs_read_TEXT, ds:nothing
else
_TEXT		segment byte public 'CODE'
		assume cs:_TEXT, ds:nothing
endif

	public	_abs_read

if	@large_code
_ abs_read	proc	far
else
_ abs_read	proc	near
endif

start:	push	bp
	mov	bp,sp
	push	di
	push	si
	push	es
if	@large_data
	push	ds		;save ds
endif
	push	bp		;save bp, int 25 destroys it

	mov	ax,[bp + @off + 00H]	;drive number
	mov	cx,[bp + @off + 02H]	;number of sectors
	mov	dx,[bp + @off + 04H]	;beginning sector number
	mov	bx,[bp + @off + 06H]	;transfer area offset address
if	@large_data
	mov	ds,[bp + @off + 08H]	;transfer area segment address
endif

	int	25H		;absolute disk read
	pushf			;put carry flag in ax
	pop	ax;		;return value

	pop	cx		;int 25 pushes return flags
				;save them

	pop	bp		;restore bp
if	@large_data
	mov	bx,[bp + @off + 0AH]	;offset of flag
	mov	ds,[bp + @off + 0CH]	;segment of flag
else
	mov	bx,[bp + @off + 08H]	;offset of flag
				;segment in small model is constant
endif
	mov	[bx],cx 	;return flags

done:				;restore registers
if	@large_data
	pop	ds
endif
	pop	es
	pop	si
	pop	di
	mov	sp,bp
	pop	bp
	ret

_ abs_read	endp

if	@large_code
abs_read_TEXT	ends
else
_TEXT		ends
endif

		end
----------------------


abswrite replacement:
-----------------------------
	name abs_write

	include model.h

;do an absolute disk write
;ds:bx constains the data to write
;carry_flag = abs_write(drive, #_sec_2_read, start_sec, buffer, ret_flags);

if	@large_code
abs_writ_TEXT	segment byte public 'CODE'
		assume cs:abs_writ_TEXT, ds:nothing
else
_TEXT		segment byte public 'CODE'
		assume cs:_TEXT, ds:nothing
endif

	public	_abs_write

if	@large_code
_abs_write	proc	far
else
_abs_write	proc	near
endif

start:	push	bp
	mov	bp,sp
	push	di
	push	si
	push	es
if	@large_data
	push	ds			;save ds
endif
	push	bp			;save bp, int 25 destroys it

	mov	ax,[bp + @off + 00H]	;drive number
	mov	cx,[bp + @off + 02H]	;number of sectors
	mov	dx,[bp + @off + 04H]	;beginning sector number
	mov	bx,[bp + @off + 06H]	;transfer area offset address
if	@large_data
	mov	ds,[bp + @off + 08H]	;transfer area segment address
endif

	int	26H		;absolute disk write
	pushf			;put carry flag in ax
	pop	ax;		;return value

	pop	cx		;int 26 pushes return flags
				;save them

	pop	bp		;restore bp
if	@large_data
	mov	bx,[bp + @off + 0AH]	;offset of flag
	mov	ds,[bp + @off + 0CH]	;segment of flag
else
	mov	bx,[bp + @off + 08H]	;offset of flag
				;segment in small model is constant
endif
	mov	[bx],cx 	;return flags

done:				;restore registers
if	@large_data
	pop	ds
endif
	pop	es
	pop	si
	pop	di
	mov	sp,bp
	pop	bp
	ret

_abs_write	endp

if	@large_code
abs_writ_TEXT	ends
else
_TEXT		ends
endif

		end

--------------------------------

Eric writes:
>In the routine mm_init() in the file main.c in mm, on line 5517 in the
>textbook, mm_init calls a routine called get_tot_mem().  I can't figure out
>where this routine is in the source files!  It's not in the cross reference
>at the end of the book, and I've been unsuccessful in searching for it with
>grep.	Can anyone tell me where it is?

2)  Finding get_tot_mem was a problem for me too. It turns out that
it is supposed to be in getutil.asm in the library, BUT, in so much
of the junk under C86, the names were truncated. I had to go through
all the library, kernel, etc. stuff, extend the names and prepend "_"
for MSC. There are suggestions in the cross development
stuff that you just start with PC-IX instead, (or the MINIX
assembly source) I eventually found it was easier to translate that
back into MASM, than to use the C86 junk. There are also errors in
the C86 stuff in other places as well. Look in getutil.s under PC-IX or MINIX.

As usual, I make no statements as to the suitability of these suggestions
for anything. Hopefully, those interested in using MSC will find them
at least entertaining. MSC works well for me for MINIX.


Harry McGavran
Group C-8
Los Alamos National Laboratory
ARPA:  hgm@lanl.GOV
USENET: ihnp4!lanl!hgm
	cmcl2!lanl!hgm