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

Last change on this file since 284 was 284, checked in by gregli@…, 12 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
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#include "library.h"
9#include <memory.h>
10#include <stdlib.h>
11#include <string.h>
12#include <stdio.h>
13
14struct floppyInfo floppyInfos[] = 
15{
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 }
28};
29
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
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
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
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 )
57{
58}
59
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 )
61{
62    double sizef;
63    char sizeChar;
64    struct floppyInfo *f;
65
66    for( char *c = shortFileName = name; *c; c++ )
67        if( *c == '\\' || *c == '/' || *c == ':' )
68            shortFileName = c+1;
69
70    if( *(shortFileName) == 0 )
71    {
72        log( 1, "Can't parse '%s' for short file name\n\n", name );
73        shortFileName = "SerDrive";
74    }
75 
76    readOnly = p_readOnly;
77    drive = p_drive;
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
85    floppy = 0;
86    for( f = floppyInfos; f->size && !(f->size == totallba && f->real); f++ ) ;
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;
95        totallba = p_cyl * p_head * p_sect;
96    }
97
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;
133    sizeChar = 'M';
134    if( sizef < 1 ) 
135    {
136        sizef *= 1024;
137        sizeChar = 'K';
138    }
139    if( useCHS )
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 );
142    else
143        log( 0, "%s: %s with total sectors %lu, size %.2lf %cB", 
144             name, (floppy ? "Floppy Disk" : "Hard Disk"), totallba, sizef, sizeChar );
145}
146
147int Image::parseGeometry( char *str, unsigned long *p_cyl, unsigned long *p_head, unsigned long *p_sect )
148{
149    char *c, *s, *h;
150    unsigned long cyl, sect, head;
151
152    c = str;
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++ ) ; 
160    if( !*s )
161        return( 0 );
162
163    *s = '\0';
164    s++;
165
166    cyl = atol(c);
167    head = atol(h);
168    sect = atol(s);
169
170    if( cyl == 0 || sect == 0 || head == 0 )
171        return( 0 );
172
173    *p_cyl = cyl;
174    *p_head = head;
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
186
187#define ATA_strSerial 10
188#define ATA_strSerial_Length 20
189
190#define ATA_strFirmware 23
191#define ATA_strFirmware_Length 8
192
193#define ATA_strModel 27
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
196
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
204// Words carved out of the vendor specific area for our use
205//
206#define ATA_wSerialServerVersion 157
207#define ATA_wSerialFloppyFlagAndType 158
208#define ATA_wSerialPortAndBaud 159
209
210// Defines used in the words above
211//
212#define ATA_wCaps_LBA 0x200
213
214#define ATA_wGenCfg_FIXED 0x40
215
216#define ATA_wSerialFloppyFlagAndType_Flag 0x10
217#define ATA_wSerialFloppyFlagAndType_TypePosition 5
218
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
240void Image::respondInquire( unsigned short *buff, unsigned short originalPortAndBaud, struct baudRate *baudRate, unsigned short port, unsigned char scan )
241{
242    char formatBuff[ 128 ];
243    char speedBuff[ 128 ];
244
245    memset( &buff[0], 0, 514 );
246
247    if( scan )
248    {
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 )
260            sprintf( speedBuff, " (COM%c/%s)", comPort, baudRate->display );
261        else
262            sprintf( speedBuff, " (%s baud)", shortFileName, baudRate->display );
263
264        sprintf( formatBuff, "%.*s%s ", XTIDEBIOS_strModel_Length - strlen(speedBuff), shortFileName, speedBuff );
265    }
266    else
267        sprintf( formatBuff, "%.*s ", XTIDEBIOS_strModel_Length, shortFileName );
268    strncpy( (char *) &buff[ATA_strModel], formatBuff, ATA_strModel_Length );
269    flipEndian( &buff[ATA_strModel], ATA_strModel_Length );
270
271    strncpy( (char *) &buff[ATA_strSerial], "SerialDrive ", ATA_strSerial_Length );
272    flipEndian( &buff[ATA_strSerial], ATA_strSerial_Length );
273
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 );
277
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
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
300    if( floppy )
301        buff[ ATA_wSerialFloppyFlagAndType ] = 
302            ATA_wSerialFloppyFlagAndType_Flag | (floppyType << ATA_wSerialFloppyFlagAndType_TypePosition);
303
304    // we always set this, so that the bulk of the BIOS will consider this disk as a hard disk
305    //
306    buff[ ATA_wGenCfg ] = ATA_wGenCfg_FIXED;
307}
308
Note: See TracBrowser for help on using the repository browser.