Parcourir la source

Refactored to reduce code size; now down from 1304 to 1105 bytes.

Tidied up debug messages; the log now contains one line per INT 13
operation, looking like

 INT 13,08 (80): Get drive parameters
 INT 13,02 (80): Read: C/H/S 0/47/14 = LBA 0xb9e <-> 1084:0000 (count 106)
tags/v0.9.3
Michael Brown il y a 18 ans
Parent
révision
ca2519cea3
1 fichiers modifiés avec 98 ajouts et 120 suppressions
  1. 98
    120
      src/arch/i386/interface/pcbios/int13.c

+ 98
- 120
src/arch/i386/interface/pcbios/int13.c Voir le fichier

@@ -65,112 +65,84 @@ extern void int13_exec_fail ( void );
65 65
 static LIST_HEAD ( drives );
66 66
 
67 67
 /**
68
- * Convert CHS address to linear address
68
+ * INT 13, 00 - Reset disk system
69 69
  *
70 70
  * @v drive		Emulated drive
71
- * @v ch		Low bits of cylinder number
72
- * @v cl (bits 7:6)	High bits of cylinder number
73
- * @v cl (bits 5:0)	Sector number
74
- * @v dh		Head number
75
- * @ret lba		LBA address
76
- * 
71
+ * @ret status		Status code
77 72
  */
78
-static unsigned long chs_to_lba ( struct int13_drive *drive,
79
-				  struct i386_all_regs *ix86 ) {
80
-	unsigned int cylinder;
81
-	unsigned int head;
82
-	unsigned int sector;
83
-	unsigned long lba;
84
-
85
-	cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 8 ) | ix86->regs.ch );
86
-	head = ix86->regs.dh;
87
-	sector = ( ix86->regs.cl & 0x3f );
88
-
89
-	assert ( cylinder < drive->cylinders );
90
-	assert ( head < drive->heads );
91
-	assert ( ( sector >= 1 ) && ( sector <= drive->sectors_per_track ) );
92
-
93
-	lba = ( ( ( ( cylinder * drive->heads ) + head )
94
-		  * drive->sectors_per_track ) + sector - 1 );
95
-
96
-	DBG ( "C/H/S address %x/%x/%x -> LBA %lx\n",
97
-	      cylinder, head, sector, lba );
98
-
99
-	return lba;
73
+static int int13_reset ( struct int13_drive *drive __unused,
74
+			 struct i386_all_regs *ix86 __unused ) {
75
+	DBG ( "Reset drive\n" );
76
+	return 0;
100 77
 }
101 78
 
102 79
 /**
103
- * Read from drive to real-mode data buffer
80
+ * INT 13, 01 - Get status of last operation
104 81
  *
105 82
  * @v drive		Emulated drive
106
- * @v lba		LBA starting sector number
107
- * @v data		Data buffer
108
- * @v count		Number of sectors to read
109 83
  * @ret status		Status code
110 84
  */
111
-static int int13_read ( struct int13_drive *drive, uint64_t lba,
112
-			struct segoff data, unsigned long count ) {
113
-	struct block_device *blockdev = drive->blockdev;
114
-	userptr_t buffer = real_to_user ( data.segment, data.offset );
115
-	int rc;
116
-
117
-	DBG ( "Read %lx sectors from %llx to %04x:%04x\n", count,
118
-	      ( unsigned long long ) lba, data.segment, data.offset );
119
-	
120
-	if ( ( rc = blockdev->read ( blockdev, lba, count, buffer ) ) != 0 )
121
-		return INT13_STATUS_READ_ERROR;
122
-
123
-	return 0;
85
+static int int13_get_last_status ( struct int13_drive *drive,
86
+				   struct i386_all_regs *ix86 __unused ) {
87
+	DBG ( "Get status of last operation\n" );
88
+	return drive->last_status;
124 89
 }
125 90
 
126 91
 /**
127
- * Write from real-mode data buffer to drive
92
+ * Read / write sectors
128 93
  *
129 94
  * @v drive		Emulated drive
130
- * @v lba		LBA starting sector number
131
- * @v data		Data buffer
132
- * @v count		Number of sectors to read
95
+ * @v al		Number of sectors to read or write (must be nonzero)
96
+ * @v ch		Low bits of cylinder number
97
+ * @v cl (bits 7:6)	High bits of cylinder number
98
+ * @v cl (bits 5:0)	Sector number
99
+ * @v dh		Head number
100
+ * @v es:bx		Data buffer
101
+ * @v io		Read / write method
133 102
  * @ret status		Status code
103
+ * @ret al		Number of sectors read or written
134 104
  */
135
-static int int13_write ( struct int13_drive *drive, uint64_t lba,
136
-			 struct segoff data, unsigned long count ) {
105
+static int int13_rw_sectors ( struct int13_drive *drive,
106
+			      struct i386_all_regs *ix86,
107
+			      int ( * io ) ( struct block_device *blockdev,
108
+					     uint64_t block,
109
+					     unsigned long count,
110
+					     userptr_t buffer ) ) {
137 111
 	struct block_device *blockdev = drive->blockdev;
138
-	userptr_t buffer = real_to_user ( data.segment, data.offset );
139
-	int rc;
112
+	unsigned int cylinder, head, sector;
113
+	unsigned long lba;
114
+	unsigned int count;
115
+	userptr_t buffer;
140 116
 
141
-	DBG ( "Write %lx sectors from %04x:%04x to %llx\n", count,
142
-	      data.segment, data.offset, ( unsigned long long ) lba );
117
+	/* Calculate parameters */
118
+	cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 8 ) | ix86->regs.ch );
119
+	assert ( cylinder < drive->cylinders );
120
+	head = ix86->regs.dh;
121
+	assert ( head < drive->heads );
122
+	sector = ( ix86->regs.cl & 0x3f );
123
+	assert ( ( sector >= 1 ) && ( sector <= drive->sectors_per_track ) );
124
+	lba = ( ( ( ( cylinder * drive->heads ) + head )
125
+		  * drive->sectors_per_track ) + sector - 1 );
126
+	count = ix86->regs.al;
127
+	buffer = real_to_user ( ix86->segs.es, ix86->regs.bx );
143 128
 
144
-	if ( ( rc = blockdev->write ( blockdev, lba, count, buffer ) ) != 0 )
145
-		return INT13_STATUS_WRITE_ERROR;
129
+	DBG ( "C/H/S %d/%d/%d = LBA %#lx <-> %04x:%04x (count %d)\n", cylinder,
130
+	      head, sector, lba, ix86->segs.es, ix86->regs.bx, count );
146 131
 
147
-	return 0;
148
-}
132
+	/* Validate blocksize */
133
+	if ( blockdev->blksize != INT13_BLKSIZE ) {
134
+		DBG ( "Invalid blocksize (%zd) for non-extended read/write\n",
135
+		      blockdev->blksize );
136
+		return INT13_STATUS_INVALID;
137
+	}
138
+	
139
+	/* Read from / write to block device */
140
+	if ( io ( blockdev, lba, count, buffer ) != 0 )
141
+		return INT13_STATUS_READ_ERROR;
149 142
 
150
-/**
151
- * INT 13, 00 - Reset disk system
152
- *
153
- * @v drive		Emulated drive
154
- * @ret status		Status code
155
- */
156
-static int int13_reset ( struct int13_drive *drive __unused,
157
-			 struct i386_all_regs *ix86 __unused ) {
158
-	DBG ( "Reset drive\n" );
159 143
 	return 0;
160 144
 }
161 145
 
162
-/**
163
- * INT 13, 01 - Get status of last operation
164
- *
165
- * @v drive		Emulated drive
166
- * @ret status		Status code
167
- */
168
-static int int13_get_last_status ( struct int13_drive *drive,
169
-				   struct i386_all_regs *ix86 __unused ) {
170
-	DBG ( "Get status of last operation\n" );
171
-	return drive->last_status;
172
-}
173
-
174 146
 /**
175 147
  * INT 13, 02 - Read sectors
176 148
  *
@@ -186,20 +158,8 @@ static int int13_get_last_status ( struct int13_drive *drive,
186 158
  */
187 159
 static int int13_read_sectors ( struct int13_drive *drive,
188 160
 				struct i386_all_regs *ix86 ) {
189
-	unsigned long lba = chs_to_lba ( drive, ix86 );
190
-	unsigned int count = ix86->regs.al;
191
-	struct segoff data = {
192
-		.segment = ix86->segs.es,
193
-		.offset = ix86->regs.bx,
194
-	};
195
-
196
-	if ( drive->blockdev->blksize != INT13_BLKSIZE ) {
197
-		DBG ( "Invalid blocksize (%zd) for non-extended read\n",
198
-		      drive->blockdev->blksize );
199
-		return INT13_STATUS_INVALID;
200
-	}
201
-
202
-	return int13_read ( drive, lba, data, count );
161
+	DBG ( "Read: " );
162
+	return int13_rw_sectors ( drive, ix86, drive->blockdev->read );
203 163
 }
204 164
 
205 165
 /**
@@ -217,20 +177,8 @@ static int int13_read_sectors ( struct int13_drive *drive,
217 177
  */
218 178
 static int int13_write_sectors ( struct int13_drive *drive,
219 179
 				 struct i386_all_regs *ix86 ) {
220
-	unsigned long lba = chs_to_lba ( drive, ix86 );
221
-	unsigned int count = ix86->regs.al;
222
-	struct segoff data = {
223
-		.segment = ix86->segs.es,
224
-		.offset = ix86->regs.bx,
225
-	};
226
-
227
-	if ( drive->blockdev->blksize != INT13_BLKSIZE ) {
228
-		DBG ( "Invalid blocksize (%zd) for non-extended write\n",
229
-		      drive->blockdev->blksize );
230
-		return INT13_STATUS_INVALID;
231
-	}
232
-
233
-	return int13_write ( drive, lba, data, count );
180
+	DBG ( "Write: " );
181
+	return int13_rw_sectors ( drive, ix86, drive->blockdev->write );
234 182
 }
235 183
 
236 184
 /**
@@ -280,6 +228,42 @@ static int int13_extension_check ( struct int13_drive *drive __unused,
280 228
 	}
281 229
 }
282 230
 
231
+/**
232
+ * Extended read / write
233
+ *
234
+ * @v drive		Emulated drive
235
+ * @v ds:si		Disk address packet
236
+ * @v io		Read / write method
237
+ * @ret status		Status code
238
+ */
239
+static int int13_extended_rw ( struct int13_drive *drive,
240
+			       struct i386_all_regs *ix86,
241
+			       int ( * io ) ( struct block_device *blockdev,
242
+					      uint64_t block,
243
+					      unsigned long count,
244
+					      userptr_t buffer ) ) {
245
+	struct block_device *blockdev = drive->blockdev;
246
+	struct int13_disk_address addr;
247
+	uint64_t lba;
248
+	unsigned long count;
249
+	userptr_t buffer;
250
+
251
+	/* Read parameters from disk address structure */
252
+	copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si, sizeof ( addr ));
253
+	lba = addr.lba;
254
+	count = addr.count;
255
+	buffer = real_to_user ( addr.buffer.segment, addr.buffer.offset );
256
+
257
+	DBG ( "LBA %#llx <-> %04x:%04x (count %ld)\n", (unsigned long long)lba,
258
+	      addr.buffer.segment, addr.buffer.offset, count );
259
+	
260
+	/* Read from / write to block device */
261
+	if ( io ( blockdev, lba, count, buffer ) != 0 )
262
+		return INT13_STATUS_READ_ERROR;
263
+
264
+	return 0;
265
+}
266
+
283 267
 /**
284 268
  * INT 13, 42 - Extended read
285 269
  *
@@ -289,11 +273,8 @@ static int int13_extension_check ( struct int13_drive *drive __unused,
289 273
  */
290 274
 static int int13_extended_read ( struct int13_drive *drive,
291 275
 				 struct i386_all_regs *ix86 ) {
292
-	struct int13_disk_address addr;
293
-
294
-	copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
295
-			 sizeof ( addr ) );
296
-	return int13_read ( drive, addr.lba, addr.buffer, addr.count );
276
+	DBG ( "Extended read: " );
277
+	return int13_extended_rw ( drive, ix86, drive->blockdev->read );
297 278
 }
298 279
 
299 280
 /**
@@ -305,11 +286,8 @@ static int int13_extended_read ( struct int13_drive *drive,
305 286
  */
306 287
 static int int13_extended_write ( struct int13_drive *drive,
307 288
 				  struct i386_all_regs *ix86 ) {
308
-	struct int13_disk_address addr;
309
-
310
-	copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
311
-			 sizeof ( addr ) );
312
-	return int13_write ( drive, addr.lba, addr.buffer, addr.count );
289
+	DBG ( "Extended write: " );
290
+	return int13_extended_rw ( drive, ix86, drive->blockdev->write );
313 291
 }
314 292
 
315 293
 /**
@@ -351,7 +329,7 @@ static void int13 ( struct i386_all_regs *ix86 ) {
351 329
 		if ( drive->drive != ix86->regs.dl )
352 330
 			continue;
353 331
 		
354
-		DBG ( "INT 13, %02x on drive %02x\n", ix86->regs.ah,
332
+		DBG ( "INT 13,%02x (%02x): ", ix86->regs.ah,
355 333
 		      ix86->regs.dl );
356 334
 	
357 335
 		switch ( ix86->regs.ah ) {

Chargement…
Annuler
Enregistrer