[comp.unix.xenix] Format 1024+ cyls.

tony@ajfcal.uucp (tony field) (12/09/89)

How does one format a disk with greater than 1024 cylendars?  I have
tried software such as SpeedStore or Ontrack's disk manager, however
they seem to fail over 1024 cyls, probably because the rom facilities
do not permit the formatting operation.  I have also tried the
internal formatting facilities of WD1003 controllers and that still
fails.

tony...

swatt@cup.portal.com (Steven Edward Watt) (12/13/89)

  I wound up writing a little program to do this...  You have to run the
controller hardware directly, though....

This was only run on a WD1106-WA2.

--------Cut here--------------------
#!/bin/sh
#
#  Feed me to sh
#
#
echo x - fmthd.c
sed 's/^X//' >fmthd.c <<'*-*-END-of-fmthd.c-*-*'
X#include <stdio.h>
X#include <conio.h>
X
X#define START	1000
X#define END		1166
X
X#define DRIVE	0
X#define HEADS	7
X#define SECS_PER_TRACK	17
X
X#define DATA_REG	0x1f0
X#define ERROR_REG	0x1f1
X#define PRECOMP_REG	0x1f1
X#define COUNT_REG	0x1f2
X#define SECTOR_REG	0x1f3
X#define CYL_LOW_REG	0x1f4
X#define CYL_HI_REG	0x1f5
X#define DRV_HD_REG	0x1f6
X  #define drive_head(d, h) (0xA0 | (d << 4) | (h))
X
X#define STATUS_REG	0x1f7
X#define COMMAND_REG	0x1f7
X
X#define RESET_COMMAND	0x1F
X#define FORMAT_COMMAND	0x50
X
Xunsigned char interleave_table[512] = {
X	0,  1, 0,  2, 0,  3, 0,  4, 0,  5, 0,  6, 0,  7, 0,  8, 0,  9,
X	0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0, 17
X};
X
Xdoinp(unsigned x)
X{
X	unsigned short val;
X
X	val = inp(x);
X	printf("(%03x: %02x) (%02x & 0x08 = %02x)\n", x, val, val, val & 0x08);
X	return (val);
X}
X/*
X#define inp(x) doinp(x)
X*/
X
Xmain()
X{
X	int cyl, head;
X	unsigned short c;
X
X	outp(COMMAND_REG, RESET_COMMAND);
X	wait_notbusy();
X
X	printf("Starting format...\n");
X
X	for (cyl = START; cyl < END; cyl++)
X	{
X		printf("\rcyl %4d head   ", cyl);
X		outp(CYL_LOW_REG, cyl & 0x00FF);
X		wait_notbusy();
X		outp(CYL_HI_REG, (cyl & 0xFF00) >> 8);
X		wait_notbusy();
X
X		for (head = 0; head < HEADS; head++)
X		{
X			printf("\b\b%2d", head);
X
X			outp(DRV_HD_REG, drive_head(DRIVE, head));
X			wait_notbusy();
X
X			outp(COUNT_REG, SECS_PER_TRACK);
X			wait_notbusy();
X
X			outp(COMMAND_REG, FORMAT_COMMAND);
X			wait_notbusy();
X			send_block(interleave_table);
X
X			wait_notbusy();
X			if ((c = (inp(STATUS_REG) & 0xFD)) != 0x51)
X				printf("... status = %02x\ncyl %4d head   ", c, cyl);
X		}
X	}
X	printf("\nDone.\n");
X}
X
Xwait_notbusy()
X{
X	wait_until(0x80, 0);
X}
X
Xwait_until(unsigned mask, unsigned state)
X{
X	unsigned long loop1, loop2;
X
X	for (loop1 = 0L; loop1 < 400L; loop1++)
X		for (loop2 = 0L; loop2 < 40000000L; loop2++)
X			if ((inp(STATUS_REG) & mask) == state)
X				return ;
X
X	fprintf(stderr, "Timeout! mask = %02x\n\n", mask);
X	exit(0);
X}
X				
Xsend_block(unsigned *block)
X{
X	int i;
X
X	wait_until(0x08, 0x08);
X	stream_to_port(256, DATA_REG, interleave_table);
X}
*-*-END-of-fmthd.c-*-*
echo x - strport.asm
sed 's/^X//' >strport.asm <<'*-*-END-of-strport.asm-*-*'
X	page	60, 132
X	Title	Stream to a port (186/286/386(/486?))
X	.model	small, c
Xassume cs:@code, ds:@data, ss:@data
X	.286C
X	.lall
X
X	.code
Xstream_to_port	proc uses si, count:word, port:word, block:ptr word
X
X	mov	cx, count
X	mov	dx, port
X	mov	si, block
X	cld
X
X    rep	outsw
X
X	ret
X
Xstream_to_port	endp
X
X	end
*-*-END-of-strport.asm-*-*
exit


Your mileage may vary, depending on moon phase, etc...

Note:  This was for an interleave of 1, because the 1006 is a buffered
controller...  I wouldn't even try this on a 1003 without re-arranging the
interleave_table.

  The reason the interleave_table is so huge is because the card works in
512 byte blocks ONLY.

Good luck!

Steve Watt
...!claris!zok!wattres!steve

or  swatt@cup.portal.com