source: xtideuniversalbios/trunk/Serial_Server/library/Image.cpp@ 590

Last change on this file since 590 was 589, checked in by Krister Nordvall, 9 years ago

Changes:

  • BIOS: Fixed a purely cosmetic bug from r542 where, in builds containing MODULE_EBIOS, the boot menu would display an incorrect drive size (0.4 kB with MODULE_STRINGS_COMPRESSED or 0.5 kB without) for old drives with no support for LBA.
  • Fixed a bug from r392 where Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent would return the ID in AL instead of AH (if DANGEROUS_DETECTION had been defined).
  • Fixed a bug from r587 in AdvAtaInit.asm that would prevent detection of QDI Vision controllers.
  • Also changed how the QDI Vision IDs are defined (removed the need for shifting) to avoid confusion. This fixed a potential bug from r587 in AdvAtaInit.asm where some IDs were not being shifted.
  • Fixed a bug in PDC20x30.asm from r587 where GetPdcIDtoAX would not return with the IDE base port in DX so DisablePdcProgrammingMode would fail.
  • Made some changes to ModuleDependency.inc and other files so that MODULE_ADVANCED_ATA now requires USE_386. Consequently it is no longer included in the regular AT-builds, only in the 386_8k-build.
  • Moved the UNROLL_SECTORS_IN_CX_TO_xWORDS macros from IDE_8bit.inc to IdeIO.inc which means it's now possible to build a BIOS without MODULE_8BIT_IDE.
  • XTIDECFG: Added a minimum DOS version check (since it needs DOS version 2+) to allow the program to quit gracefully in the unlikely scenario where someone tries to run it under DOS version 1.
  • Made some changes to Drive.asm to improve drive enumeration. The old method using GET_DOS_DRIVE_PARAMETER_BLOCK_FOR_SPECIFIC_DRIVE worked well in Windows XP but not in Windows 98 SE (in Windows or in DOS mode). The two problems were; 1) The function call would access the drives which on single floppy drive systems would cause Windows to swap between A: and B: (throwing a blue screen asking the user to insert a disk etc). 2) Only floppy drives and FAT16 drives would be available in the list of drives, no FAT32/optical/network drives.
  • Improved code in IdeControllerMenu.asm so that the default port addresses for all IDE interfaces are now restored when (re-)selecting the (same) type of IDE device.
  • Also made it impossible to select a device type unless the required module is included in the loaded BIOS.
  • The version check done when loading a BIOS now uses the FLASH_SIGNATURE definition from Version.inc. Any changes affecting RomVars now only requires updating that definition. This means that changes to RomVars must be implemented in both the BIOS and XTIDECFG before being committed to the repository.
  • Added a compatibility fix for 3Com 3C503 cards to the ROM checksumming code in Buffers.asm (Buffers_GenerateChecksum).
  • SerDrive: Made some minor changes to file names and paths to improve compatibility with case sensitive environments.
  • BIOSDRVS: Made a minor size optimization which as a side effect also makes it compatible with all DOS versions including DOS version 1.
  • Library: Renamed the WAIT_RETRACE_IF_NECESSARY_THEN macro to CALL_WAIT_FOR_RETRACE_IF_NECESSARY_THEN and made a tail-call-optimized version of it (JMP_WAIT_FOR_RETRACE_IF_NECESSARY_THEN).
  • A speed optimization to the eRCL_IM macro for 386 and higher. This change breaks emulation in the sense that the macro will fail when given a memory operand as the first parameter.
  • Other minor optimizations and fixes.
File size: 9.7 KB
RevLine 
[209]1//======================================================================
2//
3// Project: XTIDE Universal BIOS, Serial Port Server
4//
[589]5// File: Image.cpp - Abstract base class for disk image support
[209]6//
7
[376]8//
[526]9// XTIDE Universal BIOS and Associated Tools
10// Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
[376]11//
12// This program is free software; you can redistribute it and/or modify
13// it under the terms of the GNU General Public License as published by
14// the Free Software Foundation; either version 2 of the License, or
15// (at your option) any later version.
[526]16//
[376]17// This program is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
[526]20// GNU General Public License for more details.
[376]21// Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22//
23
[589]24#include "Library.h"
[209]25#include <memory.h>
26#include <stdlib.h>
27#include <string.h>
[219]28#include <stdio.h>
[209]29
[526]30struct floppyInfo floppyInfos[] =
[258]31{
[259]32 { 1, 2949120 / 512, 6, 80, 2, 36 }, // 2.88MB 3.5"
33 { 0, 2867200 / 512, 6, 80, 2, 36 }, // 2.88MB 3.5" (alternate spelling with 2.8)
34 { 0, 2969600 / 512, 6, 80, 2, 36 }, // 2.88MB 3.5" (alternate spelling with 2.9)
35 { 1, 1474560 / 512, 4, 80, 2, 18 }, // 1.44MB 3.5"
36 { 0, 1433600 / 512, 4, 80, 2, 18 }, // 1.44MB 3.5" (alternate spelling with 1.4)
37 { 1, 1228800 / 512, 2, 80, 2, 15 }, // 1.2MB 5.25"
38 { 1, 737280 / 512, 3, 80, 1, 18 }, // 720KB 3.5"
39 { 1, 368640 / 512, 1, 40, 2, 9 }, // 360KB 5.25"
40 { 1, 327680 / 512, 0, 40, 2, 8 }, // 320KB 5.25"
41 { 1, 184320 / 512, 0, 40, 1, 9 }, // 180KB 5.25" single sided
42 { 1, 163840 / 512, 0, 40, 1, 8 }, // 160KB 5.25" single sided
43 { 0, 0, 0, 0, 0, 0 }
[258]44};
45
[259]46struct floppyInfo *FindFloppyInfoBySize( double size )
47{
48 struct floppyInfo *fi;
49
50 for( fi = floppyInfos; fi->size != 0 && !(size+5 > fi->size && size-5 < fi->size); fi++ ) ;
51
52 if( fi->size == 0 )
53 fi = NULL;
54
55 return( fi );
56}
57
[277]58void flipEndian( unsigned short *buff, unsigned int len )
59{
60 for( unsigned int t = 0; t < len/2; t++ )
61 buff[t] = (buff[t] & 0xff) << 8 | (buff[t] & 0xff00) >> 8;
62}
63
[209]64Image::Image( char *name, int p_readOnly, int p_drive )
65{
66}
67
68Image::Image( char *name, int p_readOnly, int p_drive, int p_create, unsigned long p_lba )
69{
70}
71
[217]72Image::Image( char *name, int p_readOnly, int p_drive, int p_create, unsigned long p_cyl, unsigned long p_head, unsigned long p_sect, int p_useCHS )
[209]73{
74}
75
[217]76void Image::init( char *name, int p_readOnly, int p_drive, unsigned long p_cyl, unsigned long p_head, unsigned long p_sect, int p_useCHS )
[209]77{
[217]78 double sizef;
[258]79 char sizeChar;
80 struct floppyInfo *f;
[217]81
[209]82 for( char *c = shortFileName = name; *c; c++ )
83 if( *c == '\\' || *c == '/' || *c == ':' )
84 shortFileName = c+1;
85
86 if( *(shortFileName) == 0 )
[211]87 {
88 log( 1, "Can't parse '%s' for short file name\n\n", name );
89 shortFileName = "SerDrive";
90 }
[526]91
[209]92 readOnly = p_readOnly;
93 drive = p_drive;
[217]94
95 if( totallba > 0xfffffff ) // lba28 limit - 28 bits
96 log( -1, "'%s', Image size larger than LBA28 maximum of 137,438,952,960 bytes, %lu", name, totallba );
97
98 if( totallba == 0 )
99 log( -1, "'%s', Image size zero?" );
100
[258]101 floppy = 0;
[259]102 for( f = floppyInfos; f->size && !(f->size == totallba && f->real); f++ ) ;
[258]103 if( f->size )
104 {
105 floppy = 1;
106 floppyType = f->type;
107 p_useCHS = 1;
108 p_cyl = f->cylinders;
109 p_head = f->heads;
110 p_sect = f->sectors;
[259]111 totallba = p_cyl * p_head * p_sect;
[258]112 }
113
[430]114 if( p_cyl )
[217]115 {
[430]116 if( (p_sect > 255 || p_sect < 1) || (p_head > 16 || p_head < 1) || (p_cyl > 65536 || p_cyl < 1) )
117 log( -1, "'%s', parts of the CHS geometry (%lu:%lu:%lu) are out of the range (1-65536:1-16:1-255)", name, p_cyl, p_head, p_sect );
118 else if( totallba != (p_sect * p_head * p_cyl) )
119 log( -1, "'%s', file size does not match geometry", name );
120 sect = p_sect;
121 head = p_head;
122 cyl = p_cyl;
123 }
124 else
125 {
126 if( totallba > 65536*16*63 )
[217]127 {
[430]128 log( 0, "'%s': Warning: Image size is greater than derived standard CHS maximum, limiting CHS to 65535:16:63, consider using -g to specify geometry", name );
129 cyl = 65536;
130 head = 16;
131 sect = 63;
[217]132 }
[430]133 else if( (totallba % 16) != 0 || ((totallba/16) % 63) != 0 )
[217]134 {
[430]135 log( -1, "'%s', file size does not match standard CHS geometry (x:16:63), please specify geometry explicitly with -g", name );
136 }
[526]137 else
[430]138 {
139 sect = 63;
140 head = 16;
141 cyl = (totallba / sect / head);
142 if( cyl > 65536 )
[217]143 {
[430]144 log( -1, "'%s', derived standard CHS geometry of %lu:16:63 is has more cylinders than 65536, please specify geometry explicitly with -g", name, cyl, head, sect );
[217]145 }
146 }
147 }
[430]148
[217]149 useCHS = p_useCHS;
150
151 sizef = totallba/2048.0;
[258]152 sizeChar = 'M';
[526]153 if( sizef < 1 )
[258]154 {
155 sizef *= 1024;
156 sizeChar = 'K';
157 }
[217]158 if( useCHS )
[258]159 log( 0, "%s: %s with CHS geometry %u:%u:%u, size %.2lf %cB",
160 name, (floppy ? "Floppy Disk" : "Hard Disk"), cyl, head, sect, sizef, sizeChar );
[217]161 else
[526]162 log( 0, "%s: %s with %lu LBA sectors, size %.2lf %cB (CHS geometry %u:%u:%u)",
[430]163 name, (floppy ? "Floppy Disk" : "Hard Disk"), totallba, sizef, sizeChar, cyl, head, sect );
[209]164}
165
[217]166int Image::parseGeometry( char *str, unsigned long *p_cyl, unsigned long *p_head, unsigned long *p_sect )
[209]167{
168 char *c, *s, *h;
169 unsigned long cyl, sect, head;
170
171 c = str;
[217]172 for( h = c; *h && *h != ':' && *h != 'x' && *h != 'X'; h++ ) ;
173 if( !*h )
174 return( 0 );
175
176 *h = '\0';
177 h++;
[526]178 for( s = h+1; *s && *s != ':' && *s != 'x' && *s != 'X'; s++ ) ;
[209]179 if( !*s )
180 return( 0 );
181
182 *s = '\0';
183 s++;
184
185 cyl = atol(c);
[217]186 head = atol(h);
[209]187 sect = atol(s);
188
189 if( cyl == 0 || sect == 0 || head == 0 )
190 return( 0 );
191
192 *p_cyl = cyl;
[217]193 *p_head = head;
[209]194 *p_sect = sect;
195
196 return( 1 );
197}
198
199#define ATA_wGenCfg 0
200#define ATA_wCylCnt 1
201#define ATA_wHeadCnt 3
202#define ATA_wBpTrck 4
203#define ATA_wBpSect 5
204#define ATA_wSPT 6
[277]205
[209]206#define ATA_strSerial 10
[277]207#define ATA_strSerial_Length 20
208
[209]209#define ATA_strFirmware 23
[277]210#define ATA_strFirmware_Length 8
211
[209]212#define ATA_strModel 27
[284]213#define ATA_strModel_Length 40 // Maximum allowable length of the string according to the ATA spec
214#define XTIDEBIOS_strModel_Length 30 // Maximum length copied out of the ATA information by the BIOS
[277]215
[209]216#define ATA_wCaps 49
217#define ATA_wCurCyls 54
218#define ATA_wCurHeads 55
219#define ATA_wCurSPT 56
220#define ATA_dwCurSCnt 57
221#define ATA_dwLBACnt 60
222
[258]223// Words carved out of the vendor specific area for our use
224//
[277]225#define ATA_wSerialServerVersion 157
[334]226#define ATA_wSerialDriveFlags 158
[258]227#define ATA_wSerialPortAndBaud 159
[209]228
[258]229// Defines used in the words above
230//
[209]231#define ATA_wCaps_LBA 0x200
232
233#define ATA_wGenCfg_FIXED 0x40
234
[334]235// These are all shifted by 1 bit to the right, so that SerialDPT_Finalize can shift them into proper position
236// and shift the high order bit into the carry flag to indicate a floppy drive is present.
237//
238#define ATA_wSerialDriveFlags_Floppy 0x88
239#define ATA_wSerialDriveFlags_Present 0x02
240#define ATA_wSerialDriveFlags_FloppyType_FieldPosition 4
[258]241
[209]242struct comPorts {
243 unsigned long port;
244 unsigned char com;
245};
[526]246struct comPorts supportedComPorts[] =
247{
248 { 0x3f8, '1' },
249 { 0x2f8, '2' },
250 { 0x3e8, '3' },
251 { 0x2e8, '4' },
252 { 0x2f0, '5' },
253 { 0x3e0, '6' },
254 { 0x2e0, '7' },
[209]255 { 0x260, '8' },
256 { 0x368, '9' },
257 { 0x268, 'A' },
258 { 0x360, 'B' },
259 { 0x270, 'C' },
[526]260 { 0, 0 }
[209]261};
262
[277]263void Image::respondInquire( unsigned short *buff, unsigned short originalPortAndBaud, struct baudRate *baudRate, unsigned short port, unsigned char scan )
[209]264{
[277]265 char formatBuff[ 128 ];
[284]266 char speedBuff[ 128 ];
[277]267
[233]268 memset( &buff[0], 0, 514 );
[209]269
[233]270 if( scan )
[209]271 {
[233]272 unsigned short comPort = 0;
273 struct comPorts *cp;
274
275 if( port )
276 {
277 for( cp = supportedComPorts; cp->port && cp->port != port; cp++ ) ;
278 if( cp->port )
279 comPort = cp->com;
280 }
281
282 if( comPort )
[284]283 sprintf( speedBuff, " (COM%c/%s)", comPort, baudRate->display );
[233]284 else
[284]285 sprintf( speedBuff, " (%s baud)", shortFileName, baudRate->display );
286
287 sprintf( formatBuff, "%.*s%s ", XTIDEBIOS_strModel_Length - strlen(speedBuff), shortFileName, speedBuff );
[209]288 }
289 else
[284]290 sprintf( formatBuff, "%.*s ", XTIDEBIOS_strModel_Length, shortFileName );
[277]291 strncpy( (char *) &buff[ATA_strModel], formatBuff, ATA_strModel_Length );
292 flipEndian( &buff[ATA_strModel], ATA_strModel_Length );
[209]293
[277]294 strncpy( (char *) &buff[ATA_strSerial], "SerialDrive ", ATA_strSerial_Length );
295 flipEndian( &buff[ATA_strSerial], ATA_strSerial_Length );
[209]296
[277]297 sprintf( formatBuff, "%d.%d ", SERIAL_SERVER_MAJORVERSION, SERIAL_SERVER_MINORVERSION );
298 strncpy( (char *) &buff[ATA_strFirmware], formatBuff, ATA_strFirmware_Length );
299 flipEndian( &buff[ATA_strFirmware], ATA_strFirmware_Length );
[209]300
[430]301 buff[ ATA_wCylCnt ] = cyl;
302 buff[ ATA_wHeadCnt ] = head;
303 buff[ ATA_wSPT ] = sect;
304
305 if( !useCHS )
[217]306 {
307 buff[ ATA_wCaps ] = ATA_wCaps_LBA;
308 buff[ ATA_dwLBACnt ] = (unsigned short) (totallba & 0xffff);
309 buff[ ATA_dwLBACnt+1 ] = (unsigned short) (totallba >> 16);
310 }
311
[526]312 // We echo back the port and baud that we were called on from the client,
[277]313 // the client then uses this value to finalize the DPT.
314 //
315 buff[ ATA_wSerialPortAndBaud ] = originalPortAndBaud;
316
317 // In case the client requires a specific server version...
318 //
319 buff[ ATA_wSerialServerVersion ] = (SERIAL_SERVER_MAJORVERSION << 8) | SERIAL_SERVER_MINORVERSION;
320
[334]321 buff[ ATA_wSerialDriveFlags ] = ATA_wSerialDriveFlags_Present;
[258]322 if( floppy )
[526]323 buff[ ATA_wSerialDriveFlags ] |=
[334]324 ATA_wSerialDriveFlags_Floppy | (floppyType << ATA_wSerialDriveFlags_FloppyType_FieldPosition);
[258]325
326 // we always set this, so that the bulk of the BIOS will consider this disk as a hard disk
327 //
[209]328 buff[ ATA_wGenCfg ] = ATA_wGenCfg_FIXED;
329}
[284]330
Note: See TracBrowser for help on using the repository browser.