mirror of
https://github.com/open-simh/simtools.git
synced 2026-02-08 01:02:13 +00:00
Too much to list all, but includes (in no particular order): - Cleanup for 64-bit builds, MSVC warnings. - Structured help - Help file compiler. - Supports volsets, writes/create work. - Support for I18n in messages, help. - Makefiles. - Initialize volume/volset - Command line editing/history Builds and works on Linux and Windows (VS). Not recently built or tested on other platforms, but not intentinonally broken.
248 lines
8.0 KiB
C
248 lines
8.0 KiB
C
/* PHYOS2.C v1.2 Physical I/O module for OS2 */
|
|
|
|
/* This is part of ODS2 written by Paul Nankervis,
|
|
* email address: Paulnank@au1.ibm.com
|
|
*
|
|
* ODS2 is distributed freely for all members of the
|
|
* VMS community to use. However all derived works
|
|
* must maintain comments in their source to acknowledge
|
|
* the contributions of the original author and
|
|
* subsequent contributors. This is free software; no
|
|
* warranty is offered, and while we believe it to be useful,
|
|
* you use it at your own risk.
|
|
*/
|
|
|
|
/* This version implemented to read from Floppy or CD by
|
|
* guessing that A: or B: will be a floppy and anything
|
|
* else is probably a CD?
|
|
*/
|
|
|
|
/* This module has not been compiled in quite some time, and
|
|
* while some effort has been made to keep up with API changes,
|
|
* it requires quite a bit of work to bring it up to date.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#define INCL_DOS
|
|
#define INCL_DOSDEVIOCTL
|
|
#define INCL_NOPMAPI
|
|
#include <os2.h>
|
|
#include "ods2.h"
|
|
#include "phyio.h"
|
|
#include "ssdef.h"
|
|
#include "sysmsg.h"
|
|
|
|
static vmscond_t phyio_read( struct DEV *dev, uint32_t block, uint32_t length,
|
|
char *buffer );
|
|
static vmscond_t phyio_write( struct DEV *dev, uint32_t block, uint32_t length,
|
|
const char *buffer );
|
|
|
|
unsigned init_count = 0;
|
|
unsigned read_count = 0;
|
|
unsigned write_count = 0;
|
|
|
|
void phyio_show( showtype_t type ) {
|
|
switch( type ) {
|
|
case SHOW_STATS:
|
|
printmsg( IO_STATS, MSG_TEXT, init_count, read_count, write_count );
|
|
return;
|
|
case SHOW_FILE64:
|
|
printmsg( IO_NOLARGEFILE, MSG_TEXT );
|
|
return;
|
|
case SHOW_DEVICES:
|
|
return;
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
|
|
|
|
#pragma pack(1)
|
|
/*------------------------------------------------*
|
|
* Cat 0x80, Func 0x72: Read Long *
|
|
*------------------------------------------------*/
|
|
struct ReadLong {
|
|
ULONG ID_code;
|
|
UCHAR address_mode;
|
|
USHORT transfer_count;
|
|
ULONG start_sector;
|
|
UCHAR reserved;
|
|
UCHAR interleave_size;
|
|
UCHAR interleave_skip_factor;
|
|
};
|
|
#pragma pack()
|
|
|
|
#define SECTORSIZE 2048
|
|
struct ReadLong rl = {
|
|
0x31304443L, /* "CD01" */
|
|
0, /* Address mode */
|
|
1, /* Transfer count */
|
|
0, /* Start Sector */
|
|
0, /* Reserved */
|
|
0, /* Interleave size */
|
|
0/* Skip factor */
|
|
};
|
|
|
|
#define HANDLE_MAX 32
|
|
int hand_count = 0;
|
|
struct HANDLE {
|
|
HFILE hand_hfile;
|
|
int hand_drive;
|
|
} handle[HANDLE_MAX];
|
|
|
|
void phyio_help( void ) {
|
|
(void) helptopic( 0, "MOUNT OS2" );
|
|
|
|
return;
|
|
}
|
|
|
|
NOTE: This will not compile. The API for phyio_init has changed to
|
|
taking a DEV struct. I'm leaving it this way becauses I don't have the
|
|
ability to test under OS2. This was left undone when the API was changed...
|
|
before my time. /TL
|
|
|
|
|
|
vmscond_t phyio_init(int devlen,char *devnam,unsigned *hand,struct phyio_info *info) {
|
|
dev->devread = phyio_read;
|
|
dev->devwrite = phyio_write;
|
|
|
|
if (hand_count < HANDLE_MAX - 1) {
|
|
ULONG usAction;
|
|
ULONG open_mode;
|
|
ULONG bCmd;
|
|
ULONG stat;
|
|
char device[40];
|
|
memcpy(device,devnam,devlen);
|
|
device[devlen] = '\0';
|
|
handle[hand_count].hand_drive = toupper(*device);
|
|
open_mode = OPEN_FLAGS_DASD | OPEN_SHARE_DENYREADWRITE
|
|
| OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR
|
|
| OPEN_FLAGS_NOINHERIT | OPEN_ACCESS_READWRITE;
|
|
stat = DosOpen(device, /* filename to open */
|
|
&handle[hand_count].hand_hfile,
|
|
/* address of file handle */
|
|
&usAction,
|
|
/* address to store action taken */
|
|
0L,
|
|
/* size of new file */
|
|
FILE_NORMAL,
|
|
/* file's attribute */
|
|
FILE_OPEN,
|
|
/* action to take if file exists */
|
|
open_mode,
|
|
/* file's open mode */
|
|
0L);
|
|
/* Reserved */
|
|
if (stat) {
|
|
switch (stat) {
|
|
case 15:
|
|
printf("Drive %s is invalid.\n",device);
|
|
break;
|
|
case 21:
|
|
printf("Drive %s is not ready.\n",device);
|
|
break;
|
|
case 32:
|
|
printf("Drive %s is currently locked by another process.\n",device);
|
|
break;
|
|
case 65:
|
|
printf("Drive %s is a network drive.\n",device);
|
|
break;
|
|
default:
|
|
printf("error %d opening drive %s\n",stat,device);
|
|
}
|
|
return SS$_PARITY;
|
|
}
|
|
bCmd = 0;
|
|
stat = DosDevIOCtl(handle[hand_count].hand_hfile,IOCTL_DISK,DSK_LOCKDRIVE,&bCmd,1,NULL,NULL,0,NULL);
|
|
if (stat) {
|
|
printf("Error %d locking drive\n",stat);
|
|
return SS$_DEVNOTALLOC;
|
|
}
|
|
if (handle[hand_count].hand_drive > 'C') {
|
|
info->status = PHYIO_READONLY;
|
|
} else {
|
|
info->status = 0;
|
|
}
|
|
*hand = hand_count++;
|
|
init_count++;
|
|
return 1;
|
|
} else {
|
|
return SS$_IVCHAN;
|
|
}
|
|
}
|
|
|
|
static vmscond_t phy_getsect(HFILE hfile, uint32_t sector,char *buffer) {
|
|
ULONG ulPinout,ulDinout;
|
|
ULONG stat;
|
|
char rawsect[SECTORSIZE + 304];
|
|
ulPinout = sizeof(rl);
|
|
ulDinout = sizeof(rawsect);
|
|
rl.start_sector = sector;
|
|
stat = DosDevIOCtl(hfile,
|
|
IOCTL_CDROMDISK,
|
|
CDROMDISK_READLONG,
|
|
&rl,sizeof(rl),&ulPinout,
|
|
rawsect,sizeof(rawsect),&ulDinout);
|
|
if (stat) {
|
|
printf("sys%04u: CDROMDISK_READLONG error\n",stat);
|
|
return SS$_PARITY;
|
|
}
|
|
memcpy(buffer,rawsect + 16,SECTORSIZE);
|
|
return 1;
|
|
}
|
|
|
|
static vmscond_t phyio_read(unsigned handno, uint32_t block, uint32_t length, char *buffer) {
|
|
register vmscond_t sts = SS$_NORMAL;
|
|
#if DEBUG
|
|
printf("PHYIO_READ block %d length %d\n",block,length);
|
|
#endif
|
|
if (handno >= hand_count) {
|
|
sts = SS$_IVCHAN;
|
|
} else {
|
|
if (handle[handno].hand_drive > 'C') {
|
|
register unsigned sect = block * 512 / SECTORSIZE;
|
|
register unsigned offset = (block - sect * SECTORSIZE / 512) * 512;
|
|
while (length > 0) {
|
|
register unsigned transfer;
|
|
if (offset == 0 && length >= SECTORSIZE) {
|
|
transfer = SECTORSIZE;
|
|
if (((sts = phy_getsect(handle[handno].hand_hfile,sect,buffer)) & 1) == 0) break;
|
|
} else {
|
|
char sector[SECTORSIZE];
|
|
if (((sts = phy_getsect(handle[handno].hand_hfile,sect,sector)) & 1) == 0) break;
|
|
transfer = SECTORSIZE - offset;
|
|
if (transfer > length) transfer = length;
|
|
memcpy(buffer,sector + offset,transfer);
|
|
}
|
|
buffer += transfer;
|
|
length -= transfer;
|
|
sect++;
|
|
offset = 0;
|
|
}
|
|
} else {
|
|
USHORT rc;
|
|
ULONG oldpos,lenread;
|
|
sts = SS$_PARITY;
|
|
rc = DosSetFilePtr(handle[handno].hand_hfile,block * 512,0,&oldpos);
|
|
if (rc == 0) {
|
|
rc = DosRead(handle[handno].hand_hfile,buffer,length,&lenread);
|
|
if (rc == 0 && lenread == length) sts = 1;
|
|
}
|
|
}
|
|
}
|
|
if( $SUCCESSFUL(sts) ) {
|
|
read_count++;
|
|
} else {
|
|
printf("PHYOS2 Error %d Block %d Length %d\n",sts,block,length);
|
|
}
|
|
return sts;
|
|
}
|
|
|
|
static vmscond_t phyio_write(unsigned handle, uint32_t block, uint32_t length, char *buffer) {
|
|
write_count++;
|
|
return SS$_WRITLCK;
|
|
}
|