device: add base abstraction for all devices
This commit is contained in:
parent
56c76d8b4b
commit
256b49b529
14 changed files with 221 additions and 85 deletions
|
@ -16,20 +16,20 @@
|
|||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct arch_serial_interface arch_serial_default_interface = {
|
||||
struct arch_serial_device arch_serial_default_device = {
|
||||
.tx_current = NULL,
|
||||
.tx_next = NULL,
|
||||
.interface = {
|
||||
.device = {
|
||||
.rx = NULL,
|
||||
.id = 0,
|
||||
.baud = 0,
|
||||
},
|
||||
};
|
||||
struct serial_interface *serial_default_interface = &arch_serial_default_interface.interface;
|
||||
struct serial_device *serial_default_device = &arch_serial_default_device.device;
|
||||
|
||||
int arch_serial_init(struct serial_interface *interface)
|
||||
int arch_serial_init(struct serial_device *dev)
|
||||
{
|
||||
if (interface->baud <= 0 || interface->id != 0)
|
||||
if (dev->baud <= 0 || dev->id != 0)
|
||||
return -1;
|
||||
|
||||
/* enable peripheral clock for UART (which has peripheral id 8) */
|
||||
|
@ -49,7 +49,7 @@ int arch_serial_init(struct serial_interface *interface)
|
|||
REG_UART_MR = REG_UART_MR_PAR_NO | REG_UART_MR_CHMODE_NORMAL;
|
||||
|
||||
/* From Atmel Datasheet: baud rate = MCK / (REG_UART_BRGR * 16) */
|
||||
REG_UART_BRGR = (uint16_t)(( sys_core_clock / (uint32_t)interface->baud ) >> 4);
|
||||
REG_UART_BRGR = (uint16_t)(( sys_core_clock / (uint32_t)dev->baud ) >> 4);
|
||||
|
||||
/* choose the events we want an interrupt on */
|
||||
REG_UART_IDR = 0xFFFFFFFF; /* make sure all interrupts are disabled first */
|
||||
|
@ -65,9 +65,9 @@ int arch_serial_init(struct serial_interface *interface)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void arch_serial_exit(struct serial_interface *interface)
|
||||
void arch_serial_exit(struct serial_device *dev)
|
||||
{
|
||||
if (interface->id != 0)
|
||||
if (dev->id != 0)
|
||||
return;
|
||||
|
||||
/* disable receiver and transmitter */
|
||||
|
@ -78,15 +78,15 @@ void arch_serial_exit(struct serial_interface *interface)
|
|||
/* disable peripheral clock for UART (PID is taken from Atmel Datasheet, Section 9.1 */
|
||||
REG_PMC_PCDR0 = REG_PMC_PCDR0_PID(8);
|
||||
|
||||
interface->id = -1;
|
||||
dev->id = -1;
|
||||
}
|
||||
|
||||
ssize_t arch_serial_write(struct serial_interface *interface, const void *buf, size_t len)
|
||||
ssize_t arch_serial_write(struct serial_device *dev, const void *buf, size_t len)
|
||||
{
|
||||
struct arch_serial_buffer *arch_buf = NULL;
|
||||
struct arch_serial_interface *arch_iface = to_arch_serial_interface(interface);
|
||||
struct arch_serial_device *arch_dev = to_arch_serial_device(dev);
|
||||
|
||||
if (arch_iface->tx_next != NULL)
|
||||
if (arch_dev->tx_next != NULL)
|
||||
return -EBUSY;
|
||||
|
||||
if (len >= (1 << 16)) /* DMA uses 16-bit counters */
|
||||
|
@ -99,14 +99,14 @@ ssize_t arch_serial_write(struct serial_interface *interface, const void *buf, s
|
|||
memcpy(&arch_buf->data[0], buf, len);
|
||||
arch_buf->len = (uint16_t)len;
|
||||
|
||||
if (arch_iface->tx_current == NULL) {
|
||||
arch_iface->tx_current = arch_buf;
|
||||
if (arch_dev->tx_current == NULL) {
|
||||
arch_dev->tx_current = arch_buf;
|
||||
REG_UART_PDC_TPR = (uint32_t)&arch_buf->data[0];
|
||||
REG_UART_PDC_TCR = arch_buf->len;
|
||||
/* we weren't transmitting, so the interrupt was masked */
|
||||
REG_UART_IER = REG_UART_IER_ENDTX_MASK;
|
||||
} else {
|
||||
arch_iface->tx_next = arch_buf;
|
||||
arch_dev->tx_next = arch_buf;
|
||||
REG_UART_PDC_TNPR = (uint32_t)&arch_buf->data[0];
|
||||
REG_UART_PDC_TNCR = arch_buf->len;
|
||||
}
|
||||
|
@ -122,19 +122,19 @@ void irq_uart(void)
|
|||
/* RX has received a byte, store it into the ring buffer */
|
||||
if (state & REG_UART_SR_RXRDY_MASK) {
|
||||
tmp = REG_UART_RHR;
|
||||
ringbuf_write(arch_serial_default_interface.interface.rx, &tmp, sizeof(tmp));
|
||||
ringbuf_write(arch_serial_default_device.device.rx, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
/* REG_UART_PDC_TCR has reached zero */
|
||||
if (state & REG_UART_SR_ENDTX_MASK) {
|
||||
/* this might be NULL but that's ok because free() tolerates that */
|
||||
free(arch_serial_default_interface.tx_current);
|
||||
free(arch_serial_default_device.tx_current);
|
||||
|
||||
/* DMA automatically does this to the actual hardware registers */
|
||||
arch_serial_default_interface.tx_current = arch_serial_default_interface.tx_next;
|
||||
arch_serial_default_interface.tx_next = NULL;
|
||||
arch_serial_default_device.tx_current = arch_serial_default_device.tx_next;
|
||||
arch_serial_default_device.tx_next = NULL;
|
||||
|
||||
if (arch_serial_default_interface.tx_current == NULL)
|
||||
if (arch_serial_default_device.tx_current == NULL)
|
||||
REG_UART_IDR = REG_UART_IDR_ENDTX_MASK;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,23 +18,23 @@ struct arch_serial_buffer {
|
|||
uint8_t data[];
|
||||
};
|
||||
|
||||
/** Architecture-specific extension of `struct serial_interface` */
|
||||
struct arch_serial_interface {
|
||||
/** Architecture-specific extension of `struct serial_device` */
|
||||
struct arch_serial_device {
|
||||
/** should always match REG_UART_PDC_TPR */
|
||||
struct arch_serial_buffer *tx_current;
|
||||
/** should always match REG_UART_PDC_TNPR */
|
||||
struct arch_serial_buffer *tx_next;
|
||||
|
||||
struct serial_interface interface;
|
||||
struct serial_device device;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast a `struct serial_interface` out to a `struct arch_serial_interface`.
|
||||
* Cast a `struct serial_device` out to a `struct arch_serialdevice`.
|
||||
*
|
||||
* @param ptr: The `struct serial_interface *` to cast out from.
|
||||
* @returns The containing `struct arch_serial_interface *`.
|
||||
* @param ptr: The `struct serial_device *` to cast out from.
|
||||
* @returns The containing `struct arch_serialdevice *`.
|
||||
*/
|
||||
#define to_arch_serial_interface(ptr) container_of(ptr, struct arch_serial_interface, interface)
|
||||
#define to_arch_serial_device(ptr) container_of(ptr, struct arch_serial_device, device)
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Felix Kopp <sandtler@sandtler.club>
|
||||
|
|
|
@ -7,19 +7,19 @@
|
|||
|
||||
#include <ardix/serial.h>
|
||||
|
||||
int arch_serial_init(struct serial_interface *interface);
|
||||
void arch_serial_exit(struct serial_interface *interface);
|
||||
int arch_serial_init(struct serial_device *dev);
|
||||
void arch_serial_exit(struct serial_device *dev);
|
||||
|
||||
/**
|
||||
* Copy `buf` to a hardware buffer in the TX queue.
|
||||
* The transmission is performed asynchronously.
|
||||
*
|
||||
* @param interface: serial interface to enqueue the buffer for
|
||||
* @param dev: serial device to enqueue the buffer for
|
||||
* @param buf: raw buffer data
|
||||
* @param len: length of `buf`
|
||||
* @returns actual amount of bytes enqueued, or a negative error code on failure
|
||||
*/
|
||||
ssize_t arch_serial_write(struct serial_interface *interface, const void *buf, size_t len);
|
||||
ssize_t arch_serial_write(struct serial_device *dev, const void *buf, size_t len);
|
||||
|
||||
#include ARCH_INCLUDE(serial.h)
|
||||
|
||||
|
|
70
include/ardix/device.h
Normal file
70
include/ardix/device.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/* See the end of this file for copyright, licensing, and warranty information. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ardix/kent.h>
|
||||
#include <ardix/list.h>
|
||||
#include <ardix/malloc.h>
|
||||
#include <ardix/types.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/** Top-level abstraction for any device connected to the system. */
|
||||
struct device {
|
||||
struct kent kent;
|
||||
};
|
||||
|
||||
/** Cast a kent out to its containing struct device */
|
||||
#define to_device(ptr) container_of(ptr, struct device, kent)
|
||||
|
||||
extern struct kent *devices_kent;
|
||||
|
||||
/** Initialize the devices subsystem. */
|
||||
int devices_init(void);
|
||||
|
||||
/**
|
||||
* Initialize a device and add it to the device tree.
|
||||
*
|
||||
* @param dev: device to initialze
|
||||
* @param parent: parent device (may me `NULL` if unapplicable)
|
||||
* @returns 0 on success, or a negative error code on failure
|
||||
*/
|
||||
int device_init(struct device *dev, struct device *parent);
|
||||
|
||||
/** Increment a device's reference counter. */
|
||||
inline void device_get(struct device *dev)
|
||||
{
|
||||
kent_get(&dev->kent);
|
||||
}
|
||||
|
||||
/** Decrement a device's referece counter. */
|
||||
inline void device_put(struct device *dev)
|
||||
{
|
||||
kent_put(&dev->kent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (c) 2021 Felix Kopp <sandtler@sandtler.club>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <ardix/device.h>
|
||||
#include <ardix/types.h>
|
||||
#include <ardix/ringbuf.h>
|
||||
|
||||
|
@ -18,50 +19,47 @@
|
|||
#define SERIAL_BUFSZ 256
|
||||
#endif
|
||||
|
||||
struct serial_interface {
|
||||
struct serial_device {
|
||||
struct device device;
|
||||
struct ringbuf *rx;
|
||||
long int baud;
|
||||
int id;
|
||||
};
|
||||
|
||||
/** The default serial console (this is where printk outputs to) */
|
||||
extern struct serial_interface *serial_default_interface;
|
||||
extern struct serial_device *serial_default_device;
|
||||
|
||||
/**
|
||||
* Initialize a serial interface.
|
||||
* Initialize a serial device.
|
||||
*
|
||||
* @param interface: The serial interface.
|
||||
* @param baud: The baud rate (bits/second).
|
||||
* @param dev: serial device
|
||||
* @param baud: baud rate (bits/sec)
|
||||
* @returns 0 on success, a negative number otherwise.
|
||||
*/
|
||||
int serial_init(struct serial_interface *interface, long int baud);
|
||||
int serial_init(struct serial_device *dev, long int baud);
|
||||
|
||||
/**
|
||||
* Flush all buffers (if possible) and close the serial interface.
|
||||
*
|
||||
* @param interface: The serial interface.
|
||||
*/
|
||||
void serial_exit(struct serial_interface *interface);
|
||||
/** Flush all buffers (if possible) and close the serial device. */
|
||||
void serial_exit(struct serial_device *dev);
|
||||
|
||||
/**
|
||||
* Read from the serial buffer.
|
||||
*
|
||||
* @param dest: Where to store the received data.
|
||||
* @param interface: The serial interface to read data from.
|
||||
* @param len: The maximum amount of bytes to read.
|
||||
* @returns The actual amount of bytes read.
|
||||
* @param dest: where to write received data
|
||||
* @param dev: serial device to read from
|
||||
* @param len: amount of bytes to read
|
||||
* @returns actual amount of bytes read
|
||||
*/
|
||||
ssize_t serial_read(void *dest, struct serial_interface *interface, size_t len);
|
||||
ssize_t serial_read(void *dest, struct serial_device *dev, size_t len);
|
||||
|
||||
/**
|
||||
* Write data to the serial buffer.
|
||||
*
|
||||
* @param interface: The serial interface to write data to.
|
||||
* @param data: The data to write.
|
||||
* @param len: The length of `data`.
|
||||
* @returns The actual amount of bytes written.
|
||||
* @param dev: serial device to write to
|
||||
* @param data: where to read data from
|
||||
* @param len: amount of bytes to write
|
||||
* @returns actual amount of bytes written
|
||||
*/
|
||||
ssize_t serial_write(struct serial_interface *interface, const void *data, size_t len);
|
||||
ssize_t serial_write(struct serial_device *dev, const void *data, size_t len);
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Felix Kopp <sandtler@sandtler.club>
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
/**
|
||||
* Cast a pointer to a member of a struct out to the containing structure.
|
||||
*
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
#include <ardix/io.h>
|
||||
#include <ardix/printk.h>
|
||||
#include <ardix/sched.h>
|
||||
#include <ardix/serial.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define REG_PIOB_PER (*(uint32_t *)0x400E1000U)
|
||||
#define REG_PIOB_PDR (*(uint32_t *)0x400E1004U)
|
||||
|
@ -34,9 +34,12 @@ void do_bootstrap(void)
|
|||
REG_PIOB_CODR = 1 << 27;
|
||||
|
||||
sched_init();
|
||||
|
||||
devices_init();
|
||||
|
||||
io_init();
|
||||
|
||||
printk("hello, world\n");
|
||||
write(1, "hello, world\n", 13);
|
||||
|
||||
while (true) {
|
||||
if (count++ != 1000000)
|
||||
|
@ -47,7 +50,6 @@ void do_bootstrap(void)
|
|||
REG_PIOB_CODR = 1 << 27;
|
||||
else
|
||||
REG_PIOB_SODR = 1 << 27;
|
||||
printk("endless loop iteration #%u\n", print_count);
|
||||
|
||||
count = 0;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ include $(ARDIX_KERNEL_PWD)/fs/Makefile
|
|||
include $(ARDIX_KERNEL_PWD)/io/Makefile
|
||||
|
||||
ARDIX_SOURCES += \
|
||||
$(ARDIX_KERNEL_PWD)/device.c \
|
||||
$(ARDIX_KERNEL_PWD)/kent.c \
|
||||
$(ARDIX_KERNEL_PWD)/printk.c \
|
||||
$(ARDIX_KERNEL_PWD)/ringbuf.c \
|
||||
|
|
59
kernel/device.c
Normal file
59
kernel/device.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/* See the end of this file for copyright, licensing, and warranty information. */
|
||||
|
||||
#include <ardix/device.h>
|
||||
#include <ardix/kent.h>
|
||||
#include <ardix/list.h>
|
||||
#include <ardix/malloc.h>
|
||||
#include <ardix/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct kent *devices_kent = NULL;
|
||||
|
||||
/** Initialize the devices subsystem. */
|
||||
int devices_init(void)
|
||||
{
|
||||
if (devices_kent != NULL)
|
||||
return -EEXIST;
|
||||
|
||||
devices_kent = malloc(sizeof(*devices_kent));
|
||||
if (devices_kent == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
return kent_init(NULL, devices_kent);
|
||||
}
|
||||
|
||||
int device_init(struct device *dev, struct device *parent)
|
||||
{
|
||||
if (devices_kent == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
return kent_init(devices_kent, &dev->kent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (c) 2021 Felix Kopp <sandtler@sandtler.club>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
|
@ -22,7 +22,7 @@ ssize_t sys_read(int fd, __user void *buf, size_t len)
|
|||
if (copy == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = serial_read(copy, serial_default_interface, len);
|
||||
ret = serial_read(copy, serial_default_device, len);
|
||||
if (ret > 0)
|
||||
copy_to_user(buf, copy, (size_t)ret);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ ssize_t sys_write(int fd, __user const void *buf, size_t len)
|
|||
ret = (ssize_t)copy_from_user(copy, buf, len);
|
||||
|
||||
/* TODO: reschedule if blocking */
|
||||
ret = serial_write(serial_default_interface, copy, (size_t)ret);
|
||||
ret = serial_write(serial_default_device, copy, (size_t)ret);
|
||||
|
||||
free(copy);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ int io_init(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = serial_init(serial_default_interface, CONFIG_SERIAL_BAUD);
|
||||
ret = serial_init(serial_default_device, CONFIG_SERIAL_BAUD);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
* TODO: THIS CAUSES A STACK BUFFER OVERFLOW ON SYSTEMS WHERE INT IS 64 BITS
|
||||
*/
|
||||
|
||||
/* 10 decimal digits (2 ** 32 - 1) + ASCII NUL */
|
||||
#define PRINTK_UINT_BUFSZ 11
|
||||
/* 10 decimal digits of 4294967295 (2 ** 32 - 1) */
|
||||
#define PRINTK_UINT_BUFSZ 10
|
||||
|
||||
__rodata static const char fmt_hex_table[] = {
|
||||
'0', '1', '2', '3',
|
||||
|
@ -42,7 +42,7 @@ static int fmt_handle_ptr(uintptr_t ptr)
|
|||
ptr >>= 4;
|
||||
} while (pos != &buf[2]);
|
||||
|
||||
ret = serial_write(serial_default_interface, &buf[0], 2 * sizeof(uintptr_t) + 2);
|
||||
ret = serial_write(serial_default_device, &buf[0], 2 * sizeof(uintptr_t) + 2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ static int fmt_handle_uint(unsigned int u)
|
|||
} while (u != 0);
|
||||
pos++;
|
||||
|
||||
ret = serial_write(serial_default_interface, pos,
|
||||
ret = serial_write(serial_default_device, pos,
|
||||
PRINTK_UINT_BUFSZ - ( (size_t)pos - (size_t)&buf[0] ));
|
||||
return ret;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ static inline int fmt_handle_int(int i)
|
|||
char minus = '-';
|
||||
|
||||
if (i < 0) {
|
||||
ret = serial_write(serial_default_interface, &minus, sizeof(minus));
|
||||
ret = serial_write(serial_default_device, &minus, sizeof(minus));
|
||||
i = -i;
|
||||
}
|
||||
|
||||
|
@ -102,12 +102,12 @@ static inline int fmt_handle(const char **pos, va_list args)
|
|||
|
||||
switch (**pos) {
|
||||
case '%': /* literal percent sign */
|
||||
ret = serial_write(serial_default_interface, *pos, sizeof(**pos));
|
||||
ret = serial_write(serial_default_device, *pos, sizeof(**pos));
|
||||
break;
|
||||
|
||||
case 'c': /* char */
|
||||
val.c = va_arg(args, typeof(val.c));
|
||||
ret = serial_write(serial_default_interface, &val.c, sizeof(val.c));
|
||||
ret = serial_write(serial_default_device, &val.c, sizeof(val.c));
|
||||
break;
|
||||
|
||||
case 'd': /* int */
|
||||
|
@ -123,7 +123,7 @@ static inline int fmt_handle(const char **pos, va_list args)
|
|||
case 's': /* string */
|
||||
val.s = va_arg(args, typeof(val.s));
|
||||
ret = (int)strlen(val.s);
|
||||
ret = serial_write(serial_default_interface, val.s, (size_t)ret);
|
||||
ret = serial_write(serial_default_device, val.s, (size_t)ret);
|
||||
break;
|
||||
|
||||
case 'u': /* unsigned int */
|
||||
|
@ -149,7 +149,7 @@ int printk(const char *fmt, ...)
|
|||
while (*tmp != '\0') {
|
||||
if (*tmp++ == '%') {
|
||||
/* flush out everything we have so far (minus one char for %) */
|
||||
ret += (int)serial_write(serial_default_interface, fmt,
|
||||
ret += (int)serial_write(serial_default_device, fmt,
|
||||
(size_t)tmp - (size_t)fmt - 1);
|
||||
|
||||
tmpret = fmt_handle(&tmp, args);
|
||||
|
@ -166,9 +166,10 @@ int printk(const char *fmt, ...)
|
|||
}
|
||||
|
||||
if (tmp != fmt && ret >= 0)
|
||||
ret += serial_write(serial_default_interface, fmt, (size_t)tmp - (size_t)fmt);
|
||||
ret += serial_write(serial_default_device, fmt, (size_t)tmp - (size_t)fmt);
|
||||
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/* See the end of this file for copyright, licensing, and warranty information. */
|
||||
|
||||
#include <ardix/atomic.h>
|
||||
#include <ardix/device.h>
|
||||
#include <ardix/ringbuf.h>
|
||||
#include <ardix/sched.h>
|
||||
#include <ardix/serial.h>
|
||||
|
@ -10,50 +11,52 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
int serial_init(struct serial_interface *interface, long int baud)
|
||||
int serial_init(struct serial_device *dev, long int baud)
|
||||
{
|
||||
int err = -1;
|
||||
|
||||
if (interface->id < 0)
|
||||
return -1; /* invalid interface */
|
||||
if (dev->id < 0)
|
||||
return -1; /* invalid dev */
|
||||
|
||||
interface->baud = baud;
|
||||
err = device_init(&dev->device, NULL);
|
||||
|
||||
interface->rx = ringbuf_create(SERIAL_BUFSZ);
|
||||
if (interface->rx == NULL)
|
||||
dev->baud = baud;
|
||||
|
||||
dev->rx = ringbuf_create(SERIAL_BUFSZ);
|
||||
if (dev->rx == NULL)
|
||||
return -1;
|
||||
|
||||
err = arch_serial_init(interface);
|
||||
err = arch_serial_init(dev);
|
||||
if (err)
|
||||
ringbuf_destroy(interface->rx);
|
||||
ringbuf_destroy(dev->rx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void serial_exit(struct serial_interface *interface)
|
||||
void serial_exit(struct serial_device *dev)
|
||||
{
|
||||
arch_serial_exit(interface);
|
||||
ringbuf_destroy(interface->rx);
|
||||
interface->id = -1;
|
||||
arch_serial_exit(dev);
|
||||
ringbuf_destroy(dev->rx);
|
||||
dev->id = -1;
|
||||
}
|
||||
|
||||
ssize_t serial_read(void *dest, struct serial_interface *interface, size_t len)
|
||||
ssize_t serial_read(void *dest, struct serial_device *dev, size_t len)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
atomic_enter();
|
||||
ret = (ssize_t)ringbuf_read(dest, interface->rx, len);
|
||||
ret = (ssize_t)ringbuf_read(dest, dev->rx, len);
|
||||
atomic_leave();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t serial_write(struct serial_interface *interface, const void *data, size_t len)
|
||||
ssize_t serial_write(struct serial_device *dev, const void *data, size_t len)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
atomic_enter();
|
||||
ret = arch_serial_write(interface, data, len);
|
||||
ret = arch_serial_write(dev, data, len);
|
||||
atomic_leave();
|
||||
|
||||
return ret;
|
||||
|
|
Loading…
Reference in a new issue