298 |
|
|
299 |
|
|
300 |
|
/* |
301 |
+ |
* Send one I/O request, using 64-bit addressing if the device supports it |
302 |
+ |
*/ |
303 |
+ |
|
304 |
+ |
static loff_t send_io_request(file_handle *fh, bool writing, ULONG length, loff_t offset, APTR data) |
305 |
+ |
{ |
306 |
+ |
if (fh->does_64bit) { |
307 |
+ |
fh->io->io_Command = writing ? NSCMD_TD_WRITE64 : NSCMD_TD_READ64; |
308 |
+ |
fh->io->io_Actual = offset >> 32; |
309 |
+ |
} else { |
310 |
+ |
fh->io->io_Command = writing ? CMD_WRITE : CMD_READ; |
311 |
+ |
fh->io->io_Actual = 0; |
312 |
+ |
} |
313 |
+ |
fh->io->io_Length = length; |
314 |
+ |
fh->io->io_Offset = offset; |
315 |
+ |
fh->io->io_Data = data; |
316 |
+ |
if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != length) |
317 |
+ |
return 0; |
318 |
+ |
return fh->io->io_Actual; |
319 |
+ |
} |
320 |
+ |
|
321 |
+ |
|
322 |
+ |
/* |
323 |
|
* Read "length" bytes from file/device, starting at "offset", to "buffer", |
324 |
|
* returns number of bytes read (or 0) |
325 |
|
*/ |
346 |
|
|
347 |
|
} else { |
348 |
|
|
349 |
< |
// Device, pre-read (partial read of first block) neccessary? |
349 |
> |
// Device, pre-read (partial read of first block) necessary? |
350 |
|
loff_t pos = offset + fh->start_byte; |
351 |
|
size_t actual = 0; |
352 |
|
uint32 pre_offset = pos % fh->block_size; |
353 |
|
if (pre_offset) { |
354 |
|
|
355 |
|
// Yes, read one block |
356 |
< |
fh->io->io_Command = CMD_READ; |
335 |
< |
fh->io->io_Length = fh->block_size; |
336 |
< |
fh->io->io_Offset = pos - pre_offset; |
337 |
< |
fh->io->io_Data = tmp_buf; |
338 |
< |
if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != fh->block_size) |
356 |
> |
if (send_io_request(fh, false, fh->block_size, pos - pre_offset, tmp_buf) == 0) |
357 |
|
return 0; |
358 |
|
|
359 |
|
// Copy data to destination buffer |
374 |
|
|
375 |
|
// Yes, read blocks |
376 |
|
size_t main_length = length & ~(fh->block_size - 1); |
377 |
< |
fh->io->io_Command = CMD_READ; |
360 |
< |
fh->io->io_Length = main_length; |
361 |
< |
fh->io->io_Offset = pos; |
362 |
< |
fh->io->io_Data = buffer; |
363 |
< |
if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != main_length) |
377 |
> |
if (send_io_request(fh, false, main_length, pos, buffer) == 0) |
378 |
|
return 0; |
379 |
|
|
380 |
|
// Adjust data pointers |
384 |
|
actual += main_length; |
385 |
|
} |
386 |
|
|
387 |
< |
// Post-read (partial read of last block) neccessary? |
387 |
> |
// Post-read (partial read of last block) necessary? |
388 |
|
if (length) { |
389 |
|
|
390 |
|
// Yes, read one block |
391 |
< |
fh->io->io_Command = CMD_READ; |
378 |
< |
fh->io->io_Length = fh->block_size; |
379 |
< |
fh->io->io_Offset = pos; |
380 |
< |
fh->io->io_Data = tmp_buf; |
381 |
< |
if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != fh->block_size) |
391 |
> |
if (send_io_request(fh, false, fh->block_size, pos, tmp_buf) == 0) |
392 |
|
return 0; |
393 |
|
|
394 |
|
// Copy data to destination buffer |
415 |
|
// File or device? |
416 |
|
if (fh->is_file) { |
417 |
|
|
418 |
< |
// File, seek to position if neccessary |
418 |
> |
// File, seek to position if necessary |
419 |
|
if (Seek(fh->f, offset + fh->start_byte, OFFSET_BEGINNING) == -1) |
420 |
|
return 0; |
421 |
|
|
428 |
|
|
429 |
|
} else { |
430 |
|
|
431 |
< |
// Device, write data |
432 |
< |
fh->io->io_Command = CMD_WRITE; |
433 |
< |
fh->io->io_Length = length; |
434 |
< |
fh->io->io_Offset = offset + fh->start_byte; |
435 |
< |
fh->io->io_Data = buffer; |
436 |
< |
if (DoIO((struct IORequest *)fh->io)) |
437 |
< |
return 0; |
438 |
< |
else |
439 |
< |
return fh->io->io_Actual; |
431 |
> |
// Device, pre-write (partial write of first block) necessary |
432 |
> |
loff_t pos = offset + fh->start_byte; |
433 |
> |
size_t actual = 0; |
434 |
> |
uint32 pre_offset = pos % fh->block_size; |
435 |
> |
if (pre_offset) { |
436 |
> |
|
437 |
> |
// Yes, read one block |
438 |
> |
if (send_io_request(fh, false, fh->block_size, pos - pre_offset, tmp_buf) == 0) |
439 |
> |
return 0; |
440 |
> |
|
441 |
> |
// Copy data from source buffer |
442 |
> |
size_t pre_length = fh->block_size - pre_offset; |
443 |
> |
if (pre_length > length) |
444 |
> |
pre_length = length; |
445 |
> |
memcpy(tmp_buf + pre_offset, buffer, pre_length); |
446 |
> |
|
447 |
> |
// Write block back |
448 |
> |
if (send_io_request(fh, true, fh->block_size, pos - pre_offset, tmp_buf) == 0) |
449 |
> |
return 0; |
450 |
> |
|
451 |
> |
// Adjust data pointers |
452 |
> |
buffer = (uint8 *)buffer + pre_length; |
453 |
> |
pos += pre_length; |
454 |
> |
length -= pre_length; |
455 |
> |
actual += pre_length; |
456 |
> |
} |
457 |
> |
|
458 |
> |
// Main write (complete writes of middle blocks) possible? |
459 |
> |
if (length >= fh->block_size) { |
460 |
> |
|
461 |
> |
// Yes, write blocks |
462 |
> |
size_t main_length = length & ~(fh->block_size - 1); |
463 |
> |
if (send_io_request(fh, true, main_length, pos, buffer) == 0) |
464 |
> |
return 0; |
465 |
> |
|
466 |
> |
// Adjust data pointers |
467 |
> |
buffer = (uint8 *)buffer + main_length; |
468 |
> |
pos += main_length; |
469 |
> |
length -= main_length; |
470 |
> |
actual += main_length; |
471 |
> |
} |
472 |
> |
|
473 |
> |
// Post-write (partial write of last block) necessary? |
474 |
> |
if (length) { |
475 |
> |
|
476 |
> |
// Yes, read one block |
477 |
> |
if (send_io_request(fh, false, fh->block_size, pos, tmp_buf) == 0) |
478 |
> |
return 0; |
479 |
> |
|
480 |
> |
// Copy data from source buffer |
481 |
> |
memcpy(buffer, tmp_buf, length); |
482 |
> |
|
483 |
> |
// Write block back |
484 |
> |
if (send_io_request(fh, true, fh->block_size, pos, tmp_buf) == 0) |
485 |
> |
return 0; |
486 |
> |
actual += length; |
487 |
> |
} |
488 |
> |
|
489 |
> |
return actual; |
490 |
|
} |
491 |
|
} |
492 |
|
|