Browse Source

Fix bug with >256 cylinders.

Allow our functions to return a non-zero, non-error status (since the
INT 13 Extensions Check has to return the API version in the register
that is otherwise always used for the error code).

Report a non-zero API version from the INT 13 Extensions Check; GRUB
now uses extended reads.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
17eea9f933
1 changed files with 18 additions and 15 deletions
  1. 18
    15
      src/arch/i386/interface/pcbios/int13.c

+ 18
- 15
src/arch/i386/interface/pcbios/int13.c View File

@@ -115,7 +115,7 @@ static int int13_rw_sectors ( struct int13_drive *drive,
115 115
 	userptr_t buffer;
116 116
 
117 117
 	/* Calculate parameters */
118
-	cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 8 ) | ix86->regs.ch );
118
+	cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 2 ) | ix86->regs.ch );
119 119
 	assert ( cylinder < drive->cylinders );
120 120
 	head = ix86->regs.dh;
121 121
 	assert ( head < drive->heads );
@@ -133,12 +133,12 @@ static int int13_rw_sectors ( struct int13_drive *drive,
133 133
 	if ( blockdev->blksize != INT13_BLKSIZE ) {
134 134
 		DBG ( "Invalid blocksize (%zd) for non-extended read/write\n",
135 135
 		      blockdev->blksize );
136
-		return INT13_STATUS_INVALID;
136
+		return -INT13_STATUS_INVALID;
137 137
 	}
138 138
 	
139 139
 	/* Read from / write to block device */
140 140
 	if ( io ( blockdev, lba, count, buffer ) != 0 )
141
-		return INT13_STATUS_READ_ERROR;
141
+		return -INT13_STATUS_READ_ERROR;
142 142
 
143 143
 	return 0;
144 144
 }
@@ -214,7 +214,7 @@ static int int13_get_parameters ( struct int13_drive *drive,
214 214
  * @v bx		0x55aa
215 215
  * @ret bx		0xaa55
216 216
  * @ret cx		Extensions API support bitmap
217
- * @ret status		Status code
217
+ * @ret status		Status code / API version
218 218
  */
219 219
 static int int13_extension_check ( struct int13_drive *drive __unused,
220 220
 				   struct i386_all_regs *ix86 ) {
@@ -222,9 +222,9 @@ static int int13_extension_check ( struct int13_drive *drive __unused,
222 222
 		DBG ( "INT 13 extensions installation check\n" );
223 223
 		ix86->regs.bx = 0xaa55;
224 224
 		ix86->regs.cx = INT13_EXTENSION_LINEAR;
225
-		return 0;
225
+		return INT13_EXTENSION_VER_1_X;
226 226
 	} else {
227
-		return INT13_STATUS_INVALID;
227
+		return -INT13_STATUS_INVALID;
228 228
 	}
229 229
 }
230 230
 
@@ -259,7 +259,7 @@ static int int13_extended_rw ( struct int13_drive *drive,
259 259
 	
260 260
 	/* Read from / write to block device */
261 261
 	if ( io ( blockdev, lba, count, buffer ) != 0 )
262
-		return INT13_STATUS_READ_ERROR;
262
+		return -INT13_STATUS_READ_ERROR;
263 263
 
264 264
 	return 0;
265 265
 }
@@ -322,6 +322,7 @@ static int int13_get_extended_parameters ( struct int13_drive *drive,
322 322
  *
323 323
  */
324 324
 static void int13 ( struct i386_all_regs *ix86 ) {
325
+	int command = ix86->regs.ah;
325 326
 	struct int13_drive *drive;
326 327
 	int status;
327 328
 
@@ -329,10 +330,9 @@ static void int13 ( struct i386_all_regs *ix86 ) {
329 330
 		if ( drive->drive != ix86->regs.dl )
330 331
 			continue;
331 332
 		
332
-		DBG ( "INT 13,%02x (%02x): ", ix86->regs.ah,
333
-		      ix86->regs.dl );
334
-	
335
-		switch ( ix86->regs.ah ) {
333
+		DBG ( "INT 13,%02x (%02x): ", command, drive->drive );
334
+
335
+		switch ( command ) {
336 336
 		case INT13_RESET:
337 337
 			status = int13_reset ( drive, ix86 );
338 338
 			break;
@@ -362,18 +362,21 @@ static void int13 ( struct i386_all_regs *ix86 ) {
362 362
 			break;
363 363
 		default:
364 364
 			DBG ( "Unrecognised INT 13\n" );
365
-			status = INT13_STATUS_INVALID;
365
+			status = -INT13_STATUS_INVALID;
366 366
 			break;
367 367
 		}
368 368
 
369 369
 		/* Store status for INT 13,01 */
370 370
 		drive->last_status = status;
371
-		/* All functions return status via %ah and CF */
372
-		ix86->regs.ah = status;
373
-		if ( status ) {
371
+
372
+		/* Negative status indicates an error */
373
+		if ( status < 0 ) {
374 374
 			ix86->flags |= CF;
375
+			status = -status;
375 376
 			DBG ( "INT13 failed with status %x\n", status );
376 377
 		}
378
+		ix86->regs.ah = status;
379
+
377 380
 		/* Set OF to indicate to wrapper not to chain this call */
378 381
 		ix86->flags |= OF;
379 382
 	}

Loading…
Cancel
Save