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

Last change on this file since 592 was 592, checked in by krille_n_, 6 years ago

Changes:

  • The problem with NASM in the previous revision (r591) has been fixed.
  • The colors used by the boot menu and hotkey bar can now be customized by selecting one of a number of pre-defined color themes. Suggestions for additional themes are more than welcome!
  • Large builds are now 10 KB. Small builds are still 8 KB with the exception of the Tiny build which is now 4 KB. In other words, builds are now as small as possible to make it easier to combine them with other BIOSes.
  • Added code to the library to improve drive error handling. XTIDECFG can now handle "Drive Not Ready" errors.
  • Fixed a couple of potential bugs in AtaID.asm (AtaID_GetMaxPioModeToAXandMinCycleTimeToCX); 1) ATA1.bPioMode was treated as a WORD variable. 2) ATA2.bPIOSupp was assumed to be non-zero which would result in PIO mode 3 being returned if the assumption was wrong.
  • Made the same changes in the equivalent function used by BIOSDRVS (DisplayPioModeInformationUsingAtaInfoFromDSBX in AtaInfo.asm).
  • Fixed a bug from r587 in PDC20x30.asm in PDC20x30_GetMaxPioModeToALandMinPioCycleTimeToBX.
  • Fixed a bug from r523 in XTIDECFG where Auto Configure would only set the IRQ on one IDE interface on AT-builds.
  • XTIDECFG will now restore the default settings for the "Serial port virtual device" when reselecting it in the list of device types. This makes it behave consistently for all device types.
  • The eAAM macro is now used regardless if USE_UNDOC_INTEL is defined or not because it is apparently supported on all processors including the NEC V20/V30 CPUs.
  • Renamed the EXCLUDE_FROM_XTIDE_UNIVERSAL_BIOS define to EXCLUDE_FROM_XUB.
  • Added a define to exclude unused library code from BIOSDRVS (EXCLUDE_FROM_BIOSDRVS). This makes it a lot smaller than in previous revisions.
  • All unnecessary CLD-instructions are now under a new define 'CLD_NEEDED' which is only enabled for the BIOS. It is disabled for XTIDECFG and BIOSDRVS but can be enabled if needed by adding this define to the respective makefile. This change was made because these unnecessary instructions are wasteful and should never be needed. In fact, they only serve to hide bugs (in other peoples code) which I strongly believe should be avoided. I recommend people making their own BIOSes from source to not use this define as it's extremely unlikely to be needed.
  • Updated the copyright info in SerDrive and changed an URL to point to the new site.
  • Updated the copyright info and version number in BIOSDRVS.
  • Updated the copyright info in XTIDECFG.
  • Optimizations in general.
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 & 15) != 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.