peter_van_epp@cc.sfu.ca@canremote.uucp (Peter_Van_Epp@cc.sfu.ca) (12/21/89)
Subj: Suggestion for PC wini test program under DOS (long) Given the amount of troubles I and other people are having with xt_/at_wini.c it seems to me that we should write a test program that runs under DOS (sorry Andy!) that does the following: Asks DOS what the drive under consideration looks like (int 13) by reading the controller bios rom. Now the wini.c code would be executed (again under DOS although we may have to reset the controller before trying to talk to it again from DOS) except arrange to dump out the values that the MINIX code gets. Assuming that matches then try reading either some or all of the sectors of the DOS partition (note being sure to only read!) with both the DOS and the minix code and insure that they are the same. Assuming that doesn't work it would be nice (and shouldn't be too hard!) to allow a command line switch to enable the various compile time switches so that the various options (xt/at WD or ADAPTEC controllers etc) can be tried without recompiling the DOS program. This should allow us to create an option file that could be used to control the recompilation of the wini driver (and give us better confidence that the driver is actually working correctly!) before having Minix up. I will put this project on the end of my (long!) list of things to do, unless someone else is interested in making one (hint! hint!). Peter_Van_Epp@cc.sfu.ca --- * Via MaSNet/HST96/HST144/V32 - UN Minix * Via Usenet Newsgroup comp.os.minix
hall@cod.NOSC.MIL (Robert R. Hall) (01/03/90)
In article <89122504055886@masnet.uucp>, peter_van_epp@cc.sfu.ca@canremote.uucp (Peter_Van_Epp@cc.sfu.ca) writes: > Subj: Suggestion for PC wini test program under DOS (long) > > Given the amount of troubles I and other people are having with > xt_/at_wini.c it seems to me that we should write a test program that > runs under DOS (sorry Andy!) that does the following: > Asks DOS what the drive under consideration looks like (int 13) by > reading the controller bios rom. Now the wini.c code would be . . . > project on the end of my (long!) list of things to do, unless someone > else is interested in making one (hint! hint!). > Peter_Van_Epp@cc.sfu.ca Here is a couple of MS-DOS programs I used to get Minix working with my hard drive. It doesn't have most of the feature Peter_Van_Epp suggested but is may be a starting place for someone. Robert R. Hall hall@nosc.mil echo x - rd_parms.c sed '/^X/s///' > rd_parms.c << '/' X/* rd_params.c X read hard dirve parameters */ X Xstruct param { X int nr_cyl; /* Number of cylinders */ X int nr_heads; /* Number of heads */ X int nr_sectors; /* Number of sectors per track */ X int nr_drives; /* Number of drives */ X int dr_type; /* drive type */ X} param0, param1; X Xint Ax, Bx, Cx, Dx; X X#include <dos.h> X#define BIOS_ASK 0x08 X#define DRIVE 0x80 X Xbios13() X{ X union REGS in_regs, out_regs; X X in_regs.x.ax = Ax; X in_regs.x.bx = Bx; X in_regs.x.cx = Cx; X in_regs.x.dx = Dx; X int86(0x13, &in_regs, &out_regs); X Ax = out_regs.x.ax; X Bx = out_regs.x.bx; X Cx = out_regs.x.cx; X Dx = out_regs.x.dx; X return; X} X Xget_params(dr, params) Xint dr; Xstruct param *params; X{ X Dx = dr + DRIVE; X Ax = (BIOS_ASK << 8); X bios13(); X params->nr_heads = ((Dx >> 8) & 0xff) + 1; X params->nr_sectors = (Cx & 0x3F); X params->nr_cyl = ((Cx & 0xC0) << 2) + ((Cx >> 8) & 0xFF); X params->nr_drives = (Dx & 0xFF); X params->dr_type = (Bx & 0x07); X} X Xmain() X{ X get_params(1, ¶m0); X printf("nr_heads is: %d\n", param0.nr_heads); X printf("nr_sectors is: %d\n", param0.nr_sectors); X printf("nr_cyl is: %d\n", param0.nr_cyl); X printf("nr_drives is: %d\n", param0.nr_drives); X printf("dr_type is: %d\n", param0.dr_type); X X printf("Ax is: %.4x Bx is: %.4x Cx is: %.4x Dx is: %.4x\n", X Ax, Bx, Cx, Dx); X} / echo x - rd_part.c sed '/^X/s///' > rd_part.c << '/' X/* This file contains a hard disk driver that uses the ROM BIOS. It makes X * a call and just waits for the transfer to happen. It is not interrupt X * driven and thus will have poor performance. The advantage is that it should X * work on virtually any PC, XT, 386, PS/2 or clone. The generic boot X * diskette uses this driver. It is suggested that all MINIX users try the X * other drivers, and use this one only as a last resort, if all else fails. X * X * The driver supports two operations: read a block and X * write a block. It accepts two messages, one for reading and one for X * writing, both using message format m2 and with the same parameters: X * X * m_type DEVICE PROC_NR COUNT POSITION ADRRESS X * ---------------------------------------------------------------- X * | DISK_READ | device | proc nr | bytes | offset | buf ptr | X * |------------+---------+---------+---------+---------+---------| X * | DISK_WRITE | device | proc nr | bytes | offset | buf ptr | X * ---------------------------------------------------------------- X * X * The file contains one entry point: X * X * winchester_task: main entry when system is brought up X * X */ X X#include <dos.h> X X#include "minix/const.h" X#include "minix/type.h" X#include "minix/callnr.h" X#include "minix/com.h" X#include "minix/error.h" X#include "const.h" X#include "type.h" X#include "glo.h" X#include "proc.h" X X/* Error codes */ X#define ERR -1 /* general error */ X X/* Parameters for the disk drive. */ X#define MAX_DRIVES 2 /* this driver supports 2 drives (hd0 - hd9)*/ X#define DEV_PER_DRIVE 5 /* hd0 + hd1 + hd2 + hd3 + hd4 = 5 */ X#define NR_DEVICES (MAX_DRIVES * DEV_PER_DRIVE) X#define SECTOR_SIZE 512 /* physical sector size in bytes */ X#define BASE 1536 /* base address of kernel */ X X/* BIOS parameters */ X#define BIOS_ASK 0x08 /* opcode for asking BIOS for parameters */ X#define BIOS_RESET 0x00 /* opcode for resetting disk BIOS */ X#define BIOS_READ 0x02 /* opcode for BIOS read */ X#define BIOS_WRITE 0x03 /* opcode for BIOS write */ X#define DRIVE 0x80 /* BIOS code for drive 0 */ X#define PART_TABLE 0x1C6 /* IBM partition table starts here in sect 0 */ X XPRIVATE unsigned char buf[BLOCK_SIZE]; /* Buffer used by the startup routine */ XPRIVATE message w_mess; /* message buffer for in and out */ X XPRIVATE struct wini { /* main drive struct, one entry per drive */ X int wn_opcode; /* DISK_READ or DISK_WRITE */ X int wn_procnr; /* which proc wanted this operation? */ X int wn_cylinder; /* cylinder number addressed */ X int wn_sector; /* sector addressed */ X int wn_head; /* head number addressed */ X int wn_heads; /* maximum number of heads */ X int wn_maxsec; /* maximum number of sectors per track */ X long wn_low; /* lowest cylinder of partition */ X long wn_size; /* size of partition in sectors */ X int wn_count; /* byte count */ X int wn_drive; /* 0x80 or 0x81 */ X vir_bytes wn_address; /* user virtual address */ X} wini[NR_DEVICES]; X XPRIVATE struct param { X int nr_cyl; /* Number of cylinders */ X int nr_heads; /* Number of heads */ X int nr_drives; /* Number of drives on this controler */ X int nr_sectors; /* Number of sectors per track */ X} param0, param1; X Xint nr_drives; X Xint Ax, Bx, Cx, Dx, Es; X X Xbios13() X{ X union REGS in_regs, out_regs; X struct SREGS seg_regs; X X in_regs.x.ax = Ax; X in_regs.x.bx = Bx; X in_regs.x.cx = Cx; X in_regs.x.dx = Dx; X seg_regs.es = Es; X int86x(0x13, &in_regs, &out_regs, &seg_regs); X Ax = out_regs.x.ax; X Bx = out_regs.x.bx; X Cx = out_regs.x.cx; X Dx = out_regs.x.dx; X return; X} X X/*==========================================================================* X * w_do_rdwt * X *==========================================================================*/ XPRIVATE int w_do_rdwt(m_ptr) Xmessage *m_ptr; /* pointer to read or write w_message */ X{ X/* Carry out a read or write request from the disk. */ X register struct wini *wn; X vir_bytes vir, ct; X unsigned locyl, hicyl, c1, c2, c3; X int r, device, errors = 0; X long sector; X phys_bytes user_phys; X extern phys_bytes umap(); X char far *pointer; X unsigned int segment; X X /* Decode the w_message parameters. */ X printf("Entered W_do_rdwt\n"); X device = m_ptr->DEVICE; /* minor device #. 1-4 are partitions */ X if (device < 0 || device >= NR_DEVICES) return(EIO); X if (m_ptr->COUNT != BLOCK_SIZE) return(EINVAL); X printf("Passed BLOCK_SIZE test\n"); X wn = &wini[device]; /* 'wn' points to entry for this drive */ X X /* Set opcode to BIOS_READ or BIOS_WRITE. Check for bad starting addr. */ X wn->wn_opcode = (m_ptr->m_type == DISK_WRITE ? BIOS_WRITE : BIOS_READ); X if (m_ptr->POSITION % BLOCK_SIZE != 0) return(EINVAL); X X /* Calculate the physical parameters */ X sector = m_ptr->POSITION/SECTOR_SIZE; /* relative sector within partition */ X printf("sector is %ld wn_size is: %ld\n", sector, wn->wn_size); X if ((sector+BLOCK_SIZE/SECTOR_SIZE) > wn->wn_size) return(EOF); X printf("Passed sector test\n"); X sector += wn->wn_low; /* absolute sector number */ X wn->wn_cylinder = sector / (wn->wn_heads * wn->wn_maxsec); X wn->wn_sector = (sector % wn->wn_maxsec); X wn->wn_head = (sector % (wn->wn_heads * wn->wn_maxsec) )/wn->wn_maxsec; X wn->wn_count = m_ptr->COUNT; X wn->wn_address = (vir_bytes) m_ptr->ADDRESS; X wn->wn_procnr = m_ptr->PROC_NR; X X /* Do the transfer */ X vir = (vir_bytes) wn->wn_address; X ct = (vir_bytes) wn->wn_count; X pointer = buf; X segment = FP_SEG(pointer); X user_phys = ((unsigned long)segment << 4) + vir; X printf("pointer is 0x%.8lx\n", pointer); X printf("segment is 0x%.4x\n", segment); X printf("offset is 0x%.4x\n", vir); X Ax = (wn->wn_opcode << 8) | 2; /* read or write 2 sectors */ X Bx = (unsigned) (user_phys & 0xF); /* bx = low order 4 bits */ X Es = (unsigned) ((user_phys >> 4) & 0xFFFF); X hicyl = (wn->wn_cylinder >> 8) & 03; /* two high-order bits */ X locyl = (wn->wn_cylinder & 0xFF); /* 8 low-order bits */ X c1 = (locyl<<8); X c2 = (hicyl<<6); X c3 = ((unsigned) wn->wn_sector) + 1; X Cx = c1 | c2 | c3; X Dx = (wn->wn_head<<8) | wn->wn_drive; X printf("Starting call to BIOS\n"); X printf("Ax is: 0x%.4x\n", Ax); X printf("Bx is: 0x%.4x\n", Bx); X printf("Cx is: 0x%.4x\n", Cx); X printf("Dx is: 0x%.4x\n", Dx); X printf("Es is: 0x%.4x\n", Es); X bios13(); X r = (Ax >> 8) & 0xFF; X printf("bios13 status is: 0x%.2x\n", r); X return(r == 0 ? BLOCK_SIZE : EIO); X} X X X/*============================================================================* X * get_params * X *============================================================================*/ Xget_params(dr, params) Xint dr; Xstruct param *params; X{ X Dx = dr + DRIVE; X Ax = (BIOS_ASK << 8); X bios13(); X params->nr_heads = ((Dx >> 8) & 0xFF) + 1; X params->nr_sectors = (Cx & 0x3F); X params->nr_cyl = ((Cx & 0xC0) << 2) + ((Cx >> 8) & 0xFF); X params->nr_drives = (Dx & 0xFF); X} X X/*============================================================================* X * init_params * X *============================================================================*/ Xmain() X{ X unsigned int i, j; X X get_params(0, ¶m0); X get_params(1, ¶m0); X X /* Get the number of drives */ X nr_drives = param0.nr_drives; X X /* Set the parameters in the drive structure */ X for (i = 0; i < DEV_PER_DRIVE; i++) X { X wini[i].wn_heads = param0.nr_heads; X wini[i].wn_maxsec = param0.nr_sectors; X wini[i].wn_drive = DRIVE; X } X wini[0].wn_low = wini[DEV_PER_DRIVE].wn_low = 0L; X wini[0].wn_size = (long)((long)param0.nr_cyl X * (long)param0.nr_heads * (long)param0.nr_sectors); X for (i = DEV_PER_DRIVE; i < (2*DEV_PER_DRIVE); i++) X { X wini[i].wn_heads = param1.nr_heads; X wini[i].wn_maxsec = param1.nr_sectors; X wini[i].wn_drive = DRIVE + 1; X } X wini[DEV_PER_DRIVE].wn_size = (long)((long)param1.nr_cyl X * (long)param1.nr_heads * (long)param1.nr_sectors); X X printf("Starting read of partition table\n"); X /* Read the partition table for each drive and save them */ X for (i = 0; i < 1; i++) { X w_mess.DEVICE = i * 5; X w_mess.POSITION = 0L; X w_mess.COUNT = BLOCK_SIZE; X w_mess.ADDRESS = (char *) buf; X w_mess.PROC_NR = WINCHESTER; X w_mess.m_type = DISK_READ; X if (w_do_rdwt(&w_mess) != BLOCK_SIZE) X printf("Can't read partition table of winchester %d\n", i); X printf("Read partition table %d completed\n", i); X X X for(i = 0; i < 5 * 8; i += 8) X { X for(j = 0; j < 8; j++) X printf(" %.2x", buf[i + j] & 0xFF); X printf("\n"); X } X i = XT_WINI_VECTOR; X printf("XT_WINI_VECTOR is: %d 0x%.2x\n", i, i); X i = PRINTER_VECTOR; X printf("PRINTER_VECTOR is: %d 0x%.2x\n", i, i); X } X} X /