ack/plat/cpm/libsys/write.c

126 lines
2.1 KiB
C
Raw Normal View History

2007-04-27 22:42:41 +00:00
/* $Source$
* $State$
* $Revision$
*/
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
2007-04-27 22:42:41 +00:00
#include <cpm.h>
#include "cpmsys.h"
2007-04-27 22:42:41 +00:00
void _sys_write_tty(char c)
{
cpm_conout(c);
2007-04-27 22:42:41 +00:00
if (c == '\n')
cpm_conout(c);
2007-04-27 22:42:41 +00:00
}
ssize_t write(int fd, void* buffer, size_t count)
2007-04-27 22:42:41 +00:00
{
const uint8_t* bbuffer = buffer;
struct FCBE* fcbe = &__fd[fd];
uint8_t olduser;
uint16_t result;
uint8_t* dest;
__init_file_descriptors();
if (fcbe->fcb.dr == 0)
{
/* Write to the console. */
size_t i = count;
while (i--)
_sys_write_tty(*bbuffer++);
return count;
}
olduser = cpm_get_user();
cpm_set_user(fcbe->user);
if (fcbe->offset || !SECTOR_ALIGNED(count))
{
/* We're not at a sector boundary, so we need to do a
* read/modify/write of the initial fragment. */
cpm_set_dma(__transfer_buffer);
if (cpm_read_random_safe(&fcbe->fcb) != 0)
goto eio;
/* Copy enough bytes to reach the end of the sector. */
dest = __transfer_buffer + fcbe->offset;
while ((count != 0) && (fcbe->offset != 128))
{
*dest++ = *bbuffer++;
fcbe->offset++;
count--;
}
/* Write back. */
if (cpm_write_random(&fcbe->fcb) != 0)
goto eio;
/* If we've written enough bytes, advance to the next sector. */
if (fcbe->offset == 128)
{
U16(fcbe->fcb.r)++;
fcbe->offset = 0;
}
}
while (count >= 128)
2007-04-27 22:42:41 +00:00
{
/* Write entire sectors directly from the source buffer. */
cpm_set_dma(bbuffer);
if (cpm_write_random(&fcbe->fcb) != 0)
goto eio;
count -= 128;
bbuffer += 128;
U16(fcbe->fcb.r)++;
2007-04-27 22:42:41 +00:00
}
if (count != 0)
{
/* There's some trailing data to write. We need another
* read/modify/write cycle. */
cpm_set_dma(__transfer_buffer);
if (cpm_read_random_safe(&fcbe->fcb) != 0)
goto eio;
dest = __transfer_buffer;
while (count != 0)
{
*dest++ = *bbuffer++;
count--;
}
if (cpm_write_random(&fcbe->fcb) != 0)
goto eio;
fcbe->offset = count;
}
if (U16(fcbe->fcb.r) >= fcbe->length)
{
fcbe->length = U16(fcbe->fcb.r);
if (fcbe->offset != 0)
fcbe->length++;
}
result = bbuffer - (uint8_t*)buffer;
exit:
cpm_set_user(olduser);
return result;
eio:
errno = EIO;
result = -1;
goto exit;
2007-04-27 22:42:41 +00:00
}