рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ, рд╣рдордиреЗ рдорд▓реНрдЯреАрдЯрд╛рд╕реНрдХрд┐рдВрдЧ рдХреА рд╢реБрд░реБрдЖрдд рдХреА рдереАред рдЖрдЬ рдЪрд░рд┐рддреНрд░ рдбрд┐рд╡рд╛рдЗрд╕ рдбреНрд░рд╛рдЗрд╡рд░реЛрдВ рдХреЗ рд╡рд┐рд╖рдп рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред
рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рдЖрдЬ рд╣рдо рдПрдХ рдЯрд░реНрдорд┐рдирд▓ рдбреНрд░рд╛рдЗрд╡рд░ рд▓рд┐рдЦреЗрдВрдЧреЗ, рдЬреЛ рд╡реНрдпрд╡рдзрд╛рдиреЛрдВ рдХреЗ рд╕реНрдердЧрд┐рдд рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рддрдВрддреНрд░ рд╣реИ, рдФрд░ рдЗрдВрдЯрд░рдкреНрдЯ рдХреЗ рдКрдкрд░реА рдФрд░ рдирд┐рдЪрд▓реЗ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЗ рд▓рд┐рдП рд╣реИрдВрдбрд▓рд░ рдХреЗ рд╡рд┐рд╖рдп рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред
рд╣рдо рдПрдХ рдЙрдкрдХрд░рдг рд╕рдВрд░рдЪрдирд╛ рдмрдирд╛рдХрд░ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдлрд┐рд░ рдореВрд▓ рдлрд╝рд╛рдЗрд▓ I / O рд╕рдорд░реНрдерди рдХреЛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, io_buf рд╕рдВрд░рдЪрдирд╛ рдФрд░ stdio.h рд╕реЗ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред
рд╕рд╛рдордЧреНрд░реА рдХреА рддрд╛рд▓рд┐рдХрд╛
рдмрд┐рд▓реНрдб рд╕рд┐рд╕реНрдЯрдо (рдореЗрдХ, рдЬреАрд╕реАрд╕реА, рдЧреИрд╕)ред рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдмреВрдЯ (рдорд▓реНрдЯреАрдмреВрдЯ)ред рд▓реЙрдиреНрдЪ (qemu)ред рд╕реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА (strcpy, memcpy, strext)ред рд╕реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА (рд╕реНрдкреНрд░рд┐рдВрдЯрдл, рд╕реНрдЯреНрд░реИрдЪреА, рд╕реНрдЯреНрд░реИрдореНрдк, рд╕реНрдЯреНрд░реЗрдЯреЛрдХ, рд╡рд╛_рд▓рд┐рд╕реНрдЯ ...)ред рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рдХрд░реНрдиреЗрд▓ рдореЛрдб рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЛрдб рдореЗрдВ рдмрдирд╛рдирд╛ред рдХрд░реНрдиреЗрд▓ рд╕рд┐рд╕реНрдЯрдо рд▓реЙрдЧред рд╡реАрдбрд┐рдпреЛ рдореЗрдореЛрд░реА рдЯрд░реНрдорд┐рдирд▓ рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ (kprintf, kpanic, kassert)ред рдбрд╛рдпрдиреЗрдорд┐рдХ рдореЗрдореЛрд░реА, рд╣реАрдк (kmalloc, kfree)ред рдореЗрдореЛрд░реА рдФрд░ рдЗрдВрдЯрд░рдкреНрдЯ рд╣реИрдВрдбрд▓рд┐рдВрдЧ (GDT, IDT, PIC, syscall) рдХрд╛ рд╕рдВрдЧрдардиред рдЕрдкрд╡рд╛рджред рд╡рд░реНрдЪреБрдЕрд▓ рдореЗрдореЛрд░реА (рдкреЗрдЬ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдФрд░ рдкреЗрдЬ рдЯреЗрдмрд▓)ред рдкреНрд░рдХреНрд░рд┐рдпрд╛ред рд╕рдордпрдмрджреНрдзрдХред рдорд▓реНрдЯреАрдЯрд╛рд╕реНрдХрд┐рдВрдЧред рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ (рдорд╛рд░, рдирд┐рдХрд╛рд╕, рдкреАрдПрд╕)ред
рдЪрд░рд┐рддреНрд░ рдбрд┐рд╡рд╛рдЗрд╕ рдбреНрд░рд╛рдЗрд╡рд░ред рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ (ioctl, fopen, fread, fwrite)ред рд╕реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА (fopen, fclose, fprintf, fscanf)редрдХрд░реНрдиреЗрд▓ рдХреА рдлрд╝рд╛рдЗрд▓ рдкреНрд░рдгрд╛рд▓реА (initrd), рдпреЛрдЧрд┐рдиреА, рдФрд░ рдЗрд╕рдХреЗ рдЖрдВрддрд░рд┐рдХред рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ (рдирд┐рд╖реНрдкрд╛рджрди)ред рдХрд░реНрдиреЗрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреВрд░реНрдг рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рд░реВрдк рдореЗрдВ рд╢реЗрд▓ред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реБрд░рдХреНрд╖рд╛ рдореЛрдб (рд░рд┐рдВрдЧ 3)ред рдЯрд╛рд╕реНрдХ рд╕реНрдЯреЗрдЯрд╕ рд╕реЗрдЧрдореЗрдВрдЯ (tss)ред
рдЪрд░рд┐рддреНрд░ рдбреНрд░рд╛рдЗрд╡рд░
рдпрд╣ рд╕рдм рдПрдХ рдкреНрд░рддреАрдХрд╛рддреНрдордХ рдЙрдкрдХрд░рдг рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдпрд╛рдж рдХрд░рддреЗ рд╣реИрдВ, рд▓рд┐рдирдХреНрд╕ рдбрд┐рд╡рд╛рдЗрд╕ рдбреНрд░рд╛рдЗрд╡рд░реНрд╕ рдореЗрдВ, рдбрд┐рд╡рд╛рдЗрд╕ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреА рдереА:
struct cdev *my_cdev = cdev_alloc( ); my_cdev->ops = &my_fops;
рдореБрдЦреНрдп рдмрд┐рдВрджреБ рдбрд┐рд╡рд╛рдЗрд╕ рдХреЛ рдлрд╝рд╛рдЗрд▓ I / O рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЕрд╕рд╛рдЗрди рдХрд░рдирд╛ рд╣реИред
рд╣рдо рдПрдХ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдЕрд░реНрде рд╕рдорд╛рди рд╣реЛрдЧрд╛:
extern struct dev_t { struct clist_head_t list_head; char name[8]; void* base_r; void* base_w; dev_read_cb_t read_cb; dev_write_cb_t write_cb; dev_ioctl_cb_t ioctl_cb; struct clist_definition_t ih_list; };
рдкреНрд░рддреНрдпреЗрдХ рдбрд┐рд╡рд╛рдЗрд╕ рдЗрдВрдЯрд░рдкреНрдЯ рдХреА рдЖрдзреА рд╕реВрдЪреА рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИ рдЬрд┐рд╕реЗ рдЗрдВрдЯрд░рдкреНрдЯ рд╣реЛрдиреЗ рдкрд░ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред
рд▓рд┐рдирдХреНрд╕ рдореЗрдВ, рдРрд╕реЗ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдКрдкрд░реА рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рдирд┐рдЪрд▓рд╛ (рдирд┐рдЪрд▓рд╛ рд╕реНрддрд░)ред
рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ, рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рддрд░реНрдХрд╕рдВрдЧрдд рд▓рдЧ рд░рд╣рд╛ рдерд╛ рдФрд░ рдореИрдВрдиреЗ рдЧрд▓рддреА рд╕реЗ рд╢рд░реНрддреЛрдВ рдХреЛ рджреВрд╕рд░реЗ рддрд░реАрдХреЗ рд╕реЗ рдпрд╛рдж рдХрд┐рдпрд╛ред рд╣рдо рд░реБрдХрд╛рд╡рдЯ рдХреЗ рдирд┐рдЪрд▓реЗ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХрд╛ рд╡рд░реНрдгрди рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ:
extern struct ih_low_t { struct clist_head_t list_head; int number; ih_low_cb_t handler; };
рдЖрд░рдВрдн рд╣реЛрдиреЗ рдкрд░, рдбреНрд░рд╛рдЗрд╡рд░ рдЕрдкрдиреЗ рдбрд┐рд╡рд╛рдЗрд╕ рдХреЛ dev_register рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдЧрд╛, рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ рд░рд┐рдВрдЧ рд▓рд┐рд╕реНрдЯ рдореЗрдВ рдПрдХ рдирдпрд╛ рдбрд┐рд╡рд╛рдЗрд╕ рдЬреЛрдбрд╝реЗрдВ:
extern void dev_register(struct dev_t* dev) { struct clist_head_t* entry; struct dev_t* device; entry = clist_insert_entry_after(&dev_list, dev_list.head); device = (struct dev_t*)entry->data; strncpy(device->name, dev->name, sizeof(dev->name)); device->base_r = dev->base_r; device->base_w = dev->base_w; device->read_cb = dev->read_cb; device->write_cb = dev->write_cb; device->ioctl_cb = dev->ioctl_cb; device->ih_list.head = dev->ih_list.head; device->ih_list.slot_size = dev->ih_list.slot_size; }
рдЗрд╕ рд╕рдм рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рди рдХрд┐рд╕реА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо рдХреА рдЕрд╢рд┐рд╖реНрдЯрддрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреЗрд╡рд▓ рдЪрд░рд┐рддреНрд░ рдЙрдкрдХрд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдлрд╛рдЗрд▓реЗрдВ рд╣реЛрдВрдЧреАред
рдпрд╛рдиреА рдлрд╝рд╛рдЗрд▓ рдЦреЛрд▓рдирд╛ рд╕рдВрдмрдВрдзрд┐рдд рдбреНрд░рд╛рдЗрд╡рд░ рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП stdio рд╕реЗ рдПрдХ рдлрд╝рд╛рдЗрд▓ рд╕рдВрд░рдЪрдирд╛ рдмрдирд╛рдиреЗ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдЧрд╛ред
рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рдбрд┐рд╡рд╛рдЗрд╕ рдХреЗ рдирд╛рдо рд╕реЗ рдореЗрд▓ рдЦрд╛рдПрдЧрд╛ред рд╣рдо рдЕрдкрдиреЗ рд╕реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА (stdio.h) рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред
struct io_buf_t { int fd; char* base; char* ptr; bool is_eof; void* file; }; #define FILE struct io_buf_t
рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╕рднреА рдЦреБрд▓реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЕрднреА рдХреЗ рд▓рд┐рдП рдПрдХ рд░рд┐рдВрдЧ рд╕реВрдЪреА рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╕реВрдЪреА рдЖрдЗрдЯрдо рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╡рд░реНрдгрд┐рдд рд╣реИ:
extern struct file_t { struct clist_head_t list_head; struct io_buf_t io_buf; char name[8]; int mod_rw; struct dev_t* dev; };
рдкреНрд░рддреНрдпреЗрдХ рдЦреБрд▓реА рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП, рд╣рдо рдбрд┐рд╡рд╛рдЗрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдВрдЧреЗред рд╣рдо рдЦреБрд▓реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреА рдПрдХ рд░рд┐рдВрдЧ рд╕реВрдЪреА рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд░реАрдб / рд░рд╛рдЗрдЯ / рдУрдЗрдХреНрдЯрд▓ рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред
рдлрд╝рд╛рдЗрд▓ рдЦреЛрд▓рддреЗ рд╕рдордп, рд╣рдореЗрдВ рдмрд╕ рдбреНрд░рд╛рдЗрд╡рд░ рд╕реЗ io_buf_t рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдбреНрд░рд╛рдЗрд╡рд░ рдХреЛ рдкрдврд╝рдиреЗ рдФрд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд╢реБрд░реБрдЖрддреА рдкрджреЛрдВ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рддрджрдиреБрд╕рд╛рд░, рдбрд┐рд╡рд╛рдЗрд╕ рдбреНрд░рд╛рдЗрд╡рд░ рдХреЗ рд╕рд╛рде рдлрд╝рд╛рдЗрд▓ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рд╕рдВрдмрджреНрдз рдХрд░рддрд╛ рд╣реИред
extern struct io_buf_t* file_open(char* path, int mod_rw) { struct clist_head_t* entry; struct file_t* file; struct dev_t* dev; entry = clist_find(&file_list, file_list_by_name_detector, path, mod_rw); file = (struct file_t*)entry->data; if (entry != null) { return &file->io_buf; } entry = clist_insert_entry_after(&file_list, file_list.head); file = (struct file_t*)entry->data; dev = dev_find_by_name(path); if (dev != null) { file->dev = dev; if (mod_rw == MOD_R) { file->io_buf.base = dev->base_r; } else if (mod_rw == MOD_W) { file->io_buf.base = dev->base_w; } } else { file->dev = null; unreachable(); } file->mod_rw = mod_rw; file->io_buf.fd = next_fd++; file->io_buf.ptr = file->io_buf.base; file->io_buf.is_eof = false; file->io_buf.file = file; strncpy(file->name, path, sizeof(file->name)); return &file->io_buf; }
рдлрд╝рд╛рдЗрд▓ рдСрдкрд░реЗрд╢рдиреНрд╕ рд░реАрдб / рд░рд╛рдЗрдЯ / ioctl рдХреЛ рдПрдХ рдкреИрдЯрд░реНрди рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рд░реАрдб рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдПред
рдмрд╣реБрдд рд╣реА рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдЬреЛ рд╣рдордиреЗ рдЖрдЦрд┐рд░реА рдкрд╛рда рдореЗрдВ рд▓рд┐рдЦрдирд╛ рд╕реАрдЦрд╛, рдмрд╕ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдЧрд╛ред
extern size_t file_read(struct io_buf_t* io_buf, char* buff, u_int size) { struct file_t* file; file = (struct file_t*)io_buf->file; if (file->dev != null) { return file->dev->read_cb(&file->io_buf, buff, size); } else { unreachable(); } return 0; }
рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рд╡реЗ рдХреЗрд╡рд▓ рдбрд┐рд╡рд╛рдЗрд╕ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рд╕реЗ рдХреЙрд▓рдмреИрдХ рдЦреАрдВрдЪреЗрдВрдЧреЗред рдЕрдм рд╣рдо рдЯрд░реНрдорд┐рдирд▓ рдбреНрд░рд╛рдЗрд╡рд░ рд▓рд┐рдЦреЗрдВрдЧреЗред
рдЯрд░реНрдорд┐рдирд▓ рдЪрд╛рд▓рдХ
рд╣рдореЗрдВ рдПрдХ рд╕реНрдХреНрд░реАрди рдЖрдЙрдЯрдкреБрдЯ рдмрдлрд░ рдФрд░ рдХреАрдмреЛрд░реНрдб рдЗрдирдкреБрдЯ рдмрдлрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рдЗрдирдкреБрдЯ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдореЛрдб рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЭрдВрдбреЗ рднреА рдЪрд╛рд╣рд┐рдПред
static const char* tty_dev_name = TTY_DEV_NAME; static char tty_output_buff[VIDEO_SCREEN_SIZE]; static char tty_input_buff[VIDEO_SCREEN_WIDTH]; char* tty_output_buff_ptr = tty_output_buff; char* tty_input_buff_ptr = tty_input_buff; bool read_line_mode = false; bool is_echo = false;
рд╣рдо рдПрдХ рдЙрдкрдХрд░рдг рдмрдирд╛рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рд▓рд┐рдЦрддреЗ рд╣реИрдВред рдпрд╣ рдмрд╕ рдлрд╝рд╛рдЗрд▓ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдХреЙрд▓рдмреИрдХ рдХреЛ рдХрдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рд░реБрдХрд╛рд╡рдЯреЛрдВ рдХреЗ рдирд┐рдЪрд▓реЗ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдпрд╣ рдбрд┐рд╡рд╛рдЗрд╕ рдХреЛ рд░рд┐рдВрдЧ рд╕реВрдЪреА рдореЗрдВ рджрд░реНрдЬ рдХрд░рддрд╛ рд╣реИред
extern void tty_init() { struct clist_head_t* entry; struct dev_t dev; struct ih_low_t* ih_low; memset(tty_output_buff, 0, sizeof(VIDEO_SCREEN_SIZE)); memset(tty_input_buff, 0, sizeof(VIDEO_SCREEN_WIDTH)); strcpy(dev.name, tty_dev_name); dev.base_r = tty_input_buff; dev.base_w = tty_output_buff; dev.read_cb = tty_read; dev.write_cb = tty_write; dev.ioctl_cb = tty_ioctl; dev.ih_list.head = null; dev.ih_list.slot_size = sizeof(struct ih_low_t); entry = clist_insert_entry_after(&dev.ih_list, dev.ih_list.head); ih_low = (struct ih_low_t*)entry->data; ih_low->number = INT_KEYBOARD; ih_low->handler = tty_keyboard_ih_low; dev_register(&dev); }
рдХреАрдмреЛрд░реНрдб рдХреЗ рд▓рд┐рдП рдирд┐рдЪрд▓рд╛ рдЕрд╡рд░реЛрдзрдХ рд╣реИрдВрдбрд▓рд░ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
static void tty_keyboard_ih_low(int number, struct ih_low_data_t* data) { char* keycode = data->data; int index = *keycode; assert(index < 128); char ch = keyboard_map[index]; *tty_input_buff_ptr++ = ch; if (is_echo && ch != '\n') { *tty_output_buff_ptr++ = ch; } struct message_t msg; msg.type = IPC_MSG_TYPE_DQ_SCHED; msg.len = 4; *((size_t *)msg.data) = (size_t)tty_keyboard_ih_high; ksend(TID_DQ, &msg); }
рдпрд╣рд╛рдВ рд╣рдо рдмрд╕ рдХреАрдмреЛрд░реНрдб рдмрдлрд░ рдореЗрдВ рджрд░реНрдЬ рдЪрд░рд┐рддреНрд░ рдбрд╛рд▓рддреЗ рд╣реИрдВред рдЕрдВрдд рдореЗрдВ, рд╣рдо рдХреАрдмреЛрд░реНрдб рд░реБрдХрд╛рд╡рдЯ рдХреЗ рдКрдкрд░реА рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЗ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдЖрд╕реНрдердЧрд┐рдд рдХреЙрд▓ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рдХрд░реНрдиреЗрд▓ рдереНрд░реЗрдб рдХреЛ рдПрдХ рд╕рдВрджреЗрд╢ (IPC) рднреЗрдЬрдХрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдХрд░реНрдиреЗрд▓ рдзрд╛рдЧрд╛ рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ:
void dq_task() { struct message_t msg; for (;;) { kreceive(TID_DQ, &msg); switch (msg.type) { case IPC_MSG_TYPE_DQ_SCHED: assert(msg.len == 4); dq_handler_t handler = (dq_handler_t)*((size_t*)msg.data); assert((size_t)handler < KERNEL_CODE_END_ADDR); printf(MSG_DQ_SCHED, handler); handler(msg); break; } } exit(0); }
рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдХреАрдмреЛрд░реНрдб рдЗрдВрдЯрд░рдкреНрдЯ рдХреЗ рдКрдкрд░реА рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЗ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдЖрдЙрдЯрдкреБрдЯ рдмрдлрд░ рдХреЛ рд╡реАрдбрд┐рдпреЛ рдореЗрдореЛрд░реА рдореЗрдВ рдХреЙрдкреА рдХрд░рдХреЗ рд╕реНрдХреНрд░реАрди рдкрд░ рдПрдХ рдЪрд░рд┐рддреНрд░ рдХреА рдирдХрд▓ рдХрд░рдирд╛ рд╣реИред
static void tty_keyboard_ih_high(struct message_t *msg) { video_flush(tty_output_buff); }
рдЕрдм рдпрд╣ рдЖрдИ / рдУ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд░рд╣рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдлрд╝рд╛рдЗрд▓ рд╕рдВрдЪрд╛рд▓рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред
static u_int tty_read(struct io_buf_t* io_buf, void* buffer, u_int size) { char* ptr = buffer; assert((size_t)io_buf->ptr <= (size_t)tty_input_buff_ptr); assert((size_t)tty_input_buff_ptr >= (size_t)tty_input_buff); assert(size > 0); io_buf->is_eof = (size_t)io_buf->ptr == (size_t)tty_input_buff_ptr; if (read_line_mode) { io_buf->is_eof = !strchr(io_buf->ptr, '\n'); } for (int i = 0; i < size - 1 && !io_buf->is_eof; ++i) { char ch = tty_read_ch(io_buf); *ptr++ = ch; if (read_line_mode && ch == '\n') { break; } } return (size_t)ptr - (size_t)buffer; } static void tty_write(struct io_buf_t* io_buf, void* data, u_int size) { char* ptr = data; for (int i = 0; i < size && !io_buf->is_eof; ++i) { tty_write_ch(io_buf, *ptr++); } }
рдЪрд░рд┐рддреНрд░-рджрд░-рд╡рд░реНрдг рдСрдкрд░реЗрд╢рди рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИрдВ рдФрд░ рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдЙрдиреНрд╣реЗрдВ рдЯрд┐рдкреНрдкрдгреА рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
static void tty_write_ch(struct io_buf_t* io_buf, char ch) { if ((size_t)tty_output_buff_ptr - (size_t)tty_output_buff + 1 < VIDEO_SCREEN_SIZE) { if (ch != '\n') { *tty_output_buff_ptr++ = ch; } else { int line_pos = ((size_t)tty_output_buff_ptr - (size_t)tty_output_buff) % VIDEO_SCREEN_WIDTH; for (int j = 0; j < VIDEO_SCREEN_WIDTH - line_pos; ++j) { *tty_output_buff_ptr++ = ' '; } } } else { tty_output_buff_ptr = video_scroll(tty_output_buff, tty_output_buff_ptr); tty_write_ch(io_buf, ch); } io_buf->ptr = tty_output_buff_ptr; } static char tty_read_ch(struct io_buf_t* io_buf) { if ((size_t)io_buf->ptr < (size_t)tty_input_buff_ptr) { return *io_buf->ptr++; } else { io_buf->is_eof = true; return '\0'; } }
рдпрд╣ рдХреЗрд╡рд▓ ioctl рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдирдкреБрдЯ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдореЛрдб рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред
static void tty_ioctl(struct io_buf_t* io_buf, int command) { char* hello_msg = MSG_KERNEL_NAME; switch (command) { case IOCTL_INIT: if (io_buf->base == tty_output_buff) { kmode(false); tty_output_buff_ptr = video_clear(io_buf->base); io_buf->ptr = tty_output_buff_ptr; tty_write(io_buf, hello_msg, strlen(hello_msg)); video_flush(io_buf->base); io_buf->ptr = tty_output_buff_ptr; } else if (io_buf->base == tty_input_buff) { unreachable(); } break; case IOCTL_CLEAR: if (io_buf->base == tty_output_buff) { tty_output_buff_ptr = video_clear(io_buf->base); video_flush(io_buf->base); io_buf->ptr = tty_output_buff_ptr; } else if (io_buf->base == tty_input_buff) { tty_input_buff_ptr = tty_input_buff; io_buf->ptr = io_buf->base; io_buf->is_eof = true; } break; case IOCTL_FLUSH: if (io_buf->base == tty_output_buff) { video_flush(io_buf->base); } else if (io_buf->base == tty_input_buff) { unreachable(); } break; case IOCTL_READ_MODE_LINE: if (io_buf->base == tty_input_buff) { read_line_mode = true; } else if (io_buf->base == tty_output_buff) { unreachable(); } break; case IOCTL_READ_MODE_ECHO: if (io_buf->base == tty_input_buff) { is_echo = true; } else if (io_buf->base == tty_output_buff) { unreachable(); } break; default: unreachable(); } }
рдЕрдм рд╣рдо рдЕрдкрдиреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕реА рдХреЗ рд╕реНрддрд░ рдкрд░ рдлрд╝рд╛рдЗрд▓ рдЗрдирдкреБрдЯ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред
extern FILE* fopen(const char* file, int mod_rw) { FILE* result = null; asm_syscall(SYSCALL_OPEN, file, mod_rw, &result); return result; } extern void fclose(FILE* file) { asm_syscall(SYSCALL_CLOSE, file); } extern u_int fread(FILE* file, char* buff, u_int size) { return asm_syscall(SYSCALL_READ, file, buff, size); } extern void fwrite(FILE* file, const char* data, u_int size) { asm_syscall(SYSCALL_WRITE, file, data, size); }
рдареАрдХ рд╣реИ, рдпрд╣рд╛рдБ рдХреБрдЫ рдЙрдЪреНрдЪ-рд╕реНрддрд░реАрдп рдХрд╛рд░реНрдп рд╣реИрдВ:
extern void uvnprintf(const char* format, u_int n, va_list list) { char buff[VIDEO_SCREEN_WIDTH]; vsnprintf(buff, n, format, list); uputs(buff); } extern void uscanf(char* buff, ...) { u_int readed = 0; do { readed = fread(stdin, buff, 255); } while (readed == 0); buff[readed - 1] = '\0'; uprintf("\n"); uflush(); }
рдЕрдм рддрдХ рдкреНрд░рд╛рд░реВрдк рдкрдврд╝рдиреЗ рдХреЗ рд╕рд╛рде рдореВрд░реНрдЦ рдирд╣реАрдВ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╣рдореЗрд╢рд╛ рд▓рд╛рдЗрди рдореЗрдВ рдкрдврд╝реЗрдВрдЧреЗ рдЬреИрд╕реЗ рдХрд┐% s рдзреНрд╡рдЬ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдлрд╝рд╛рдЗрд▓ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдИ рдХрд╛рд░реНрдп рд╕реНрдерд┐рддрд┐ рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВ рдмрд╣реБрдд рдЖрд▓рд╕реА рдерд╛, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЕрдирдВрдд рд▓реВрдк рдореЗрдВ рдХреБрдЫ рдкрдврд╝рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ рдЬрдм рддрдХ рд╣рдо рд╕рдлрд▓ рдирд╣реАрдВ рд╣реЛ рдЬрд╛рддреЗред
рд╡рд╣ рд╕рдм рд╣реИред рдЕрдм рдЖрдк рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдЕрдкрдиреЗ рдХрд░реНрдиреЗрд▓ рдХреЛ рдбреНрд░рд╛рдЗрд╡рд░реЛрдВ рдХреЛ рдлрд╛рд╕реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ!
рд╕рдВрджрд░реНрдн
рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП
рд╡реАрдбрд┐рдпреЛ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рджреЗрдЦреЗрдВред
тЖТ
рдЬреАрдЖрдИрдЯреА рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб (рдЖрдкрдХреЛ рд╕рдмрдХ 8 рд╢рд╛рдЦрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ)
рд╕рдВрджрд░реНрдн
- рдЬреЗрдореНрд╕ рдореЛрд▓реЙрдпред рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдЦрд┐рд▓реМрдирд╛ рдпреВрдирд┐рдХреНрд╕-рдХреНрд▓реЛрди рдУрдПрд╕ рд░реЛрд▓ рдХрд░реЗрдВред
- рдЬреБрдмрдХреЛрд╡ред рдбреЙрд╕, рд╡рд┐рдВрдбреЛрдЬ, рдпреВрдирд┐рдХреНрд╕ рдХреЗ рд▓рд┐рдП рдЕрд╕реЗрдВрдмрд▓рд░
- рдХрд▓рд╛рд╢реНрдирд┐рдХреЛрд╡ред рдЕрд╕реЗрдВрдмрд▓рд░ рдЖрд╕рд╛рди рд╣реИ!
- Tanenbaumред рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдоред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдФрд░ рд╡рд┐рдХрд╛рд╕ред
- рд░реЙрдмрд░реНрдЯ рд▓рд╡ред рд▓рд┐рдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рд╡рд┐рдХрд╛рд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рд╡рд┐рд╡рд░рдгред