[U-Boot] [PATCH v2] NS16550: buffer reads
Graeme Russ
graeme.russ at gmail.com
Wed Oct 26 11:18:41 CEST 2011
Hi Wolfgang,
On 26/10/11 18:00, Wolfgang Denk wrote:
> Dear Graeme,
>
> In message <CALButCKQ_bgpOZquozzQnU01v41Y+uWo8ELLNqSE15D30p52ug at mail.gmail.com> you wrote:
>>
>> Well, I have the feeling than an console API might be in order. The way
>> U-Boot is structured at the moment, serial I/O is kind of taken for
>> granted to 'just exist' and nobody needs to really be self-aware that
>> they use it...
>
> Indeed. All we need is a working set of srdin/stdout/stderr. Keep in
> mind that anything couldbe attached - not only a serial line.
>
>> ... The same cannot be said of users of USB and Network -
>> Net is a good example - all 'users' of net call NetLoop() which does
>> an eth_init()...do stuff...eth_halt()
>
> Driver API...
>
>> So maybe a serial API which 'users' must 'wake up' and 'sleep'...
>
> Arghhh...
>
>> - console_configure() - Set parameters (port, baud rate etc)
>> - console_wake() - Prepare the console (could be serial, USB, netconsole)
>> - console_flush() - Throw away any buffered characters
>> - console_getc(), console_putc(), console_tstc() - Self explainatory
>> - console_sleep() - Shut the console down (send XOFF, turn of USB etc)
>
> Forget it. We will not have a separate and completely non-standard "serial API".
> If anything gets changed here, then in the context of a general driver
> API cleanup, or at least based on a design for such a generic driver
> API.
Funny, I wrote that without the code in front of me. But look at this...
struct serial_device {
char name[NAMESIZE];
int (*init) (void);
int (*uninit) (void);
void (*setbrg) (void);
int (*getc) (void);
int (*tstc) (void);
void (*putc) (const char c);
void (*puts) (const char *s);
#if CONFIG_POST & CONFIG_SYS_POST_UART
void (*loop) (int);
#endif
struct serial_device *next;
};
and
struct stdio_dev {
int flags; /* Device flags: input/output/system */
int ext; /* Supported extensions */
char name[16] /* Device name */
/* GENERAL functions */
int (*start) (void); /* To start the device */
int (*stop) (void); /* To stop the device */
/* OUTPUT functions */
void (*putc) (const char c); /* To put a char */
void (*puts) (const char *s); /* To put a string */
/* INPUT functions */
int (*tstc) (void); /* To test if a char is ready...*/
int (*getc) (void); /* To get that char */
/* Other functions */
void *priv; /* Private extensions */
struct list_head list;
};
and
void serial_stdio_init (void)
{
struct stdio_dev dev;
struct serial_device *s = serial_devices;
while (s) {
memset (&dev, 0, sizeof (dev));
strcpy (dev.name, s->name);
dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
dev.start = s->init;
dev.stop = s->uninit;
dev.putc = s->putc;
dev.puts = s->puts;
dev.getc = s->getc;
dev.tstc = s->tstc;
stdio_register (&dev);
s = s->next;
}
}
and mpc512x has this gem
int close_port(int num)
{
struct stdio_dev *port;
int ret;
char name[7];
if (num < 0 || num > 11)
return -1;
sprintf(name, "psc%d", num);
port = stdio_get_by_name(name);
if (!port)
return -1;
ret = port->stop();
clear_bit(num, &initialized);
return ret;
}
stdio_dev->start() is called in console_setfile() which is called by
console_init_r(). stdio_dev->stop() is never called apart from in the above
mpc512x example.
As I said, stdio is, unlike other devices, taken for granted - It gets
setup during console_init_r() and is assumed to be in-volatile from then on.
So the hooks are already there - All that would be needed is a hook to
allow console users to ultimately call stdio_dev->start when they want to
start using stdio and stdio_dev->stop when they are finished. Of course the
physical device itself is hidden and could be serial, USB, Ethernet, VGA,
Braille display - whatever.
Hmmm, stdio_open() and stdio_close()
>> UART like your SPI example. The command line interpreter calls
>> console_sleep() to release the serial UART resource before the command
>> which uses the multiplexed device wakes that device, does it's thing and
>> shuts the device down before returning to the command line interpreter
>> which wakes up the serial UART...
>
> Sorry, but that's crappy by design.
When resources are tight - The eNET board has 8-bit CF ports instead of 16
bit because of board space and FPGA limitation which necessitated a slight
mod to the Linux CF driver. Crappy yes, but hey, when given lemons
Regards,
Graeme
More information about the U-Boot
mailing list