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

Last change on this file since 599 was 592, checked in by Krister Nordvall, 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
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 }
[592]133 else if( (totallba & 15) != 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.