Index: /trunk/Serial_Server/library/FlatImage.cpp
===================================================================
--- /trunk/Serial_Server/library/FlatImage.cpp	(revision 216)
+++ /trunk/Serial_Server/library/FlatImage.cpp	(revision 217)
@@ -12,7 +12,7 @@
 #include "FlatImage.h"
 
-FlatImage::FlatImage( char *name, int p_readOnly, int p_drive, int p_create, unsigned long p_cyl, unsigned long p_sect, unsigned long p_head )   :   Image( name, p_readOnly, p_drive, p_create, p_cyl, p_sect, p_head )
+FlatImage::FlatImage( 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 )   :   Image( name, p_readOnly, p_drive, p_create, p_cyl, p_head, p_sect, p_useCHS )
 {
-	double sizef;
+	long filesize;
 
 	if( p_create )
@@ -40,5 +40,8 @@
 		
 		sizef = size2/2048.0;
-		log( 0, "Created file '%s' with geometry %u:%u:%u, size %.1lf megabytes\n", name, p_cyl, p_sect, p_head, sizef );
+		if( p_cyl > 1024 )
+			log( 0, "Created file '%s', size %.1lf MB", name, sizef );
+		else
+			log( 0, "Created file '%s', geometry %u:%u:%u, size %.1lf MB", name, p_cyl, p_sect, p_head, sizef );
 	}
 
@@ -48,35 +51,15 @@
 
 	fseek( fp, 0, SEEK_END );
-	totallba = ftell( fp );
+	filesize = ftell( fp );
 
-	if( !totallba )
-		log( -1, "Could not get file size for '%s'", name );
+	if( filesize == 0 || filesize == -1L )
+		log( -1, "Could not get file size for '%s', file possibly larger than 2 GB", name );
 
-	if( totallba & 0x1ff )
+	if( filesize & 0x1ff )
 		log( -1, "'%s' not made up of 512 byte sectors", name );
 
-	totallba >>= 9;
-	if( totallba != (p_sect * p_head * p_cyl) )
-	{
-		if( p_sect || p_head || p_cyl )
-			log( -1, "'%s', file size does not match geometry", name );
-		else if( (totallba % 16) != 0 || ((totallba/16) % 63) != 0 )
-			log( -1, "'%s', file size does not match standard geometry (x:16:63), please geometry explicitly with -g", name );
-		else
-		{
-			sect = 63;
-			head = 16;
-			cyl = (totallba / sect / head);
-		}
-	}
-	else
-	{
-		sect = p_sect;
-		head = p_head;
-		cyl = p_cyl;
-	}
+	totallba = filesize >> 9;     // 512 bytes per sector
 
-	sizef = totallba/2048.0;
-	log( 0, "Opening disk '%s', geometry %u:%u:%u, total size %.1lf MB", name, cyl, sect, head, sizef );
+	init( name, p_readOnly, p_drive, p_cyl, p_head, p_sect, p_useCHS );
 }
 
Index: /trunk/Serial_Server/library/FlatImage.h
===================================================================
--- /trunk/Serial_Server/library/FlatImage.h	(revision 216)
+++ /trunk/Serial_Server/library/FlatImage.h	(revision 217)
@@ -15,5 +15,5 @@
 
 public:
-	FlatImage( char *name, int p_readOnly, int p_drive, int create, unsigned long cyl, unsigned long sect, unsigned long head );
+	FlatImage( char *name, int p_readOnly, int p_drive, int create, unsigned long cyl, unsigned long head, unsigned long sect, int useCHS );
 	~FlatImage();
 
Index: /trunk/Serial_Server/library/Image.cpp
===================================================================
--- /trunk/Serial_Server/library/Image.cpp	(revision 216)
+++ /trunk/Serial_Server/library/Image.cpp	(revision 217)
@@ -13,19 +13,18 @@
 Image::Image( char *name, int p_readOnly, int p_drive )
 {
-	init( name, p_readOnly, p_drive );
 }
 
 Image::Image( char *name, int p_readOnly, int p_drive, int p_create, unsigned long p_lba )
 {
-	init( name, p_readOnly, p_drive );
-}
-
-Image::Image( char *name, int p_readOnly, int p_drive, int p_create, unsigned long p_cyl, unsigned long p_sect, unsigned long p_head )
-{
-	init( name, p_readOnly, p_drive );
-}
-
-void Image::init( char *name, int p_readOnly, int p_drive )
-{
+}
+
+Image::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 )
+{
+}
+
+void 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 )
+{
+	double sizef;
+
 	for( char *c = shortFileName = name; *c; c++ )
 		if( *c == '\\' || *c == '/' || *c == ':' )
@@ -40,7 +39,53 @@
 	readOnly = p_readOnly;
 	drive = p_drive;
-}
-
-int Image::parseGeometry( char *str, unsigned long *p_cyl, unsigned long *p_sect, unsigned long *p_head )
+
+	if( totallba > 0xfffffff )     // lba28 limit - 28 bits
+		log( -1, "'%s', Image size larger than LBA28 maximum of 137,438,952,960 bytes, %lu", name, totallba );
+
+	if( totallba == 0 )
+		log( -1, "'%s', Image size zero?" );
+
+	if( p_useCHS )
+	{
+		if( p_cyl )
+		{
+			if( p_sect > 63 || (p_head > 16 || p_head < 1) || (p_cyl > 1024 || p_cyl < 1) )
+				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 );
+			else if( totallba != (p_sect * p_head * p_cyl) )
+				log( -1, "'%s', file size does not match geometry", name );
+			sect = p_sect;
+			head = p_head;
+			cyl = p_cyl;
+		}
+		else
+		{
+			if( (totallba % 16) != 0 || ((totallba/16) % 63) != 0 )
+				log( -1, "'%s', file size does not match standard CHS geometry (x:16:63), please specify geometry explicitly with -g", name );
+			else
+			{
+				sect = 63;
+				head = 16;
+				cyl = (totallba / sect / head);
+				if( cyl > 1024 )
+					log( -1, "'%s', CHS geometry of %lu:%lu:%lu is larger than maximum values 1024:16:63", name, cyl, head, sect );
+			}
+		}
+	}
+	else
+	{
+		sect = 0;
+		head = 0;
+		cyl = 0;
+	}
+	useCHS = p_useCHS;
+
+	sizef = totallba/2048.0;
+	if( useCHS )
+		log( 0, "Opening '%s', CHS geometry %u:%u:%u, total size %.1lf MB", name, cyl, sect, head, sizef );
+	else
+		log( 0, "Opening '%s', total lba %lu, total size %.1lf MB", name, totallba, sizef );
+}
+
+int Image::parseGeometry( char *str, unsigned long *p_cyl, unsigned long *p_head, unsigned long *p_sect )
 {
 	char *c, *s, *h;
@@ -48,5 +93,11 @@
 
 	c = str;
-	for( s = c; *s && *s != ':' && *s != 'x' && *s != 'X'; s++ ) ;
+	for( h = c; *h && *h != ':' && *h != 'x' && *h != 'X'; h++ ) ;
+	if( !*h )
+		return( 0 );
+
+	*h = '\0';
+	h++;
+	for( s = h+1; *s && *s != ':' && *s != 'x' && *s != 'X'; s++ ) ; 
 	if( !*s )
 		return( 0 );
@@ -54,14 +105,8 @@
 	*s = '\0';
 	s++;
-	for( h = s+1; *h && *h != ':' && *h != 'x' && *h != 'X'; h++ ) ; 
-	if( !*h )
-		return( 0 );
-
-	*h = '\0';
-	h++;
 
 	cyl = atol(c);
+	head = atol(h);
 	sect = atol(s);
-	head = atol(h);
 
 	if( cyl == 0 || sect == 0 || head == 0 )
@@ -69,6 +114,6 @@
 
 	*p_cyl = cyl;
+	*p_head = head;
 	*p_sect = sect;
-	*p_head = head;
 
 	return( 1 );
@@ -145,16 +190,18 @@
 		buff[t] = (buff[t] >> 8) | (buff[t] << 8);
 
-#if 1
-	buff[ ATA_wCylCnt ] = cyl;
-	buff[ ATA_wHeadCnt ] = head;
-	buff[ ATA_wSPT ] = sect;
-#endif
+	if( useCHS )
+	{
+		buff[ ATA_wCylCnt ] = cyl;
+		buff[ ATA_wHeadCnt ] = head;
+		buff[ ATA_wSPT ] = sect;
+	}
+	else
+	{
+		buff[ ATA_wCaps ] = ATA_wCaps_LBA;
+		buff[ ATA_dwLBACnt ] = (unsigned short) (totallba & 0xffff);
+		buff[ ATA_dwLBACnt+1 ] = (unsigned short) (totallba >> 16);
+	}
+
 	buff[ ATA_wGenCfg ] = ATA_wGenCfg_FIXED;
 	//					buff[ ATA_VendorSpecific_ReturnPortBaud ] = retWord;
-#if 0
-	buff[ ATA_wCaps ] = ATA_wCaps_LBA;
-  
-	buff[ ATA_dwLBACnt ] = (unsigned short) (totallba & 0xffff);
-	buff[ ATA_dwLBACnt+1 ] = (unsigned short) (totallba >> 16);
-#endif
-}
+}
Index: /trunk/Serial_Server/library/Library.h
===================================================================
--- /trunk/Serial_Server/library/Library.h	(revision 216)
+++ /trunk/Serial_Server/library/Library.h	(revision 217)
@@ -29,9 +29,10 @@
 	Image( char *name, int p_readOnly, int p_drive );
 	Image( char *name, int p_readOnly, int p_drive, int p_create, unsigned long p_lba );
-	Image( char *name, int p_readOnly, int p_drive, int p_create, unsigned long p_cyl, unsigned long p_sect, unsigned long p_head );
+	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 );
 
 	virtual ~Image() {};
 
 	unsigned long cyl, sect, head;
+	int useCHS;
 
 	unsigned long totallba;
@@ -41,10 +42,9 @@
 	int drive;
 
-	static int parseGeometry( char *str, unsigned long *p_cyl, unsigned long *p_sect, unsigned long *p_head );
+	static int parseGeometry( char *str, unsigned long *p_cyl, unsigned long *p_head, unsigned long *p_sect );
 
 	void respondInquire( unsigned short *buff, struct baudRate *baudRate, unsigned char portAndBaud );
 
-private:
-	void init( char *name, int p_readOnly, int p_drive );
+	void init( char *name, int p_readOnly, int p_drive, unsigned long p_cyl, unsigned long p_head, unsigned long p_sect, int p_useCHS );
 };
 
Index: /trunk/Serial_Server/library/Process.cpp
===================================================================
--- /trunk/Serial_Server/library/Process.cpp	(revision 216)
+++ /trunk/Serial_Server/library/Process.cpp	(revision 217)
@@ -252,5 +252,5 @@
 				workCommand = buff.chs.command & SERIAL_COMMAND_RWMASK;
 
-				if( (workCommand != SERIAL_COMMAND_INQUIRE) && (buff.chs.command & ATA_COMMAND_LBA) )
+				if( (workCommand != SERIAL_COMMAND_INQUIRE) && (buff.chs.driveAndHead & ATA_COMMAND_LBA) )
 				{
 					mylba = ((((unsigned long) buff.lba.bits24) & ATA_COMMAND_HEADMASK) << 24) 
@@ -279,5 +279,5 @@
 							 + SERIAL_INQUIRE_PORTANDBAUD_STARTINGPORT,
 							 baudRateMatchDivisor( buff.inquire.portAndBaud & SERIAL_INQUIRE_PORTANDBAUD_BAUDMASK )->display );
-					else if( buff.chs.command & ATA_COMMAND_LBA )
+					else if( buff.chs.driveAndHead & ATA_COMMAND_LBA )
 						log( 1, "%s %d: LBA=%u, Count=%u", comStr, img == image0 ? 0 : 1,
 							 mylba, workCount );
Index: /trunk/Serial_Server/win32/Win32.cpp
===================================================================
--- /trunk/Serial_Server/win32/Win32.cpp	(revision 216)
+++ /trunk/Serial_Server/win32/Win32.cpp	(revision 217)
@@ -26,25 +26,27 @@
 		"usage: SerDrive [options] imagefile [[slave-options] slave-imagefile]",
 		"",
-		"  -g cyl:sect:head  Geometry in cylinders, sectors per cylinder, and heads",
-		"                    (default is 65:63:16 for a 32 MB disk)",
-		"",
-		"  -n [megabytes]    Create new disk with given size or use -g geometry",
-		"",
-		"  -p                Named Pipe mode for emulators (pipe is '" PIPENAME "')",
-		"",
-		"  -c COMPortNumber  COM Port to use (default is first found)",
-		"",
-		"  -b BaudRate       Baud rate to use on the COM port ",
-		"                    Without a rate multiplier: 2400, 9600, 38400, 115200",
-		"                    With a 2x rate multiplier: 4800, 19200, 76800, 230400",
-		"                    With a 4x rate multiplier: 9600, 38400, 153600, 460800",
-		"                    Abbreviations also accepted (ie, '460K', '38.4K', etc)",
-		"                    (default is 38400, 115200 in named pipe mode)",
-		"",
-		"  -t                Disable timeout, useful for long delays when debugging",
-		"",
-		"  -r                Read Only disk, do not allow writes",
-		"",
-		"  -v [level]        Reporting level 1-6, with increasing information",
+		"  -g [cyl:head:sect]  Geometry in cylinders, sectors per cylinder, and heads",
+		"                      -g without parameters uses CHS mode (default is LBA28)",
+		"",
+		"  -n [megabytes]      Create new disk with given size or use -g geometry",
+		"                      Maximum size is 137.4 GB (LBA28 limit)",
+		"                      (default is a 32 MB disk, with CHS geometry 65:63:16)",
+		"",
+		"  -p                  Named Pipe mode for emulators (pipe is '" PIPENAME "')",
+		"",
+		"  -c COMPortNumber    COM Port to use (default is first found)",
+		"",
+		"  -b BaudRate         Baud rate to use on the COM port ",
+		"                      Without a rate multiplier: 2400, 9600, 38400, 115200",
+		"                      With a 2x rate multiplier: 4800, 19200, 76800, 230400",
+		"                      With a 4x rate multiplier: 9600, 38400, 153600, 460800",
+		"                      Abbreviations also accepted (ie, '460K', '38.4K', etc)",
+		"                      (default is 38400, 115200 in named pipe mode)",
+		"",
+		"  -t                  Disable timeout, useful for long delays when debugging",
+		"",
+		"  -r                  Read Only disk, do not allow writes",
+		"",
+		"  -v [level]          Reporting level 1-6, with increasing information",
 		"",
 		"On the client computer, a serial port can be configured for use as a hard disk",
@@ -83,5 +85,6 @@
 
 	unsigned long cyl = 0, sect = 0, head = 0;
-	int readOnly = 0, createFile = 0, explicitGeometry = 0;
+	int readOnly = 0, createFile = 0;
+	int useCHS = 0;
 
 	int imagecount = 0;
@@ -122,7 +125,10 @@
 				break;			  
 			case 'g': case 'G':
-				if( !Image::parseGeometry( argv[++t], &cyl, &sect, &head ) )
-					usage();
-				explicitGeometry = 1;
+				if( atol(argv[t+1]) != 0 )
+				{
+					if( !Image::parseGeometry( argv[++t], &cyl, &head, &sect ) )
+						usage();
+				}
+				useCHS = 1;
 				break;
 			case 'h': case 'H': case '?':
@@ -137,5 +143,4 @@
 					head = 16;
 					cyl = (size*1024*2) / (16*63);
-					explicitGeometry = 1;
 				}
 				break;
@@ -157,7 +162,7 @@
 		else if( imagecount < 2 )
 		{
-			images[imagecount] = new FlatImage( argv[t], readOnly, imagecount, createFile, cyl, sect, head );
+			images[imagecount] = new FlatImage( argv[t], readOnly, imagecount, createFile, cyl, head, sect, useCHS );
 			imagecount++;
-			createFile = readOnly = cyl = sect = head = 0;
+			createFile = readOnly = cyl = sect = head = useCHS = 0;
 		}
 		else
