Changeset 1f8657b in mainline for uspace/srv/drivers/serial/serial.c


Ignore:
Timestamp:
2010-04-22T14:54:01Z (14 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a78fa2a
Parents:
f928a8a
Message:

serial port probing

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/drivers/serial/serial.c

    rf928a8a r1f8657b  
    4949#include <fcntl.h>
    5050#include <sys/stat.h>
     51#include <ddi.h>
     52#include <libarch/ddi.h>
    5153
    5254#include <driver.h>
     
    5759#include <device/hw_res.h>
    5860
     61#include "cyclic_buffer.h"
     62
    5963#define NAME "serial"
    6064
     65#define REG_COUNT 7
     66
    6167typedef struct serial_dev_data {
    62                
     68        bool client_connected;
     69        int irq;
     70        uint32_t io_addr;
     71        ioport8_t *port;
     72        cyclic_buffer_t input_buffer;
     73        fibril_mutex_t mutex;           
    6374} serial_dev_data_t;
    6475
     76static serial_dev_data_t * create_serial_dev_data()
     77{
     78        serial_dev_data_t *data = (serial_dev_data_t *)malloc(sizeof(serial_dev_data_t));
     79        if (NULL != data) {
     80                memset(data, 0, sizeof(serial_dev_data_t));
     81                fibril_mutex_initialize(&data->mutex);
     82        }
     83        return data;   
     84}
     85
     86static void delete_serial_dev_data(serial_dev_data_t *data)
     87{
     88        if (NULL != data) {
     89                free(data);
     90        }
     91}
    6592
    6693static device_class_t serial_dev_class;
     
    81108};
    82109
     110static void serial_dev_cleanup(device_t *dev)
     111{
     112        if (NULL != dev->driver_data) {
     113                delete_serial_dev_data((serial_dev_data_t*)dev->driver_data);   
     114                dev->driver_data = NULL;
     115        }
     116       
     117        if (dev->parent_phone > 0) {
     118                ipc_hangup(dev->parent_phone);
     119                dev->parent_phone = 0;
     120        }       
     121}
     122
     123static bool serial_pio_enable(device_t *dev)
     124{
     125        printf(NAME ": serial_pio_enable = %s\n", dev->name);
     126       
     127        serial_dev_data_t *data = (serial_dev_data_t *)dev->driver_data;
     128       
     129        // Gain control over port's registers.
     130        if (pio_enable((void *)data->io_addr, REG_COUNT, (void **)(&data->port))) { 
     131                printf(NAME ": error - cannot gain the port %lx for device %s.\n", data->io_addr, dev->name);
     132                return false;
     133        }
     134       
     135        return true;
     136}
     137
     138static bool serial_dev_probe(device_t *dev)
     139{
     140        printf(NAME ": serial_dev_probe dev = %s\n", dev->name);
     141       
     142        serial_dev_data_t *data = (serial_dev_data_t *)dev->driver_data;
     143        ioport8_t *port_addr = data->port;     
     144        bool res = true;
     145        uint8_t olddata;
     146       
     147        olddata = pio_read_8(port_addr + 4);
     148       
     149        pio_write_8(port_addr + 4, 0x10);
     150        if (pio_read_8(port_addr + 6) & 0xf0) {
     151                res = false;
     152        }
     153       
     154        pio_write_8(port_addr + 4, 0x1f);
     155        if ((pio_read_8(port_addr + 6) & 0xf0) != 0xf0) {
     156                res = false;
     157        }
     158       
     159        pio_write_8(port_addr + 4, olddata);
     160       
     161        if (!res) {
     162                printf(NAME ": device %s is not present.\n", dev->name);
     163        }
     164       
     165        return res;     
     166}
     167
     168static bool serial_dev_initialize(device_t *dev)
     169{
     170        printf(NAME ": serial_dev_initialize dev = %s\n", dev->name);
     171       
     172        hw_resource_list_t hw_resources;
     173        memset(&hw_resources, 0, sizeof(hw_resource_list_t));
     174       
     175        // allocate driver data for the device
     176        serial_dev_data_t *data = create_serial_dev_data();     
     177        if (NULL == data) {
     178                return false;
     179        }
     180        dev->driver_data = data;
     181       
     182        // connect to the parent's driver
     183        dev->parent_phone = devman_parent_device_connect(dev->handle,  IPC_FLAG_BLOCKING);
     184        if (dev->parent_phone <= 0) {
     185                printf(NAME ": failed to connect to the parent driver of the device %s.\n", dev->name);
     186                goto failed;
     187        }
     188       
     189        // get hw resources
     190       
     191        if (!get_hw_resources(dev->parent_phone, &hw_resources)) {
     192                printf(NAME ": failed to get hw resources for the device %s.\n", dev->name);
     193                goto failed;
     194        }       
     195       
     196        size_t i;
     197        hw_resource_t *res;
     198        bool irq = false;
     199        bool ioport = false;
     200       
     201        for (i = 0; i < hw_resources.count; i++) {
     202                res = &hw_resources.resources[i];
     203                switch (res->type) {
     204                case INTERRUPT:
     205                        data->irq = res->res.interrupt.irq;
     206                        irq = true;
     207                        printf(NAME ": the %s device was asigned irq = 0x%x.\n", dev->name, data->irq);
     208                        break;
     209                case IO_RANGE:
     210                        data->io_addr = res->res.io_range.address;
     211                        if (res->res.io_range.size < REG_COUNT) {
     212                                printf(NAME ": i/o range assigned to the device %s is too small.\n", dev->name);
     213                                goto failed;
     214                        }
     215                        ioport = true;
     216                        printf(NAME ": the %s device was asigned i/o address = 0x%x.\n", dev->name, data->io_addr);
     217                        break;                 
     218                }
     219        }
     220       
     221        if (!irq || !ioport) {
     222                printf(NAME ": missing hw resource(s) for the device %s.\n", dev->name);
     223                goto failed;
     224        }               
     225       
     226        clean_hw_resource_list(&hw_resources);
     227        return true;
     228       
     229failed:
     230        serial_dev_cleanup(dev);       
     231        clean_hw_resource_list(&hw_resources); 
     232        return false;   
     233}
     234
    83235static bool serial_add_device(device_t *dev)
    84236{
    85237        printf(NAME ": serial_add_device, device handle = %d\n", dev->handle);
    86238       
    87         // TODO
     239        if (!serial_dev_initialize(dev)) {
     240                return false;
     241        }
     242       
     243        if (!serial_pio_enable(dev)) {
     244                serial_dev_cleanup(dev);
     245                return false;
     246        }
     247       
     248        if (!serial_dev_probe(dev)) {
     249                serial_dev_cleanup(dev);
     250                return false;
     251        }       
     252       
     253        // TODO interrupt and serial port initialization (baud rate etc.)
    88254       
    89255        return true;
Note: See TracChangeset for help on using the changeset viewer.