Updated AltairZ80 documentation and incorporated altairz80_mhdsk.c in build process
This commit is contained in:
parent
1d35a4f612
commit
49d38187dd
6 changed files with 211 additions and 206 deletions
Binary file not shown.
|
@ -595,6 +595,7 @@ static int32 bootrom_hdsk[BOOTROM_SIZE_HDSK] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
|
static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
|
||||||
|
t_bool installSuccessful;
|
||||||
if (MEMORYSIZE < 24*KB) {
|
if (MEMORYSIZE < 24*KB) {
|
||||||
printf("Need at least 24KB RAM to boot from hard disk.\n");
|
printf("Need at least 24KB RAM to boot from hard disk.\n");
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
|
@ -609,9 +610,9 @@ static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
|
||||||
}
|
}
|
||||||
install_ALTAIRbootROM(); /* install modified ROM */
|
install_ALTAIRbootROM(); /* install modified ROM */
|
||||||
}
|
}
|
||||||
const t_bool result = (install_bootrom(bootrom_hdsk, BOOTROM_SIZE_HDSK, HDSK_BOOT_ADDRESS,
|
installSuccessful = (install_bootrom(bootrom_hdsk, BOOTROM_SIZE_HDSK, HDSK_BOOT_ADDRESS,
|
||||||
FALSE) == SCPE_OK);
|
FALSE) == SCPE_OK);
|
||||||
assert(result);
|
assert(installSuccessful);
|
||||||
*((int32 *) sim_PC -> loc) = HDSK_BOOT_ADDRESS;
|
*((int32 *) sim_PC -> loc) = HDSK_BOOT_ADDRESS;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,92 +25,92 @@
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
The 88-HDSK from MITS/Pertec consists of a 5mb removable platter and
|
The 88-HDSK from MITS/Pertec consists of a 5mb removable platter and
|
||||||
a fixed 5mb platter. Each platter is double sided. Head 0 and 1 are the
|
a fixed 5mb platter. Each platter is double sided. Head 0 and 1 are the
|
||||||
top and bottom surface of the removable platter and head 2 and 3 are the
|
top and bottom surface of the removable platter and head 2 and 3 are the
|
||||||
top and bottom surface of the fixed platter. Hard disk BASIC treats the
|
top and bottom surface of the fixed platter. Hard disk BASIC treats the
|
||||||
two platters as two separate drives. Each platter has 406 cylinders
|
two platters as two separate drives. Each platter has 406 cylinders
|
||||||
with 24 sectors per track and 256 bytes per sector.
|
with 24 sectors per track and 256 bytes per sector.
|
||||||
|
|
||||||
The disk image file starts with head 0, track 0, sector 0 (0,0,0) through
|
The disk image file starts with head 0, track 0, sector 0 (0,0,0) through
|
||||||
(0,0,23), followed by head 1, track 0, sector 0 (1,0,0) through (1,0,23).
|
(0,0,23), followed by head 1, track 0, sector 0 (1,0,0) through (1,0,23).
|
||||||
The pattern then repeats starting with (0,1,0).
|
The pattern then repeats starting with (0,1,0).
|
||||||
|
|
||||||
The external hard disk is accessed through eight ports of a 4-PIO card
|
The external hard disk is accessed through eight ports of a 4-PIO card
|
||||||
at I/O addresses A0h-A7h.
|
at I/O addresses A0h-A7h.
|
||||||
|
|
||||||
Written by Mike Douglas March, 2014
|
Written by Mike Douglas March, 2014
|
||||||
Disk images provided by Martin Eberhard
|
Disk images provided by Martin Eberhard
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#include "altairz80_defs.h"
|
#include "altairz80_defs.h"
|
||||||
|
|
||||||
/** Typedefs & Defines **************************************/
|
/** Typedefs & Defines **************************************/
|
||||||
#define HDSK_SECTOR_SIZE 256 /* size of sector */
|
#define HDSK_SECTOR_SIZE 256 /* size of sector */
|
||||||
#define HDSK_SECTORS_PER_TRACK 24 /* sectors per track */
|
#define HDSK_SECTORS_PER_TRACK 24 /* sectors per track */
|
||||||
#define HDSK_NUM_HEADS 2 /* heads per disk */
|
#define HDSK_NUM_HEADS 2 /* heads per disk */
|
||||||
#define HDSK_NUM_TRACKS 406 /* tracks per surface */
|
#define HDSK_NUM_TRACKS 406 /* tracks per surface */
|
||||||
#define HDSK_TRACK_SIZE (HDSK_SECTOR_SIZE * HDSK_SECTORS_PER_TRACK)
|
#define HDSK_TRACK_SIZE (HDSK_SECTOR_SIZE * HDSK_SECTORS_PER_TRACK)
|
||||||
#define HDSK_CYLINDER_SIZE (HDSK_TRACK_SIZE * 2)
|
#define HDSK_CYLINDER_SIZE (HDSK_TRACK_SIZE * 2)
|
||||||
#define HDSK_CAPACITY (HDSK_CYLINDER_SIZE * HDSK_NUM_TRACKS)
|
#define HDSK_CAPACITY (HDSK_CYLINDER_SIZE * HDSK_NUM_TRACKS)
|
||||||
#define HDSK_NUMBER 8 /* number of hard disks */
|
#define HDSK_NUMBER 8 /* number of hard disks */
|
||||||
#define IO_IN 0 /* I/O operation is input */
|
#define IO_IN 0 /* I/O operation is input */
|
||||||
#define IO_OUT 1 /* I/O operation is output */
|
#define IO_OUT 1 /* I/O operation is output */
|
||||||
#define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */
|
#define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */
|
||||||
#define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK)
|
#define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK)
|
||||||
|
|
||||||
// Disk controller commands are in upper nibble of command high byte.
|
// Disk controller commands are in upper nibble of command high byte.
|
||||||
|
|
||||||
#define CMD_SHIFT 4 // shift right 4 places
|
#define CMD_SHIFT 4 // shift right 4 places
|
||||||
#define CMD_MASK 0x0f // mask after shifting
|
#define CMD_MASK 0x0f // mask after shifting
|
||||||
#define CMD_SEEK 0 // seek to track
|
#define CMD_SEEK 0 // seek to track
|
||||||
#define CMD_WRITE_SEC 2 // write sector from buf n
|
#define CMD_WRITE_SEC 2 // write sector from buf n
|
||||||
#define CMD_READ_SEC 3 // read sector into buf n
|
#define CMD_READ_SEC 3 // read sector into buf n
|
||||||
#define CMD_WRITE_BUF 4 // load buffer n from CPU
|
#define CMD_WRITE_BUF 4 // load buffer n from CPU
|
||||||
#define CMD_READ_BUF 5 // read buffer n into CPU
|
#define CMD_READ_BUF 5 // read buffer n into CPU
|
||||||
#define CMD_READ_STATUS 6 // read controller IV byte
|
#define CMD_READ_STATUS 6 // read controller IV byte
|
||||||
#define CMD_SET_IV_BYTE 8 // set controller IV byte
|
#define CMD_SET_IV_BYTE 8 // set controller IV byte
|
||||||
#define CMD_READ_UNFMT 10 // read unformatted sector
|
#define CMD_READ_UNFMT 10 // read unformatted sector
|
||||||
#define CMD_FORMAT 12
|
#define CMD_FORMAT 12
|
||||||
#define CMD_INITIALIZE 14
|
#define CMD_INITIALIZE 14
|
||||||
|
|
||||||
// Other disk controller bit fields
|
// Other disk controller bit fields
|
||||||
|
|
||||||
#define UNIT_SHIFT 2 // shift right 2 places
|
#define UNIT_SHIFT 2 // shift right 2 places
|
||||||
#define UNIT_MASK 0x03 // mask after shifting
|
#define UNIT_MASK 0x03 // mask after shifting
|
||||||
|
|
||||||
#define BUFFER_MASK 0x03 // mask - no shift needed
|
#define BUFFER_MASK 0x03 // mask - no shift needed
|
||||||
|
|
||||||
#define TRACK_SHIFTH 8 // shift left 8 places into MSbyte
|
#define TRACK_SHIFTH 8 // shift left 8 places into MSbyte
|
||||||
#define TRACK_MASKH 0x01 // msb of track number
|
#define TRACK_MASKH 0x01 // msb of track number
|
||||||
#define TRACK_MASKL 0xff // entire lsb of track number
|
#define TRACK_MASKL 0xff // entire lsb of track number
|
||||||
|
|
||||||
#define HEAD_SHIFT 5 // shift right 5 places
|
#define HEAD_SHIFT 5 // shift right 5 places
|
||||||
#define HEAD_MASK 0x03 // mask after shifting (no heads 4-7)
|
#define HEAD_MASK 0x03 // mask after shifting (no heads 4-7)
|
||||||
|
|
||||||
#define SECTOR_MASK 0x1f // mask - no shift needed
|
#define SECTOR_MASK 0x1f // mask - no shift needed
|
||||||
|
|
||||||
// Command status equates
|
// Command status equates
|
||||||
|
|
||||||
#define CSTAT_WRITE_PROTECT 0x80 // disk is write protected
|
#define CSTAT_WRITE_PROTECT 0x80 // disk is write protected
|
||||||
#define CSTAT_NOT_READY 0x01 // drive not ready
|
#define CSTAT_NOT_READY 0x01 // drive not ready
|
||||||
#define CSTAT_BAD_SECTOR 0x02 // invalid sector number
|
#define CSTAT_BAD_SECTOR 0x02 // invalid sector number
|
||||||
|
|
||||||
|
|
||||||
/** Module Globals - Private ********************************/
|
/** Module Globals - Private ********************************/
|
||||||
static uint32 selectedDisk = 0; // current active disk
|
static uint32 selectedDisk = 0; // current active disk
|
||||||
static uint32 selectedSector = 0; // current sector
|
static uint32 selectedSector = 0; // current sector
|
||||||
static uint32 selectedTrack = 0; // current track
|
static uint32 selectedTrack = 0; // current track
|
||||||
static uint32 selectedHead = 0; // current head
|
static uint32 selectedHead = 0; // current head
|
||||||
static uint32 selectedBuffer = 0; // current buffer # in use
|
static uint32 selectedBuffer = 0; // current buffer # in use
|
||||||
static uint32 bufferIdx = 0; // current index into selected buffer
|
static uint32 bufferIdx = 0; // current index into selected buffer
|
||||||
static uint32 maxBufferIdx = 256; // maximum buffer index allowed
|
static uint32 maxBufferIdx = 256; // maximum buffer index allowed
|
||||||
static uint32 cmdLowByte = 0; // low byte of command
|
static uint32 cmdLowByte = 0; // low byte of command
|
||||||
|
|
||||||
// Controller status bytes
|
// Controller status bytes
|
||||||
|
|
||||||
static uint8 cstat = 0; // command status from controller
|
static uint8 cstat = 0; // command status from controller
|
||||||
|
|
||||||
// The hard disk controller support four 256 byte disk buffers */
|
// The hard disk controller support four 256 byte disk buffers */
|
||||||
|
|
||||||
|
@ -168,166 +168,166 @@ DEVICE mhdsk_dev = {
|
||||||
----------------------------------------------------------------------------------*/
|
----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static t_stat dsk_reset(DEVICE *dptr) {
|
static t_stat dsk_reset(DEVICE *dptr) {
|
||||||
sim_map_resource(0xA0, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
|
sim_map_resource(0xA0, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
|
||||||
sim_map_resource(0xA1, 1, RESOURCE_TYPE_IO, &hdCstat, dptr->flags & DEV_DIS);
|
sim_map_resource(0xA1, 1, RESOURCE_TYPE_IO, &hdCstat, dptr->flags & DEV_DIS);
|
||||||
sim_map_resource(0xA2, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
|
sim_map_resource(0xA2, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
|
||||||
sim_map_resource(0xA3, 1, RESOURCE_TYPE_IO, &hdAcmd, dptr->flags & DEV_DIS);
|
sim_map_resource(0xA3, 1, RESOURCE_TYPE_IO, &hdAcmd, dptr->flags & DEV_DIS);
|
||||||
sim_map_resource(0xA4, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
|
sim_map_resource(0xA4, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
|
||||||
sim_map_resource(0xA5, 1, RESOURCE_TYPE_IO, &hdCdata, dptr->flags & DEV_DIS);
|
sim_map_resource(0xA5, 1, RESOURCE_TYPE_IO, &hdCdata, dptr->flags & DEV_DIS);
|
||||||
sim_map_resource(0xA6, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
|
sim_map_resource(0xA6, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
|
||||||
sim_map_resource(0xA7, 1, RESOURCE_TYPE_IO, &hdAdata, dptr->flags & DEV_DIS);
|
sim_map_resource(0xA7, 1, RESOURCE_TYPE_IO, &hdAdata, dptr->flags & DEV_DIS);
|
||||||
|
|
||||||
selectedSector = 0; // current sector
|
selectedSector = 0; // current sector
|
||||||
selectedTrack = 0; // current track
|
selectedTrack = 0; // current track
|
||||||
selectedHead = 0; // current head
|
selectedHead = 0; // current head
|
||||||
selectedBuffer = 0; // current buffer # in use
|
selectedBuffer = 0; // current buffer # in use
|
||||||
bufferIdx = 0; // current index into selected buffer
|
bufferIdx = 0; // current index into selected buffer
|
||||||
maxBufferIdx = 256; // maximum buffer index allowed
|
maxBufferIdx = 256; // maximum buffer index allowed
|
||||||
cmdLowByte = 0; // low byte of command
|
cmdLowByte = 0; // low byte of command
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------------------
|
||||||
hdReturnReady - common I/O handler for several hard disk status ports which set
|
hdReturnReady - common I/O handler for several hard disk status ports which set
|
||||||
bit 7 when the corresponding hard disk function is ready. In the emulator,
|
bit 7 when the corresponding hard disk function is ready. In the emulator,
|
||||||
we're always ready for the next step, so we simply return ready all the time.
|
we're always ready for the next step, so we simply return ready all the time.
|
||||||
|
|
||||||
0xA0 - CREADY register. Accessed through the status/control register of 4-PIO
|
0xA0 - CREADY register. Accessed through the status/control register of 4-PIO
|
||||||
port 1-A. Returns the "ready for command" status byte.
|
port 1-A. Returns the "ready for command" status byte.
|
||||||
|
|
||||||
0xA2 - ACSTA register. Accessed through the status/control register of 4-PIO
|
0xA2 - ACSTA register. Accessed through the status/control register of 4-PIO
|
||||||
port 1-B. Returns the "command received" status byte.
|
port 1-B. Returns the "command received" status byte.
|
||||||
|
|
||||||
0xA4 - CDSTA register. Accessed through the status/control register of 4-PIO
|
0xA4 - CDSTA register. Accessed through the status/control register of 4-PIO
|
||||||
port 2-A. Returns the "command data available" status byte.
|
port 2-A. Returns the "command data available" status byte.
|
||||||
|
|
||||||
0xA6 - ADSTA register. Accessed through the status/control register of 4-PIO
|
0xA6 - ADSTA register. Accessed through the status/control register of 4-PIO
|
||||||
port 2-B. Returns the "available to write" status byte.
|
port 2-B. Returns the "available to write" status byte.
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------*/
|
---------------------------------------------------------------------------------------*/
|
||||||
static int32 hdReturnReady(const int32 port, const int32 io, const int32 data)
|
static int32 hdReturnReady(const int32 port, const int32 io, const int32 data)
|
||||||
{
|
{
|
||||||
return(0x80); // always indicate ready
|
return(0x80); // always indicate ready
|
||||||
|
|
||||||
// output operations have no effect
|
// output operations have no effect
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
/*------------------------------------------------------------
|
||||||
hdCstat (0xA1) CSTAT register. Accessed through the
|
hdCstat (0xA1) CSTAT register. Accessed through the
|
||||||
data register of 4-PIO port 1-A.
|
data register of 4-PIO port 1-A.
|
||||||
|
|
||||||
Comments: Returns error code byte of the most recent
|
Comments: Returns error code byte of the most recent
|
||||||
operation. Reading this byte also clears
|
operation. Reading this byte also clears
|
||||||
the CRDY bit, but this isn't actually done
|
the CRDY bit, but this isn't actually done
|
||||||
in the emulation since we're always ready.
|
in the emulation since we're always ready.
|
||||||
-------------------------------------------------------------*/
|
-------------------------------------------------------------*/
|
||||||
static int32 hdCstat(const int32 port, const int32 io, const int32 data)
|
static int32 hdCstat(const int32 port, const int32 io, const int32 data)
|
||||||
{
|
{
|
||||||
return(cstat);
|
return(cstat);
|
||||||
|
|
||||||
// output operations have no effect
|
// output operations have no effect
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
/*------------------------------------------------------------
|
||||||
hdAcmd (0xA3) ACMD register. Accessed through the
|
hdAcmd (0xA3) ACMD register. Accessed through the
|
||||||
data register of 4-PIO port 1-B.
|
data register of 4-PIO port 1-B.
|
||||||
|
|
||||||
Comments: The high byte of a command is written to
|
Comments: The high byte of a command is written to
|
||||||
this register and initiates the command.
|
this register and initiates the command.
|
||||||
The low byte of a command is assumed to
|
The low byte of a command is assumed to
|
||||||
have already been written and stored in
|
have already been written and stored in
|
||||||
cmdLowByte;
|
cmdLowByte;
|
||||||
-------------------------------------------------------------*/
|
-------------------------------------------------------------*/
|
||||||
static int32 hdAcmd(const int32 port, const int32 io, const int32 data)
|
static int32 hdAcmd(const int32 port, const int32 io, const int32 data)
|
||||||
{
|
{
|
||||||
uint32 command; // command field from command msb
|
uint32 command; // command field from command msb
|
||||||
uint32 unit; // unit number from command msb
|
uint32 unit; // unit number from command msb
|
||||||
uint32 buffer; // buffer number from command msb
|
uint32 buffer; // buffer number from command msb
|
||||||
|
|
||||||
// if not an OUT command, exit
|
// if not an OUT command, exit
|
||||||
|
|
||||||
if (io != IO_OUT)
|
if (io != IO_OUT)
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
// extract command and possible unit and buffer fields.
|
// extract command and possible unit and buffer fields.
|
||||||
|
|
||||||
cstat = 0; // assume command success
|
cstat = 0; // assume command success
|
||||||
command = (data >> CMD_SHIFT) & CMD_MASK;
|
command = (data >> CMD_SHIFT) & CMD_MASK;
|
||||||
unit = (data >> UNIT_SHIFT) & UNIT_MASK;
|
unit = (data >> UNIT_SHIFT) & UNIT_MASK;
|
||||||
buffer = data & BUFFER_MASK;
|
buffer = data & BUFFER_MASK;
|
||||||
|
|
||||||
// SEEK command. Updated selectedTrack.
|
// SEEK command. Updated selectedTrack.
|
||||||
|
|
||||||
if (command == CMD_SEEK) {
|
if (command == CMD_SEEK) {
|
||||||
selectedTrack = cmdLowByte + ((data & TRACK_MASKH) << TRACK_SHIFTH);
|
selectedTrack = cmdLowByte + ((data & TRACK_MASKH) << TRACK_SHIFTH);
|
||||||
if (selectedTrack >= HDSK_NUM_TRACKS)
|
if (selectedTrack >= HDSK_NUM_TRACKS)
|
||||||
selectedTrack = HDSK_NUM_TRACKS-1;
|
selectedTrack = HDSK_NUM_TRACKS-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// READ, READ UNFORMATTED or WRITE SECTOR command.
|
// READ, READ UNFORMATTED or WRITE SECTOR command.
|
||||||
|
|
||||||
else if ((command==CMD_WRITE_SEC) || (command==CMD_READ_SEC) || (command==CMD_READ_UNFMT)) {
|
else if ((command==CMD_WRITE_SEC) || (command==CMD_READ_SEC) || (command==CMD_READ_UNFMT)) {
|
||||||
selectedHead = (cmdLowByte >> HEAD_SHIFT) & HEAD_MASK;
|
selectedHead = (cmdLowByte >> HEAD_SHIFT) & HEAD_MASK;
|
||||||
selectedDisk = (selectedHead >> 1) + unit * 2 ;
|
selectedDisk = (selectedHead >> 1) + unit * 2 ;
|
||||||
selectedSector = cmdLowByte & SECTOR_MASK;
|
selectedSector = cmdLowByte & SECTOR_MASK;
|
||||||
selectedBuffer = buffer;
|
selectedBuffer = buffer;
|
||||||
if (mhdsk_dev.units[selectedDisk].fileref == NULL) // make sure a file is attached
|
if (mhdsk_dev.units[selectedDisk].fileref == NULL) // make sure a file is attached
|
||||||
cstat = CSTAT_NOT_READY;
|
cstat = CSTAT_NOT_READY;
|
||||||
else {
|
else {
|
||||||
if (command == CMD_WRITE_SEC)
|
if (command == CMD_WRITE_SEC)
|
||||||
doWrite();
|
doWrite();
|
||||||
else
|
else
|
||||||
doRead();
|
doRead();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// READ or WRITE BUFFER command. Initiates reading/loading specified buffer.
|
// READ or WRITE BUFFER command. Initiates reading/loading specified buffer.
|
||||||
|
|
||||||
else if ((command == CMD_WRITE_BUF) || (command == CMD_READ_BUF)) {
|
else if ((command == CMD_WRITE_BUF) || (command == CMD_READ_BUF)) {
|
||||||
selectedBuffer = buffer;
|
selectedBuffer = buffer;
|
||||||
maxBufferIdx = cmdLowByte;
|
maxBufferIdx = cmdLowByte;
|
||||||
if (maxBufferIdx == 0)
|
if (maxBufferIdx == 0)
|
||||||
maxBufferIdx = 256;
|
maxBufferIdx = 256;
|
||||||
bufferIdx = 0;
|
bufferIdx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// READ STATUS command (read IV byte)
|
// READ STATUS command (read IV byte)
|
||||||
|
|
||||||
else if (command == CMD_READ_STATUS) {
|
else if (command == CMD_READ_STATUS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SET IV byte command
|
// SET IV byte command
|
||||||
|
|
||||||
else if (command == CMD_SET_IV_BYTE) {
|
else if (command == CMD_SET_IV_BYTE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FORMAT command
|
// FORMAT command
|
||||||
|
|
||||||
else if (command == CMD_FORMAT) {
|
else if (command == CMD_FORMAT) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// INITIALIZE command
|
// INITIALIZE command
|
||||||
|
|
||||||
else if (command == CMD_INITIALIZE) {
|
else if (command == CMD_INITIALIZE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
/*------------------------------------------------------------
|
||||||
hdCdata (0xA5) Cdata register. Accessed through the
|
hdCdata (0xA5) Cdata register. Accessed through the
|
||||||
data register of 4-PIO port 1-B.
|
data register of 4-PIO port 1-B.
|
||||||
|
|
||||||
Comments: Returns data from the read buffer
|
Comments: Returns data from the read buffer
|
||||||
-------------------------------------------------------------*/
|
-------------------------------------------------------------*/
|
||||||
static int32 hdCdata(const int32 port, const int32 io, const int32 data)
|
static int32 hdCdata(const int32 port, const int32 io, const int32 data)
|
||||||
{
|
{
|
||||||
if (io == IO_IN) {
|
if (io == IO_IN) {
|
||||||
if (bufferIdx < maxBufferIdx)
|
if (bufferIdx < maxBufferIdx)
|
||||||
return(diskBuf[selectedBuffer][bufferIdx++]);
|
return(diskBuf[selectedBuffer][bufferIdx++]);
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
// output operations have no effect
|
// output operations have no effect
|
||||||
}
|
}
|
||||||
|
@ -335,70 +335,70 @@ static int32 hdCdata(const int32 port, const int32 io, const int32 data)
|
||||||
|
|
||||||
/*------------------------------------------------------------
|
/*------------------------------------------------------------
|
||||||
hdAdata (0xA7) ADATA register. Accessed through the
|
hdAdata (0xA7) ADATA register. Accessed through the
|
||||||
data register of 4-PIO port 2-B.
|
data register of 4-PIO port 2-B.
|
||||||
|
|
||||||
Comments: Accepts data into the current buffer
|
Comments: Accepts data into the current buffer
|
||||||
and is also the low byte of a command.
|
and is also the low byte of a command.
|
||||||
-------------------------------------------------------------*/
|
-------------------------------------------------------------*/
|
||||||
static int32 hdAdata(const int32 port, const int32 io, const int32 data)
|
static int32 hdAdata(const int32 port, const int32 io, const int32 data)
|
||||||
{
|
{
|
||||||
if (io == IO_OUT) {
|
if (io == IO_OUT) {
|
||||||
cmdLowByte = data & 0xff;
|
cmdLowByte = data & 0xff;
|
||||||
if (bufferIdx < maxBufferIdx)
|
if (bufferIdx < maxBufferIdx)
|
||||||
diskBuf[selectedBuffer][bufferIdx++] = data;
|
diskBuf[selectedBuffer][bufferIdx++] = data;
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-- doRead -------------------------------------------------
|
/*-- doRead -------------------------------------------------
|
||||||
Performs read from MITS Hard Disk image file
|
Performs read from MITS Hard Disk image file
|
||||||
|
|
||||||
Params: nothing
|
Params: nothing
|
||||||
Uses: selectedTrack, selectedHead, selectedSector
|
Uses: selectedTrack, selectedHead, selectedSector
|
||||||
selectedDisk, diskBuf[], mhdsk_dev
|
selectedDisk, diskBuf[], mhdsk_dev
|
||||||
Returns: nothing (updates cstat directly)
|
Returns: nothing (updates cstat directly)
|
||||||
Comments:
|
Comments:
|
||||||
-------------------------------------------------------------*/
|
-------------------------------------------------------------*/
|
||||||
static void doRead(void)
|
static void doRead(void)
|
||||||
{
|
{
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
uint32 fileOffset;
|
uint32 fileOffset;
|
||||||
|
|
||||||
uptr = mhdsk_dev.units + selectedDisk;
|
uptr = mhdsk_dev.units + selectedDisk;
|
||||||
fileOffset = HDSK_CYLINDER_SIZE * selectedTrack +
|
fileOffset = HDSK_CYLINDER_SIZE * selectedTrack +
|
||||||
HDSK_TRACK_SIZE * (selectedHead & 0x01) +
|
HDSK_TRACK_SIZE * (selectedHead & 0x01) +
|
||||||
HDSK_SECTOR_SIZE * selectedSector;
|
HDSK_SECTOR_SIZE * selectedSector;
|
||||||
if (sim_fseek(uptr->fileref, fileOffset, SEEK_SET))
|
if (sim_fseek(uptr->fileref, fileOffset, SEEK_SET))
|
||||||
cstat = CSTAT_NOT_READY; /* seek error */
|
cstat = CSTAT_NOT_READY; /* seek error */
|
||||||
else if (sim_fread(diskBuf[selectedBuffer], 1, HDSK_SECTOR_SIZE, uptr->fileref) != HDSK_SECTOR_SIZE)
|
else if (sim_fread(diskBuf[selectedBuffer], 1, HDSK_SECTOR_SIZE, uptr->fileref) != HDSK_SECTOR_SIZE)
|
||||||
cstat = CSTAT_NOT_READY; /* write error */
|
cstat = CSTAT_NOT_READY; /* write error */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-- doWrite ------------------------------------------------
|
/*-- doWrite ------------------------------------------------
|
||||||
Performs write to MITS Hard Disk image file
|
Performs write to MITS Hard Disk image file
|
||||||
|
|
||||||
Params: none
|
Params: none
|
||||||
Uses: selectedTrack, selectedHead, selectedSector
|
Uses: selectedTrack, selectedHead, selectedSector
|
||||||
selectedDisk, diskBuf[], mhdsk_dev
|
selectedDisk, diskBuf[], mhdsk_dev
|
||||||
Returns: nothing (updates cstat directly)
|
Returns: nothing (updates cstat directly)
|
||||||
Comments:
|
Comments:
|
||||||
-------------------------------------------------------------*/
|
-------------------------------------------------------------*/
|
||||||
static void doWrite(void)
|
static void doWrite(void)
|
||||||
{
|
{
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
uint32 fileOffset;
|
uint32 fileOffset;
|
||||||
|
|
||||||
uptr = mhdsk_dev.units + selectedDisk;
|
uptr = mhdsk_dev.units + selectedDisk;
|
||||||
if (((uptr->flags) & UNIT_DSK_WLK) == 0) { /* write enabled */
|
if (((uptr->flags) & UNIT_DSK_WLK) == 0) { /* write enabled */
|
||||||
fileOffset = HDSK_CYLINDER_SIZE * selectedTrack +
|
fileOffset = HDSK_CYLINDER_SIZE * selectedTrack +
|
||||||
HDSK_TRACK_SIZE * (selectedHead & 0x01) +
|
HDSK_TRACK_SIZE * (selectedHead & 0x01) +
|
||||||
HDSK_SECTOR_SIZE * selectedSector;
|
HDSK_SECTOR_SIZE * selectedSector;
|
||||||
if (sim_fseek(uptr->fileref, fileOffset, SEEK_SET))
|
if (sim_fseek(uptr->fileref, fileOffset, SEEK_SET))
|
||||||
cstat = CSTAT_NOT_READY; /* seek error */
|
cstat = CSTAT_NOT_READY; /* seek error */
|
||||||
else if (sim_fwrite(diskBuf[selectedBuffer], 1, HDSK_SECTOR_SIZE, uptr->fileref) != HDSK_SECTOR_SIZE)
|
else if (sim_fwrite(diskBuf[selectedBuffer], 1, HDSK_SECTOR_SIZE, uptr->fileref) != HDSK_SECTOR_SIZE)
|
||||||
cstat = CSTAT_NOT_READY; /* write error */
|
cstat = CSTAT_NOT_READY; /* write error */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cstat = CSTAT_WRITE_PROTECT;
|
cstat = CSTAT_WRITE_PROTECT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,6 +197,10 @@
|
||||||
RelativePath="..\AltairZ80\altairz80_hdsk.c"
|
RelativePath="..\AltairZ80\altairz80_hdsk.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\AltairZ80\altairz80_mhdsk.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\AltairZ80\altairz80_net.c"
|
RelativePath="..\AltairZ80\altairz80_net.c"
|
||||||
>
|
>
|
||||||
|
|
|
@ -330,7 +330,7 @@ ALTAIRZ80_SOURCE2 = $(ALTAIRZ80_DIR)S100_DISK1A.C,$(ALTAIRZ80_DIR)S100_DISK2.C,\
|
||||||
$(ALTAIRZ80_DIR)S100_SCP300F.C,$(ALTAIRZ80_DIR)SIM_IMD.C,\
|
$(ALTAIRZ80_DIR)S100_SCP300F.C,$(ALTAIRZ80_DIR)SIM_IMD.C,\
|
||||||
$(ALTAIRZ80_DIR)WD179X.C,$(ALTAIRZ80_DIR)S100_DISK3.C,\
|
$(ALTAIRZ80_DIR)WD179X.C,$(ALTAIRZ80_DIR)S100_DISK3.C,\
|
||||||
$(ALTAIRZ80_DIR)S100_ADCS6.C,$(ALTAIRZ80_DIR)S100_HDC1001.C,\
|
$(ALTAIRZ80_DIR)S100_ADCS6.C,$(ALTAIRZ80_DIR)S100_HDC1001.C,\
|
||||||
$(ALTAIRZ80_DIR)S100_IF3.C
|
$(ALTAIRZ80_DIR)S100_IF3.C,$(ALTAIRZ80_DIR)ALTAIRZ80_MHDSK.C
|
||||||
ALTAIRZ80_OPTIONS = /INCL=($(SIMH_DIR),$(ALTAIRZ80_DIR))/DEF=($(CC_DEFS))
|
ALTAIRZ80_OPTIONS = /INCL=($(SIMH_DIR),$(ALTAIRZ80_DIR))/DEF=($(CC_DEFS))
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
4
makefile
4
makefile
|
@ -1011,9 +1011,9 @@ ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \
|
||||||
${ALTAIRZ80D}/altairz80_hdsk.c ${ALTAIRZ80D}/altairz80_net.c \
|
${ALTAIRZ80D}/altairz80_hdsk.c ${ALTAIRZ80D}/altairz80_net.c \
|
||||||
${ALTAIRZ80D}/flashwriter2.c ${ALTAIRZ80D}/i86_decode.c \
|
${ALTAIRZ80D}/flashwriter2.c ${ALTAIRZ80D}/i86_decode.c \
|
||||||
${ALTAIRZ80D}/i86_ops.c ${ALTAIRZ80D}/i86_prim_ops.c \
|
${ALTAIRZ80D}/i86_ops.c ${ALTAIRZ80D}/i86_prim_ops.c \
|
||||||
${ALTAIRZ80D}/i8272.c ${ALTAIRZ80D}/insnsd.c \
|
${ALTAIRZ80D}/i8272.c ${ALTAIRZ80D}/insnsd.c ${ALTAIRZ80D}/altairz80_mhdsk.c \
|
||||||
${ALTAIRZ80D}/mfdc.c ${ALTAIRZ80D}/n8vem.c ${ALTAIRZ80D}/vfdhd.c \
|
${ALTAIRZ80D}/mfdc.c ${ALTAIRZ80D}/n8vem.c ${ALTAIRZ80D}/vfdhd.c \
|
||||||
${ALTAIRZ80D}/s100_disk1a.c ${ALTAIRZ80D}/s100_disk2.c ${ALTAIRZ80D}/s100_disk3.c\
|
${ALTAIRZ80D}/s100_disk1a.c ${ALTAIRZ80D}/s100_disk2.c ${ALTAIRZ80D}/s100_disk3.c \
|
||||||
${ALTAIRZ80D}/s100_fif.c ${ALTAIRZ80D}/s100_mdriveh.c \
|
${ALTAIRZ80D}/s100_fif.c ${ALTAIRZ80D}/s100_mdriveh.c \
|
||||||
${ALTAIRZ80D}/s100_mdsad.c ${ALTAIRZ80D}/s100_selchan.c \
|
${ALTAIRZ80D}/s100_mdsad.c ${ALTAIRZ80D}/s100_selchan.c \
|
||||||
${ALTAIRZ80D}/s100_ss1.c ${ALTAIRZ80D}/s100_64fdc.c \
|
${ALTAIRZ80D}/s100_ss1.c ${ALTAIRZ80D}/s100_64fdc.c \
|
||||||
|
|
Loading…
Add table
Reference in a new issue