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

Last change on this file since 327 was 284, checked in by gregli@…, 13 years ago

Increased the width of the drive Model name that the boot menu display, better accomodating serial drives on auto detect which include the COM port and baud rate information.

File size: 8.4 KB
RevLine 
[209]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#include "library.h"
9#include <memory.h>
10#include <stdlib.h>
11#include <string.h>
[219]12#include <stdio.h>
[209]13
[259]14struct floppyInfo floppyInfos[] =
[258]15{
[259]16 { 1, 2949120 / 512, 6, 80, 2, 36 }, // 2.88MB 3.5"
17 { 0, 2867200 / 512, 6, 80, 2, 36 }, // 2.88MB 3.5" (alternate spelling with 2.8)
18 { 0, 2969600 / 512, 6, 80, 2, 36 }, // 2.88MB 3.5" (alternate spelling with 2.9)
19 { 1, 1474560 / 512, 4, 80, 2, 18 }, // 1.44MB 3.5"
20 { 0, 1433600 / 512, 4, 80, 2, 18 }, // 1.44MB 3.5" (alternate spelling with 1.4)
21 { 1, 1228800 / 512, 2, 80, 2, 15 }, // 1.2MB 5.25"
22 { 1, 737280 / 512, 3, 80, 1, 18 }, // 720KB 3.5"
23 { 1, 368640 / 512, 1, 40, 2, 9 }, // 360KB 5.25"
24 { 1, 327680 / 512, 0, 40, 2, 8 }, // 320KB 5.25"
25 { 1, 184320 / 512, 0, 40, 1, 9 }, // 180KB 5.25" single sided
26 { 1, 163840 / 512, 0, 40, 1, 8 }, // 160KB 5.25" single sided
27 { 0, 0, 0, 0, 0, 0 }
[258]28};
29
[259]30struct floppyInfo *FindFloppyInfoBySize( double size )
31{
32 struct floppyInfo *fi;
33
34 for( fi = floppyInfos; fi->size != 0 && !(size+5 > fi->size && size-5 < fi->size); fi++ ) ;
35
36 if( fi->size == 0 )
37 fi = NULL;
38
39 return( fi );
40}
41
[277]42void flipEndian( unsigned short *buff, unsigned int len )
43{
44 for( unsigned int t = 0; t < len/2; t++ )
45 buff[t] = (buff[t] & 0xff) << 8 | (buff[t] & 0xff00) >> 8;
46}
47
[209]48Image::Image( char *name, int p_readOnly, int p_drive )
49{
50}
51
52Image::Image( char *name, int p_readOnly, int p_drive, int p_create, unsigned long p_lba )
53{
54}
55
[217]56Image::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]57{
58}
59
[217]60void 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]61{
[217]62 double sizef;
[258]63 char sizeChar;
64 struct floppyInfo *f;
[217]65
[209]66 for( char *c = shortFileName = name; *c; c++ )
67 if( *c == '\\' || *c == '/' || *c == ':' )
68 shortFileName = c+1;
69
70 if( *(shortFileName) == 0 )
[211]71 {
72 log( 1, "Can't parse '%s' for short file name\n\n", name );
73 shortFileName = "SerDrive";
74 }
[209]75
76 readOnly = p_readOnly;
77 drive = p_drive;
[217]78
79 if( totallba > 0xfffffff ) // lba28 limit - 28 bits
80 log( -1, "'%s', Image size larger than LBA28 maximum of 137,438,952,960 bytes, %lu", name, totallba );
81
82 if( totallba == 0 )
83 log( -1, "'%s', Image size zero?" );
84
[258]85 floppy = 0;
[259]86 for( f = floppyInfos; f->size && !(f->size == totallba && f->real); f++ ) ;
[258]87 if( f->size )
88 {
89 floppy = 1;
90 floppyType = f->type;
91 p_useCHS = 1;
92 p_cyl = f->cylinders;
93 p_head = f->heads;
94 p_sect = f->sectors;
[259]95 totallba = p_cyl * p_head * p_sect;
[258]96 }
97
[217]98 if( p_useCHS )
99 {
100 if( p_cyl )
101 {
102 if( p_sect > 63 || (p_head > 16 || p_head < 1) || (p_cyl > 1024 || p_cyl < 1) )
103 log( -1, "'%s', parts of the CHS geometry (%lu:%lu:%lu) are out of the range (1-1024:1-16:1-63)", name, p_cyl, p_head, p_sect );
104 else if( totallba != (p_sect * p_head * p_cyl) )
105 log( -1, "'%s', file size does not match geometry", name );
106 sect = p_sect;
107 head = p_head;
108 cyl = p_cyl;
109 }
110 else
111 {
112 if( (totallba % 16) != 0 || ((totallba/16) % 63) != 0 )
113 log( -1, "'%s', file size does not match standard CHS geometry (x:16:63), please specify geometry explicitly with -g", name );
114 else
115 {
116 sect = 63;
117 head = 16;
118 cyl = (totallba / sect / head);
119 if( cyl > 1024 )
120 log( -1, "'%s', CHS geometry of %lu:%lu:%lu is larger than maximum values 1024:16:63", name, cyl, head, sect );
121 }
122 }
123 }
124 else
125 {
126 sect = 0;
127 head = 0;
128 cyl = 0;
129 }
130 useCHS = p_useCHS;
131
132 sizef = totallba/2048.0;
[258]133 sizeChar = 'M';
134 if( sizef < 1 )
135 {
136 sizef *= 1024;
137 sizeChar = 'K';
138 }
[217]139 if( useCHS )
[258]140 log( 0, "%s: %s with CHS geometry %u:%u:%u, size %.2lf %cB",
141 name, (floppy ? "Floppy Disk" : "Hard Disk"), cyl, head, sect, sizef, sizeChar );
[217]142 else
[258]143 log( 0, "%s: %s with total sectors %lu, size %.2lf %cB",
144 name, (floppy ? "Floppy Disk" : "Hard Disk"), totallba, sizef, sizeChar );
[209]145}
146
[217]147int Image::parseGeometry( char *str, unsigned long *p_cyl, unsigned long *p_head, unsigned long *p_sect )
[209]148{
149 char *c, *s, *h;
150 unsigned long cyl, sect, head;
151
152 c = str;
[217]153 for( h = c; *h && *h != ':' && *h != 'x' && *h != 'X'; h++ ) ;
154 if( !*h )
155 return( 0 );
156
157 *h = '\0';
158 h++;
159 for( s = h+1; *s && *s != ':' && *s != 'x' && *s != 'X'; s++ ) ;
[209]160 if( !*s )
161 return( 0 );
162
163 *s = '\0';
164 s++;
165
166 cyl = atol(c);
[217]167 head = atol(h);
[209]168 sect = atol(s);
169
170 if( cyl == 0 || sect == 0 || head == 0 )
171 return( 0 );
172
173 *p_cyl = cyl;
[217]174 *p_head = head;
[209]175 *p_sect = sect;
176
177 return( 1 );
178}
179
180#define ATA_wGenCfg 0
181#define ATA_wCylCnt 1
182#define ATA_wHeadCnt 3
183#define ATA_wBpTrck 4
184#define ATA_wBpSect 5
185#define ATA_wSPT 6
[277]186
[209]187#define ATA_strSerial 10
[277]188#define ATA_strSerial_Length 20
189
[209]190#define ATA_strFirmware 23
[277]191#define ATA_strFirmware_Length 8
192
[209]193#define ATA_strModel 27
[284]194#define ATA_strModel_Length 40 // Maximum allowable length of the string according to the ATA spec
195#define XTIDEBIOS_strModel_Length 30 // Maximum length copied out of the ATA information by the BIOS
[277]196
[209]197#define ATA_wCaps 49
198#define ATA_wCurCyls 54
199#define ATA_wCurHeads 55
200#define ATA_wCurSPT 56
201#define ATA_dwCurSCnt 57
202#define ATA_dwLBACnt 60
203
[258]204// Words carved out of the vendor specific area for our use
205//
[277]206#define ATA_wSerialServerVersion 157
[258]207#define ATA_wSerialFloppyFlagAndType 158
208#define ATA_wSerialPortAndBaud 159
[209]209
[258]210// Defines used in the words above
211//
[209]212#define ATA_wCaps_LBA 0x200
213
214#define ATA_wGenCfg_FIXED 0x40
215
[258]216#define ATA_wSerialFloppyFlagAndType_Flag 0x10
217#define ATA_wSerialFloppyFlagAndType_TypePosition 5
218
[209]219struct comPorts {
220 unsigned long port;
221 unsigned char com;
222};
223struct comPorts supportedComPorts[] =
224{
225 { 0x3f8, '1' },
226 { 0x2f8, '2' },
227 { 0x3e8, '3' },
228 { 0x2e8, '4' },
229 { 0x2f0, '5' },
230 { 0x3e0, '6' },
231 { 0x2e0, '7' },
232 { 0x260, '8' },
233 { 0x368, '9' },
234 { 0x268, 'A' },
235 { 0x360, 'B' },
236 { 0x270, 'C' },
237 { 0, 0 }
238};
239
[277]240void Image::respondInquire( unsigned short *buff, unsigned short originalPortAndBaud, struct baudRate *baudRate, unsigned short port, unsigned char scan )
[209]241{
[277]242 char formatBuff[ 128 ];
[284]243 char speedBuff[ 128 ];
[277]244
[233]245 memset( &buff[0], 0, 514 );
[209]246
[233]247 if( scan )
[209]248 {
[233]249 unsigned short comPort = 0;
250 struct comPorts *cp;
251
252 if( port )
253 {
254 for( cp = supportedComPorts; cp->port && cp->port != port; cp++ ) ;
255 if( cp->port )
256 comPort = cp->com;
257 }
258
259 if( comPort )
[284]260 sprintf( speedBuff, " (COM%c/%s)", comPort, baudRate->display );
[233]261 else
[284]262 sprintf( speedBuff, " (%s baud)", shortFileName, baudRate->display );
263
264 sprintf( formatBuff, "%.*s%s ", XTIDEBIOS_strModel_Length - strlen(speedBuff), shortFileName, speedBuff );
[209]265 }
266 else
[284]267 sprintf( formatBuff, "%.*s ", XTIDEBIOS_strModel_Length, shortFileName );
[277]268 strncpy( (char *) &buff[ATA_strModel], formatBuff, ATA_strModel_Length );
269 flipEndian( &buff[ATA_strModel], ATA_strModel_Length );
[209]270
[277]271 strncpy( (char *) &buff[ATA_strSerial], "SerialDrive ", ATA_strSerial_Length );
272 flipEndian( &buff[ATA_strSerial], ATA_strSerial_Length );
[209]273
[277]274 sprintf( formatBuff, "%d.%d ", SERIAL_SERVER_MAJORVERSION, SERIAL_SERVER_MINORVERSION );
275 strncpy( (char *) &buff[ATA_strFirmware], formatBuff, ATA_strFirmware_Length );
276 flipEndian( &buff[ATA_strFirmware], ATA_strFirmware_Length );
[209]277
[217]278 if( useCHS )
279 {
280 buff[ ATA_wCylCnt ] = cyl;
281 buff[ ATA_wHeadCnt ] = head;
282 buff[ ATA_wSPT ] = sect;
283 }
284 else
285 {
286 buff[ ATA_wCaps ] = ATA_wCaps_LBA;
287 buff[ ATA_dwLBACnt ] = (unsigned short) (totallba & 0xffff);
288 buff[ ATA_dwLBACnt+1 ] = (unsigned short) (totallba >> 16);
289 }
290
[277]291 // We echo back the port and baud that we were called on from the client,
292 // the client then uses this value to finalize the DPT.
293 //
294 buff[ ATA_wSerialPortAndBaud ] = originalPortAndBaud;
295
296 // In case the client requires a specific server version...
297 //
298 buff[ ATA_wSerialServerVersion ] = (SERIAL_SERVER_MAJORVERSION << 8) | SERIAL_SERVER_MINORVERSION;
299
[258]300 if( floppy )
[277]301 buff[ ATA_wSerialFloppyFlagAndType ] =
302 ATA_wSerialFloppyFlagAndType_Flag | (floppyType << ATA_wSerialFloppyFlagAndType_TypePosition);
[258]303
304 // we always set this, so that the bulk of the BIOS will consider this disk as a hard disk
305 //
[209]306 buff[ ATA_wGenCfg ] = ATA_wGenCfg_FIXED;
307}
[284]308
Note: See TracBrowser for help on using the repository browser.