Changeset 86554e7 in mainline
- Timestamp:
- 2009-11-16T15:21:44Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f052c57
- Parents:
- 8344d0a
- Files:
-
- 4 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/arch/ia32/Makefile.inc
r8344d0a r86554e7 62 62 $(USPACEDIR)/app/bdsh/bdsh \ 63 63 $(USPACEDIR)/app/lspci/lspci \ 64 $(USPACEDIR)/app/shutters/shutters 64 $(USPACEDIR)/app/shutters/shutters \ 65 $(USPACEDIR)/app/test_serial/test_serial 65 66 66 67 build: $(BASE)/image.iso -
kernel/generic/src/ipc/irq.c
r8344d0a r86554e7 149 149 (unative_t) devno 150 150 }; 151 152 printf("kernel ipc_irq_register() ... registering irq = %d\n", inr); 151 153 152 154 if (ucode) { … … 202 204 203 205 interrupts_restore(ipl); 206 207 printf("kernel ipc_irq_register() ... registering irq = %d was successful \n", inr); 208 204 209 return EOK; 205 210 } -
uspace/Makefile
r8344d0a r86554e7 54 54 app/tetris \ 55 55 app/shutters \ 56 app/test_serial \ 56 57 app/tester \ 57 58 app/trace \ -
uspace/srv/pci/Makefile
r8344d0a r86554e7 45 45 SOURCES = \ 46 46 main.c \ 47 pic.c \ 47 48 pci.c \ 48 49 intel_piix3.c \ -
uspace/srv/pci/main.c
r8344d0a r86554e7 4 4 5 5 #include "intel_piix3.h" 6 #include "pic.h" 6 7 #include "pci.h" 7 8 #include "pci_bus.h" … … 10 11 11 12 13 12 14 int main(int argc, char **argv) 13 15 { 14 16 printf("PCI bus driver\n"); 17 18 if (!pic_init()) { 19 printf("PIC initialization failed.\n"); 20 return 1; 21 } 15 22 16 23 if (!pci_bus_init()) { … … 22 29 printf("ISA bus initialization failed.\n"); 23 30 return 1; 24 } 25 31 } 26 32 27 33 // pci-to-isa bridge device -
uspace/srv/pci/serial.c
r8344d0a r86554e7 18 18 #include "isa.h" 19 19 #include "serial.h" 20 #include "pic.h" 20 21 21 22 #define NAME "serial" … … 24 25 25 26 #define MAX_NAME_LEN 8 27 #define BUF_LEN 256 // the length of the input buffer 28 29 struct cyclic_buffer { 30 uint8_t buf[BUF_LEN]; // cyclic buffer 31 int start; 32 int cnt; 33 }; 34 35 typedef struct cyclic_buffer cyclic_buffer_t; 36 37 // returns false if the buffer is full 38 static bool buf_push_back(cyclic_buffer_t *buf, uint8_t item) 39 { 40 if (buf->cnt >= BUF_LEN) { 41 return false; 42 } 43 44 int pos = (buf->start + buf->cnt) % BUF_LEN; 45 buf->buf[pos] = item; 46 buf->cnt++; 47 return true; 48 } 49 50 static bool buf_is_empty(cyclic_buffer_t *buf) 51 { 52 return buf->cnt == 0; 53 } 54 55 // call it on non empty buffer! 56 static uint8_t buf_pop_front(cyclic_buffer_t *buf) 57 { 58 assert(!buf_is_empty(buf)); 59 60 uint8_t res = buf->buf[buf->start]; 61 buf->start = (buf->start + 1) % BUF_LEN; 62 buf->cnt--; 63 return res; 64 } 65 66 static void buf_clear(cyclic_buffer_t *buf) 67 { 68 buf->cnt = 0; 69 } 26 70 27 71 struct serial_dev { 28 72 link_t link; 29 73 char name[MAX_NAME_LEN]; 30 int handle; 74 int handle; // devmapper device handle 75 int devno; // unique device number; used in irq registration (cannot be handle used instead of it?) 31 76 bool client_connected; 32 77 ioport8_t *port; 33 78 void *phys_addr; 79 int irq; 34 80 bridge_to_isa_t *parent; 81 cyclic_buffer_t input_buffer; 82 futex_t futex; 35 83 }; 36 84 37 85 typedef struct serial_dev serial_dev_t; 38 86 87 static irq_cmd_t serial_cmds[] = { 88 { 89 .cmd = CMD_ACCEPT 90 } 91 }; 92 93 static irq_code_t serial_pseudocode = { 94 sizeof(serial_cmds) / sizeof(irq_cmd_t), 95 serial_cmds 96 }; 97 39 98 static void * serial_phys_addresses[] = { (void *)0x3F8, (void *)0x2F8 }; 99 static int serial_irqs[] = { 4, 3 }; // TODO - what about if there were more than two serial ports? 40 100 static int serial_phys_addr_cnt = sizeof(serial_phys_addresses)/sizeof(void *); 101 static int serial_irq_cnt = sizeof(serial_irqs)/sizeof(int); 102 41 103 // number, which should be assigned to a newly found serial device - increment first, then assign to the device 42 104 static int serial_idx = 0; … … 61 123 static void serial_getchar(serial_dev_t *dev, ipc_callid_t rid); 62 124 static void serial_client_conn(ipc_callid_t iid, ipc_call_t *icall); 125 static void serial_irq_handler(ipc_callid_t iid, ipc_call_t *icall); 126 static serial_dev_t * serial_devno_to_dev(int devno); 127 static serial_dev_t * serial_handle_to_dev(int handle); 128 static void serial_enable_interrupt(serial_dev_t *dev); 63 129 64 130 static isa_drv_ops_t serial_isa_ops = { … … 77 143 if (serial_driver_phone < 0) { 78 144 printf(NAME ": Unable to register driver\n"); 79 return false; 80 } 145 return 0; 146 } 147 148 // register irq handler 149 printf(NAME ": Registering interrup notification callback function.\n"); 150 async_set_interrupt_received(serial_irq_handler); 81 151 82 152 // register this driver by generic isa bus driver … … 92 162 static uint8_t serial_read_8(ioport8_t *port) 93 163 { 94 while (!serial_received(port)) 95 ; 96 97 uint8_t c = pio_read_8(port); 98 return c; 164 return pio_read_8(port); 99 165 } 100 166 … … 120 186 pio_write_8(port + 3, 0x07); // 8 bits, no parity, two stop bits 121 187 pio_write_8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold 122 pio_write_8(port + 4, 0x0B); // RTS/DSR set (Request to Send and Data Terminal Ready lines enabled), Aux Output2 set 188 pio_write_8(port + 4, 0x0B); // RTS/DSR set (Request to Send and Data Terminal Ready lines enabled), 189 // Aux Output2 set - needed for interrupts 190 191 } 192 193 static void serial_enable_interrupt(serial_dev_t *dev) 194 { 195 futex_down(&(dev->futex)); 196 // TODO do not call pic directly, do it more generally 197 pic_enable_interrupt(dev->irq); 198 pio_write_8(dev->port + 1 , 0x01); // Interrupt when data received 199 pio_write_8(dev->port + 4, 0x0B); 200 futex_up(&(dev->futex)); 123 201 } 124 202 … … 137 215 dev->parent = parent; 138 216 dev->phys_addr = dev->parent->ops->absolutize(serial_phys_addresses[idx % serial_phys_addr_cnt]); 217 dev->irq = serial_irqs[idx % serial_irq_cnt]; 139 218 snprintf(dev->name, MAX_NAME_LEN, "com%d", idx + 1); 140 dev->client_connected = false; 219 dev->devno = -1; 220 dev->client_connected = false; 221 futex_initialize(&(dev->futex), 1); 141 222 } 142 223 … … 145 226 assert(dev != NULL); 146 227 147 printf(NAME " driver: probing %s \n", dev->name);148 228 return (dev->port = (ioport8_t *)serial_probe_port(dev->phys_addr)) != NULL; 149 229 } … … 160 240 161 241 int i; 162 for (i = 0; i < serial_phys_addr_cnt; i++) { 242 for (i = 0; i < serial_phys_addr_cnt; i++) { 163 243 serial_init_dev(dev, parent, serial_idx); 244 printf(NAME ": probing %s. \n", dev->name); 164 245 if (serial_probe_dev(dev)) { 165 246 printf(NAME " driver: initializing %s.\n", dev->name); 166 247 serial_init_port(dev->port); 167 248 if (EOK != serial_device_register(serial_driver_phone, dev->name, &(dev->handle))) { 168 printf(NAME ": Unable to register device %s\n", dev->name); 169 } 170 list_append(&(dev->link), &serial_devices_list); 171 dev = serial_alloc_dev(); 249 printf(NAME ": unable to register device %s\n", dev->name); 250 } else { 251 dev->devno = device_assign_devno(); 252 253 // 3rd argument called method is equal devno,this enables us to identify the device 254 // which caused the interrupt in the irq notification callback function 255 printf(NAME ": registering irq = %d for %s.\n", dev->irq, dev->name); 256 ipc_register_irq(dev->irq, dev->devno, dev->devno, &serial_pseudocode); 257 list_append(&(dev->link), &serial_devices_list); 258 printf(NAME ": enabling irq = %d for %s.\n", dev->irq, dev->name); 259 serial_enable_interrupt(dev); 260 dev = serial_alloc_dev(); 261 } 172 262 } else { 173 263 printf(NAME " driver: %s is not present \n", dev->name); … … 210 300 { 211 301 int c = IPC_GET_ARG1(*request); 302 futex_down(&(dev->futex)); 212 303 serial_write_8(dev->port, (uint8_t)c); 304 futex_up(&(dev->futex)); 213 305 ipc_answer_0(rid, EOK); 214 306 } … … 216 308 static void serial_getchar(serial_dev_t *dev, ipc_callid_t rid) 217 309 { 218 uint8_t c = serial_read_8(dev->port); 310 uint8_t c; 311 printf(NAME ": trying to read from serial port %s\n", dev->name); 312 while (true) { // TODO: fix it - the queue of requests to read ? 313 futex_down(&(dev->futex)); 314 if (!buf_is_empty(&(dev->input_buffer))) { 315 c = buf_pop_front(&(dev->input_buffer)); 316 futex_up(&(dev->futex)); 317 break; 318 } 319 //printf(NAME "no data ready, trying to read again after some while.\n", dev->name); 320 futex_up(&(dev->futex)); 321 async_usleep(10000); 322 } 323 printf(NAME ": serial_getchar: sending characer %c read from %s to client.\n", c, dev->name); 219 324 ipc_answer_1(rid, EOK, c); 220 325 } 221 326 222 static serial_dev_t * serial_handle_to_dev(int handle) {223 327 static serial_dev_t * serial_handle_to_dev(int handle) 328 { 224 329 futex_down(&serial_futex); 225 330 … … 230 335 dev = list_get_instance(item, serial_dev_t, link); 231 336 if (dev->handle == handle) { 337 futex_up(&serial_futex); 338 return dev; 339 } 340 item = item->next; 341 } 342 343 futex_up(&serial_futex); 344 return NULL; 345 } 346 347 static serial_dev_t * serial_devno_to_dev(int devno) 348 { 349 futex_down(&serial_futex); 350 351 link_t *item = serial_devices_list.next; 352 serial_dev_t *dev = NULL; 353 354 while (item != &serial_devices_list) { 355 dev = list_get_instance(item, serial_dev_t, link); 356 if (dev->devno == devno) { 232 357 futex_up(&serial_futex); 233 358 return dev; … … 262 387 return; 263 388 } 264 389 390 buf_clear(&(dev->input_buffer)); // synchronization with interrupt service routine ? 265 391 dev->client_connected = true; 266 392 ipc_answer_0(iid, EOK); … … 310 436 while (phone < 0) { 311 437 usleep(10000); 312 phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, 313 DEVMAP_DRIVER, 0); 438 phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0); 314 439 } 315 440 … … 336 461 aid_t req; 337 462 ipc_call_t answer; 463 464 if (handle != NULL) { 465 *handle = -1; 466 } 338 467 339 468 req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer); … … 347 476 348 477 async_wait_for(req, &retval); 349 350 if (handle != NULL)351 *handle = -1;352 478 353 479 if (EOK == retval) { … … 358 484 return retval; 359 485 } 486 487 static void serial_read_from_device(serial_dev_t *dev) 488 { 489 bool cont = true; 490 491 while (cont) { 492 futex_down(&(dev->futex)); 493 if (cont = serial_received(dev->port)) { 494 uint8_t val = serial_read_8(dev->port); 495 printf(NAME ": character %c read from %s.\n", val, dev->name); 496 if (dev->client_connected) { 497 if (!buf_push_back(&(dev->input_buffer), val)) { 498 printf(NAME ": buffer overflow on %s.\n", dev->name); 499 } else { 500 printf(NAME ": the character %c saved to the buffer of %s.\n", val, dev->name); 501 } 502 } else { 503 printf(NAME ": no client is connected to %s, discarding the character which was read.\n", dev->name); 504 } 505 } 506 futex_up(&(dev->futex)); 507 usleep(10000); 508 } 509 } 510 511 // TODO - this is the only irq handling function registered by this task. 512 // (A task can register only one such function.) 513 // If more drivers within the task needed to handle interrupts, 514 // there will have to be one generic handler redistributing 515 // irq notification messages among them. 516 // Or the change of ansync framework will be needed. 517 static void serial_irq_handler(ipc_callid_t iid, ipc_call_t *icall) 518 { 519 printf(NAME ": irq handler\n"); 520 int devno = IPC_GET_METHOD(*icall); 521 serial_dev_t *dev = serial_devno_to_dev(devno); 522 serial_read_from_device(dev); 523 } 524
Note:
See TracChangeset
for help on using the changeset viewer.