/* 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 #include #include #include #define INCL_DOS #define INCL_DOSDEVIOCTL #define INCL_NOPMAPI #include #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; }