Changeset 1f8657b in mainline
- Timestamp:
- 2010-04-22T14:54:01Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a78fa2a
- Parents:
- f928a8a
- Location:
- uspace/srv/drivers/serial
- Files:
-
- 1 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/drivers/serial/serial.c
rf928a8a r1f8657b 49 49 #include <fcntl.h> 50 50 #include <sys/stat.h> 51 #include <ddi.h> 52 #include <libarch/ddi.h> 51 53 52 54 #include <driver.h> … … 57 59 #include <device/hw_res.h> 58 60 61 #include "cyclic_buffer.h" 62 59 63 #define NAME "serial" 60 64 65 #define REG_COUNT 7 66 61 67 typedef 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; 63 74 } serial_dev_data_t; 64 75 76 static 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 86 static void delete_serial_dev_data(serial_dev_data_t *data) 87 { 88 if (NULL != data) { 89 free(data); 90 } 91 } 65 92 66 93 static device_class_t serial_dev_class; … … 81 108 }; 82 109 110 static 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 123 static 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 138 static 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 168 static 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 229 failed: 230 serial_dev_cleanup(dev); 231 clean_hw_resource_list(&hw_resources); 232 return false; 233 } 234 83 235 static bool serial_add_device(device_t *dev) 84 236 { 85 237 printf(NAME ": serial_add_device, device handle = %d\n", dev->handle); 86 238 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.) 88 254 89 255 return true;
Note:
See TracChangeset
for help on using the changeset viewer.