125 lines
		
	
	
	
		
			2.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
	
		
			2.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Source$
 | 
						|
 * $State$
 | 
						|
 * $Revision$
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <errno.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <string.h>
 | 
						|
#include <cpm.h>
 | 
						|
#include "cpmsys.h"
 | 
						|
 | 
						|
void _sys_write_tty(char c)
 | 
						|
{
 | 
						|
	if (c == '\n')
 | 
						|
		cpm_conout('\r');
 | 
						|
	cpm_conout(c);
 | 
						|
}
 | 
						|
 | 
						|
ssize_t write(int fd, void* buffer, size_t count)
 | 
						|
{
 | 
						|
	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)
 | 
						|
	{
 | 
						|
		/* 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)++;
 | 
						|
	}
 | 
						|
 | 
						|
	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;
 | 
						|
}
 |