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

Last change on this file since 589 was 589, checked in by krille_n_, 8 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
Line 
1//======================================================================
2//
3// Project:     XTIDE Universal BIOS, Serial Port Server
4//
5// File:        Image.cpp - Abstract base class for disk image support
6//
7
8//
9// XTIDE Universal BIOS and Associated Tools
10// Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
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.
16//
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
20// GNU General Public License for more details.
21// Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22//
23
24#include "Library.h"
25#include <memory.h>
26#include <stdlib.h>
27#include <string.h>
28#include <stdio.h>
29
30struct floppyInfo floppyInfos[] =
31{
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 }
44};
45
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
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
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
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 )
73{
74}
75
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 )
77{
78    double sizef;
79    char sizeChar;
80    struct floppyInfo *f;
81
82    for( char *c = shortFileName = name; *c; c++ )
83        if( *c == '\\' || *c == '/' || *c == ':' )
84            shortFileName = c+1;
85
86    if( *(shortFileName) == 0 )
87    {
88        log( 1, "Can't parse '%s' for short file name\n\n", name );
89        shortFileName = "SerDrive";
90    }
91
92    readOnly = p_readOnly;
93    drive = p_drive;
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
101    floppy = 0;
102    for( f = floppyInfos; f->size && !(f->size == totallba && f->real); f++ ) ;
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;
111        totallba = p_cyl * p_head * p_sect;
112    }
113
114    if( p_cyl )
115    {
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 )
127        {
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;
132        }
133        else if( (totallba % 16) != 0 || ((totallba/16) % 63) != 0 )
134        {
135            log( -1, "'%s', file size does not match standard CHS geometry (x:16:63), please specify geometry explicitly with -g", name );
136        }
137        else
138        {
139            sect = 63;
140            head = 16;
141            cyl = (totallba / sect / head);
142            if( cyl > 65536 )
143            {
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 );
145            }
146        }
147    }
148
149    useCHS = p_useCHS;
150
151    sizef = totallba/2048.0;
152    sizeChar = 'M';
153    if( sizef < 1 )
154    {
155        sizef *= 1024;
156        sizeChar = 'K';
157    }
158    if( useCHS )
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 );
161    else
162        log( 0, "%s: %s with %lu LBA sectors, size %.2lf %cB (CHS geometry %u:%u:%u)",
163             name, (floppy ? "Floppy Disk" : "Hard Disk"), totallba, sizef, sizeChar, cyl, head, sect );
164}
165
166int Image::parseGeometry( char *str, unsigned long *p_cyl, unsigned long *p_head, unsigned long *p_sect )
167{
168    char *c, *s, *h;
169    unsigned long cyl, sect, head;
170
171    c = str;
172    for( h = c; *h && *h != ':' && *h != 'x' && *h != 'X'; h++ ) ;
173    if( !*h )
174        return( 0 );
175
176    *h = '\0';
177    h++;
178    for( s = h+1; *s && *s != ':' && *s != 'x' && *s != 'X'; s++ ) ;
179    if( !*s )
180        return( 0 );
181
182    *s = '\0';
183    s++;
184
185    cyl = atol(c);
186    head = atol(h);
187    sect = atol(s);
188
189    if( cyl == 0 || sect == 0 || head == 0 )
190        return( 0 );
191
192    *p_cyl = cyl;
193    *p_head = head;
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
205
206#define ATA_strSerial 10
207#define ATA_strSerial_Length 20
208
209#define ATA_strFirmware 23
210#define ATA_strFirmware_Length 8
211
212#define ATA_strModel 27
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
215
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
223// Words carved out of the vendor specific area for our use
224//
225#define ATA_wSerialServerVersion 157
226#define ATA_wSerialDriveFlags 158
227#define ATA_wSerialPortAndBaud 159
228
229// Defines used in the words above
230//
231#define ATA_wCaps_LBA 0x200
232
233#define ATA_wGenCfg_FIXED 0x40
234
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
241
242struct comPorts {
243    unsigned long port;
244    unsigned char com;
245};
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' },
255  { 0x260, '8' },
256  { 0x368, '9' },
257  { 0x268, 'A' },
258  { 0x360, 'B' },
259  { 0x270, 'C' },
260  { 0, 0 }
261};
262
263void Image::respondInquire( unsigned short *buff, unsigned short originalPortAndBaud, struct baudRate *baudRate, unsigned short port, unsigned char scan )
264{
265    char formatBuff[ 128 ];
266    char speedBuff[ 128 ];
267
268    memset( &buff[0], 0, 514 );
269
270    if( scan )
271    {
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 )
283            sprintf( speedBuff, " (COM%c/%s)", comPort, baudRate->display );
284        else
285            sprintf( speedBuff, " (%s baud)", shortFileName, baudRate->display );
286
287        sprintf( formatBuff, "%.*s%s ", XTIDEBIOS_strModel_Length - strlen(speedBuff), shortFileName, speedBuff );
288    }
289    else
290        sprintf( formatBuff, "%.*s ", XTIDEBIOS_strModel_Length, shortFileName );
291    strncpy( (char *) &buff[ATA_strModel], formatBuff, ATA_strModel_Length );
292    flipEndian( &buff[ATA_strModel], ATA_strModel_Length );
293
294    strncpy( (char *) &buff[ATA_strSerial], "SerialDrive ", ATA_strSerial_Length );
295    flipEndian( &buff[ATA_strSerial], ATA_strSerial_Length );
296
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 );
300
301    buff[ ATA_wCylCnt ] = cyl;
302    buff[ ATA_wHeadCnt ] = head;
303    buff[ ATA_wSPT ] = sect;
304
305    if( !useCHS )
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
312    // We echo back the port and baud that we were called on from the client,
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
321    buff[ ATA_wSerialDriveFlags ] = ATA_wSerialDriveFlags_Present;
322    if( floppy )
323        buff[ ATA_wSerialDriveFlags ] |=
324            ATA_wSerialDriveFlags_Floppy | (floppyType << ATA_wSerialDriveFlags_FloppyType_FieldPosition);
325
326    // we always set this, so that the bulk of the BIOS will consider this disk as a hard disk
327    //
328    buff[ ATA_wGenCfg ] = ATA_wGenCfg_FIXED;
329}
330
Note: See TracBrowser for help on using the repository browser.