mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
496 lines
10 KiB
496 lines
10 KiB
#include "insignia.h"
|
|
#include "host_def.h"
|
|
/*
|
|
* SoftPC Revision 3.0
|
|
*
|
|
*
|
|
* Title : Primary SFD BIOS floppy diskette functions
|
|
*
|
|
*
|
|
* Description : This module defines the floppy diskette BIOS functions
|
|
* that are invoked directly from BOP instructions:
|
|
*
|
|
* diskette_io() floppy diskette access functions
|
|
*
|
|
* diskette_post() floppy diskette POST function
|
|
*
|
|
* diskette_int() floppy diskette interrupt handler
|
|
*
|
|
*
|
|
* Author : Ross Beresford
|
|
*
|
|
*
|
|
* Notes :
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
* static char SccsID[]="@(#)floppy_io.c 1.14 03/02/94 Copyright Insignia Solutions Ltd.";
|
|
*/
|
|
|
|
|
|
#ifdef SEGMENTATION
|
|
/*
|
|
* The following #include specifies the code segment into which this
|
|
* module will by placed by the MPW C compiler on the Mac II running
|
|
* MultiFinder.
|
|
*/
|
|
#include "SOFTPC_FLOPPY.seg"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include TypesH
|
|
#include "xt.h"
|
|
#include "bios.h"
|
|
#include "ios.h"
|
|
#include CpuH
|
|
#include "error.h"
|
|
#include "config.h"
|
|
#include "gfi.h"
|
|
#include "fla.h"
|
|
#include "sas.h"
|
|
#include "floppy.h"
|
|
#include "equip.h"
|
|
#include "trace.h"
|
|
#include "ica.h"
|
|
#include "debug.h"
|
|
|
|
#include "tape_io.h"
|
|
|
|
#ifdef NTVDM
|
|
extern UTINY number_of_floppy;
|
|
|
|
#endif /* NTVDM */
|
|
|
|
#ifndef PROD
|
|
/*
|
|
* Internal functions (for tracing)
|
|
*/
|
|
|
|
static void rwvf_dump(op)
|
|
int op;
|
|
{
|
|
fprintf(trace_file, "(drive=%d,head=%d,track=%d,sec=%d,nsecs=%d",
|
|
getDL(), getDH(), getCH(), getCL(), getAL());
|
|
if (op != FL_DISK_VERF)
|
|
fprintf(trace_file, ",addr=%x:%x", getES(), getBX());
|
|
fprintf(trace_file, ")\n");
|
|
}
|
|
|
|
|
|
static void call_dump(op)
|
|
int op;
|
|
{
|
|
half_word diskette_status;
|
|
|
|
switch(op)
|
|
{
|
|
case FL_DISK_RESET:
|
|
fprintf(trace_file, "diskette_io:RESET()\n");
|
|
break;
|
|
case FL_DISK_STATUS:
|
|
fprintf(trace_file, "diskette_io:STATUS");
|
|
sas_load(FLOPPY_STATUS, &diskette_status);
|
|
fprintf(trace_file, "(status=0x%x)\n", diskette_status);
|
|
break;
|
|
case FL_DISK_READ:
|
|
fprintf(trace_file, "diskette_io:READ");
|
|
rwvf_dump(op);
|
|
break;
|
|
case FL_DISK_WRITE:
|
|
fprintf(trace_file, "diskette_io:WRITE");
|
|
rwvf_dump(op);
|
|
break;
|
|
case FL_DISK_VERF:
|
|
fprintf(trace_file, "diskette_io:VERIFY");
|
|
rwvf_dump(op);
|
|
break;
|
|
case FL_DISK_FORMAT:
|
|
fprintf(trace_file, "diskette_io:FORMAT");
|
|
rwvf_dump(op);
|
|
break;
|
|
case FL_DISK_PARMS:
|
|
fprintf(trace_file, "diskette_io:PARAMS(drive=%d)\n", getDL());
|
|
break;
|
|
case FL_DISK_TYPE:
|
|
fprintf(trace_file, "diskette_io:TYPE(drive=%d)\n", getDL());
|
|
break;
|
|
case FL_DISK_CHANGE:
|
|
fprintf(trace_file, "diskette_io:CHANGE(drive=%d)\n", getDL());
|
|
break;
|
|
case FL_FORMAT_SET:
|
|
fprintf(trace_file,
|
|
"diskette_io:SET_FORMAT(drive=%d,type=", getDL());
|
|
switch(getAL())
|
|
{
|
|
case MEDIA_TYPE_360_IN_360:
|
|
fprintf(trace_file, "360K media in 360K drive)\n");
|
|
break;
|
|
case MEDIA_TYPE_360_IN_12:
|
|
fprintf(trace_file, "360K media in 1.2M drive)\n");
|
|
break;
|
|
case MEDIA_TYPE_12_IN_12:
|
|
fprintf(trace_file, "1.2M media in 1.2M drive)\n");
|
|
break;
|
|
case MEDIA_TYPE_720_IN_720:
|
|
fprintf(trace_file, "720K media in 720K drive)\n");
|
|
break;
|
|
case MEDIA_TYPE_720_IN_144:
|
|
fprintf(trace_file, "720K media in 1.44M drive)\n");
|
|
break;
|
|
case MEDIA_TYPE_144_IN_144:
|
|
fprintf(trace_file, "1.44M media in 1.44M drive)\n");
|
|
break;
|
|
default:
|
|
fprintf(trace_file, "SILLY)\n");
|
|
break;
|
|
}
|
|
break;
|
|
case FL_SET_MEDIA:
|
|
fprintf(trace_file,
|
|
"diskette_io:SET_MEDIA(drive=%d,tracks=%d,sectors=%d)\n",
|
|
getDL(), getCH(), getCL());
|
|
break;
|
|
|
|
default:
|
|
fprintf(trace_file, "diskette_io:UNRECOGNISED(op=0x%x)\n", op);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void gen_dump()
|
|
{
|
|
int status = getAH();
|
|
|
|
fprintf(trace_file, "status=");
|
|
if (status & FS_CRC_ERROR)
|
|
fprintf(trace_file, "FS_CRC_ERROR|");
|
|
if (status & FS_FDC_ERROR)
|
|
fprintf(trace_file, "FS_FDC_ERROR|");
|
|
if (status & FS_SEEK_ERROR)
|
|
fprintf(trace_file, "FS_SEEK_ERROR|");
|
|
if (status & FS_TIME_OUT)
|
|
fprintf(trace_file, "FS_TIME_OUT|");
|
|
switch (status & 0xf)
|
|
{
|
|
case FS_OK:
|
|
fprintf(trace_file, "FS_OK");
|
|
break;
|
|
case FS_BAD_COMMAND:
|
|
fprintf(trace_file, "FS_BAD_COMMAND");
|
|
break;
|
|
case FS_BAD_ADDRESS_MARK:
|
|
fprintf(trace_file, "FS_BAD_ADDRESS_MARK");
|
|
break;
|
|
case FS_WRITE_PROTECTED:
|
|
fprintf(trace_file, "FS_WRITE_PROTECTED");
|
|
break;
|
|
case FS_SECTOR_NOT_FOUND:
|
|
fprintf(trace_file, "FS_SECTOR_NOT_FOUND");
|
|
break;
|
|
case FS_MEDIA_CHANGE:
|
|
fprintf(trace_file, "FS_MEDIA_CHANGE");
|
|
break;
|
|
case FS_DMA_ERROR:
|
|
fprintf(trace_file, "FS_DMA_ERROR");
|
|
break;
|
|
case FS_DMA_BOUNDARY:
|
|
fprintf(trace_file, "FS_DMA_BOUNDARY");
|
|
break;
|
|
case FS_MEDIA_NOT_FOUND:
|
|
fprintf(trace_file, "FS_MEDIA_NOT_FOUND");
|
|
break;
|
|
default:
|
|
fprintf(trace_file, "SILLY");
|
|
break;
|
|
}
|
|
fprintf(trace_file, ")\n");
|
|
}
|
|
|
|
|
|
static void return_dump(op)
|
|
int op;
|
|
{
|
|
fprintf(trace_file, "diskette_io:RETURN(");
|
|
switch(op)
|
|
{
|
|
case FL_DISK_TYPE:
|
|
switch(getAH())
|
|
{
|
|
case DRIVE_IQ_UNKNOWN:
|
|
fprintf(trace_file, "ABSENT");
|
|
break;
|
|
case DRIVE_IQ_NO_CHANGE_LINE:
|
|
fprintf(trace_file, "NO CHANGE LINE");
|
|
break;
|
|
case DRIVE_IQ_CHANGE_LINE:
|
|
fprintf(trace_file, "CHANGE LINE");
|
|
break;
|
|
case DRIVE_IQ_RESERVED:
|
|
fprintf(trace_file, "RESERVED");
|
|
break;
|
|
default:
|
|
fprintf(trace_file, "SILLY");
|
|
break;
|
|
}
|
|
fprintf(trace_file, ")\n");
|
|
break;
|
|
case FL_DISK_PARMS:
|
|
fprintf(trace_file, "addr=%x:%x,tracks=%d,sectors=%d,heads=%d,drives=%d,type=",
|
|
getES(), getDI(), getCH(), getCL(), getDH(), getDL());
|
|
switch(getBL())
|
|
{
|
|
case GFI_DRIVE_TYPE_NULL:
|
|
fprintf(trace_file, "NULL,");
|
|
break;
|
|
case GFI_DRIVE_TYPE_360:
|
|
fprintf(trace_file, "360K,");
|
|
break;
|
|
case GFI_DRIVE_TYPE_12:
|
|
fprintf(trace_file, "1.2M,");
|
|
break;
|
|
case GFI_DRIVE_TYPE_720:
|
|
fprintf(trace_file, "720K,");
|
|
break;
|
|
case GFI_DRIVE_TYPE_144:
|
|
fprintf(trace_file, "1.44M,");
|
|
break;
|
|
case GFI_DRIVE_TYPE_288:
|
|
fprintf(trace_file, "2.88M,");
|
|
break;
|
|
default:
|
|
fprintf(trace_file, "SILLY,");
|
|
break;
|
|
}
|
|
gen_dump();
|
|
break;
|
|
case FL_SET_MEDIA:
|
|
fprintf(trace_file, "addr=%x:%x,", getES(), getDI());
|
|
gen_dump();
|
|
break;
|
|
case FL_DISK_READ:
|
|
case FL_DISK_WRITE:
|
|
case FL_DISK_VERF:
|
|
case FL_DISK_FORMAT:
|
|
fprintf(trace_file, "nsecs=%d,", getAL());
|
|
gen_dump();
|
|
break;
|
|
case FL_DISK_CHANGE:
|
|
case FL_DISK_RESET:
|
|
case FL_DISK_STATUS:
|
|
case FL_FNC_ERR:
|
|
case FL_FORMAT_SET:
|
|
gen_dump();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
#endif /* nPROD */
|
|
|
|
|
|
void diskette_io()
|
|
{
|
|
/*
|
|
* Check for valid call and use secondary functions to
|
|
* perform the required operation
|
|
*
|
|
* Register inputs:
|
|
* AH operation required
|
|
* DL drive number
|
|
*/
|
|
half_word diskette_status;
|
|
int op = getAH(), drive = getDL();
|
|
|
|
#ifndef PROD
|
|
if (io_verbose & FLOPBIOS_VERBOSE)
|
|
call_dump(op);
|
|
#endif
|
|
|
|
#ifndef JOKER
|
|
/*
|
|
* Enable interrupts
|
|
*/
|
|
|
|
setIF(1);
|
|
#endif /* JOKER */
|
|
|
|
/*
|
|
* Check operation required, using known invalid function
|
|
* if operation is out of range
|
|
*/
|
|
|
|
if (!fl_operation_in_range(op))
|
|
op = FL_FNC_ERR;
|
|
|
|
/*
|
|
* If the drive number is applicable in the operation, check it
|
|
*/
|
|
|
|
if (op != FL_DISK_RESET && op != FL_DISK_STATUS && op != FL_DISK_PARMS)
|
|
#ifdef NTVDM
|
|
if (drive >= number_of_floppy)
|
|
#else
|
|
if (drive >= MAX_FLOPPY)
|
|
#endif /* NTVDM */
|
|
op = FL_FNC_ERR;
|
|
|
|
|
|
/*
|
|
* Save previous diskette status, initialise current diskette
|
|
* status to OK
|
|
*/
|
|
|
|
sas_load(FLOPPY_STATUS, &diskette_status);
|
|
setAH(diskette_status);
|
|
sas_store(FLOPPY_STATUS, FS_OK);
|
|
|
|
/*
|
|
* Do the operation
|
|
*/
|
|
|
|
(*fl_fnc_tab[op])(drive);
|
|
|
|
|
|
|
|
#ifndef PROD
|
|
if (io_verbose & FLOPBIOS_VERBOSE)
|
|
return_dump(op);
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifndef JOKER /* Floppies handled v. weirdly on JOKER */
|
|
|
|
void diskette_int()
|
|
{
|
|
/*
|
|
* The diskette interrupt service routine. Mark the Seek Status to say
|
|
* the interrupt has occurred and terminate the interrupt.
|
|
*/
|
|
half_word seek_status;
|
|
word savedAX, savedCS, savedIP;
|
|
|
|
note_trace0(FLOPBIOS_VERBOSE, "diskette_int()");
|
|
sas_load(SEEK_STATUS, &seek_status);
|
|
sas_store(SEEK_STATUS, seek_status | SS_INT_OCCURRED);
|
|
|
|
outb(ICA0_PORT_0, END_INTERRUPT);
|
|
|
|
/*
|
|
* Enable interrupts
|
|
*/
|
|
|
|
setIF(1);
|
|
|
|
/*
|
|
* Notify OS that BIOS has completed a "wait" for
|
|
* a diskette interrupt
|
|
*/
|
|
savedAX = getAX();
|
|
savedCS = getCS();
|
|
savedIP = getIP();
|
|
|
|
setAH(INT15_INTERRUPT_COMPLETE);
|
|
setAL(INT15_DEVICE_FLOPPY);
|
|
#ifdef NTVDM
|
|
setCS(int15_seg);
|
|
setIP(int15_off);
|
|
#else
|
|
setCS(RCPU_INT15_SEGMENT);
|
|
setIP(RCPU_INT15_OFFSET);
|
|
#endif /* NTVDM */
|
|
|
|
host_simulate();
|
|
|
|
setAX(savedAX);
|
|
setCS(savedCS);
|
|
setIP(savedIP);
|
|
}
|
|
|
|
#endif /* ndef JOKER */
|
|
|
|
|
|
#ifdef SEGMENTATION
|
|
/*
|
|
* The following #include specifies the code segment into which this
|
|
* module will by placed by the MPW C compiler on the Mac II running
|
|
* MultiFinder.
|
|
*/
|
|
#include "SOFTPC_INIT.seg"
|
|
#endif
|
|
|
|
void diskette_post()
|
|
{
|
|
/*
|
|
* This routine performs the diskette BIOS initialisation
|
|
* functionality in the POST.
|
|
*/
|
|
half_word diskette_id_reg, hf_cntrl, interrupt_mask;
|
|
#ifndef NTVDM
|
|
half_word disk_state;
|
|
#endif
|
|
EQUIPMENT_WORD equip_flag;
|
|
|
|
note_trace0(FLOPBIOS_VERBOSE, "diskette_post()");
|
|
|
|
/*
|
|
* Set the diskette data rate to 250 kbs (low density)
|
|
*/
|
|
|
|
outb(DISKETTE_DCR_REG, DCR_RATE_250);
|
|
|
|
/*
|
|
* If there are any diskettes installed, check whether
|
|
* they are accessed via a DUAL card or the old-style
|
|
* adapter card
|
|
*/
|
|
|
|
sas_loadw(EQUIP_FLAG, &equip_flag.all);
|
|
if (equip_flag.bits.diskette_present)
|
|
{
|
|
/*
|
|
* Enable diskette interrupts
|
|
*/
|
|
|
|
inb(ICA0_PORT_1, &interrupt_mask);
|
|
interrupt_mask &= ~(1 << CPU_DISKETTE_INT);
|
|
outb(ICA0_PORT_1, interrupt_mask);
|
|
|
|
/*
|
|
* If a DUAL diskette/fixed disk adapter is fitted,
|
|
* set the drive indicator for drive 0 accordingly
|
|
*/
|
|
|
|
inb(DISKETTE_ID_REG, &diskette_id_reg);
|
|
sas_load(DRIVE_CAPABILITY, &hf_cntrl);
|
|
hf_cntrl &= ~DC_DUAL;
|
|
if ((diskette_id_reg & IDR_ID_MASK) == DUAL_CARD_ID)
|
|
hf_cntrl |= DC_DUAL;
|
|
sas_store(DRIVE_CAPABILITY, hf_cntrl);
|
|
|
|
#ifndef NTVDM /* prevent floppies showing up in bios data area */
|
|
/*
|
|
* Setup the diskette BIOS state according to the
|
|
* types of drives installed
|
|
*/
|
|
fl_diskette_setup();
|
|
|
|
/*
|
|
* If a second drive was discovered, update the
|
|
* equipment flag accordingly
|
|
*/
|
|
|
|
sas_load(FDD_STATUS+1, &disk_state);
|
|
if (disk_state != 0)
|
|
{
|
|
sas_loadw(EQUIP_FLAG, &equip_flag.all);
|
|
equip_flag.bits.max_diskette = 1;
|
|
sas_storew(EQUIP_FLAG, equip_flag.all);
|
|
}
|
|
#endif /* NTVDM */
|
|
}
|
|
}
|