nucleo
Nucleo di Calcolatori Elettronici
Caricamento in corso...
Ricerca in corso...
Nessun risultato
io.cpp
Vai alla documentazione di questo file.
1
8#include <costanti.h>
9#include <libce.h>
10#include <sys.h>
11#include <sysio.h>
12#include <io.h>
13
24
27
32void* operator new(size_t s)
33{
34 void* p;
35
37 p = alloc(s);
39
40 return p;
41}
42
52void* operator new(size_t s, std::align_val_t a)
53{
54 void* p;
55
56 if (static_cast<natq>(a) > DIM_PAGINA)
57 return phys_alloc(s, a);
58
60 p = alloc_aligned(s, a);
62 return p;
63}
64
68void operator delete(void* p)
69{
71 dealloc(p);
73}
74
81void operator delete(void *p, std::align_val_t a)
82{
83 if (static_cast<natq>(a) > DIM_PAGINA)
84 return phys_dealloc(p);
85
87 dealloc(p);
89}
90
91
100
114
117
120
125extern "C" void c_writeconsole(const char* buff, natq quanti)
126{
127 des_console* p_des = &console;
128
129 if (!access(buff, quanti, false, false)) {
130 flog(LOG_WARN, "writeconsole: parametri non validi: %p, %lu:", buff, quanti);
131 abort_p();
132 }
133
134 sem_wait(p_des->mutex);
135#ifndef AUTOCORR
136 for (natq i = 0; i < quanti; i++)
137 vid::char_write(buff[i]);
138#else /* AUTOCORR */
139 if (quanti > 0 && buff[quanti - 1] == '\n')
140 quanti--;
141 if (quanti > 0)
142 flog(LOG_USR, "%.*s", static_cast<int>(quanti), buff);
143#endif /* AUTOCORR */
144 sem_signal(p_des->mutex);
145}
146
147
153void startkbd_in(des_console* d, char* buff, natq dim)
154{
155 d->punt = buff;
156 d->cont = dim;
157 d->dim = dim;
159}
160
163
169extern "C" natq c_readconsole(char* buff, natq quanti)
170{
171 des_console* d = &console;
172 natq rv;
173
174 if (!access(buff, quanti, true)) {
175 flog(LOG_WARN, "readconsole: parametri non validi: %p, %lu:", buff, quanti);
176 abort_p();
177 }
178
179#ifdef AUTOCORR
180 return 0;
181#endif
182
183 if (!quanti)
184 return 0;
185
186 sem_wait(d->mutex);
187 startkbd_in(d, buff, quanti);
188 sem_wait(d->sincr);
189 rv = d->dim - d->cont;
190 sem_signal(d->mutex);
191 return rv;
192}
193
194
197{
198 des_console* d = &console;
199 char a;
200 bool fine;
201
202 for(;;) {
204
206
207 fine = false;
208 switch (a) {
209 case 0:
210 break;
211 case '\b':
212 if (d->cont < d->dim) {
213 d->punt--;
214 d->cont++;
215 vid::str_write("\b \b");
216 }
217 break;
218 case '\r':
219 case '\n':
220 fine = true;
221 *d->punt = '\0';
222 vid::str_write("\r\n");
223 break;
224 default:
225 *d->punt = a;
226 d->punt++;
227 d->cont--;
229 if (d->cont == 0) {
230 fine = true;
231 }
232 break;
233 }
234 if (fine)
235 sem_signal(d->sincr);
236 else
238 wfi();
239 }
240}
241
244
248extern "C" void c_iniconsole(natb cc)
249{
250 vid::clear(cc);
251}
252
253
255const int KBD_IRQ = 1;
256
261{
262 // blocchiamo subito le interruzioni generabili dalla tastiera
264
265 // svuotiamo il buffer interno della tastiera
266 kbd::drain();
267
269 flog(LOG_ERR, "kbd: impossibile creare estern_kbd");
270 return false;
271 }
272 flog(LOG_INFO, "kbd: tastiera inizializzata");
273 return true;
274}
275
280{
281 vid::clear(0x07);
282 flog(LOG_INFO, "vid: video inizializzato");
283 return true;
284}
285
290{
291 des_console* d = &console;
292
293 if ( (d->mutex = sem_ini(1)) == 0xFFFFFFFF) {
294 flog(LOG_ERR, "console: impossibile creare mutex");
295 return false;
296 }
297 if ( (d->sincr = sem_ini(0)) == 0xFFFFFFFF) {
298 flog(LOG_ERR, "console: impossibile creare sincr");
299 return false;
300 }
301 return kbd_init() && vid_init();
302}
303
304
310
326
329
331const natb HD_IRQ = 14;
332
341bool prepare_prd(des_ata *d, natb* vett, natb quanti)
342{
343 natq n = quanti * DIM_BLOCK;
344 int i = 0;
345
346 while (n && i < MAX_PRD) {
347 paddr p = trasforma(vett);
348 natq r = DIM_PAGINA - (p % DIM_PAGINA);
349 if (r > n)
350 r = n;
351 d->prd[i] = p;
352 d->prd[i + 1] = r;
353
354 n -= r;
355 vett += r;
356 i += 2;
357 }
358 if (n)
359 return false;
360 d->prd[i - 1] |= 0x80000000;
361 return true;
362}
363
370void starthd_in(des_ata* d, natb vetti[], natl primo, natb quanti)
371{
372 d->cont = quanti;
373 d->punt = vetti;
375 hd::start_cmd(primo, quanti, hd::READ_SECT);
376}
377
380
386extern "C" void c_readhd_n(natb vetti[], natl primo, natb quanti)
387{
388 des_ata* d = &hard_disk;
389
390 if (!access(vetti, quanti * DIM_BLOCK, true)) {
391 flog(LOG_WARN, "readhd_n: parametri non validi: %p, %d", vetti, quanti);
392 abort_p();
393 }
394
395 if (!quanti)
396 return;
397
398 sem_wait(d->mutex);
399 starthd_in(d, vetti, primo, quanti);
400 sem_wait(d->sincr);
401 sem_signal(d->mutex);
402}
403
404
411void starthd_out(des_ata* d, natb vetto[], natl primo, natb quanti)
412{
413 d->cont = quanti;
414 d->punt = vetto + DIM_BLOCK;
416 hd::start_cmd(primo, quanti, hd::WRITE_SECT);
417 hd::output_sect(vetto);
418}
419
422
428extern "C" void c_writehd_n(natb vetto[], natl primo, natb quanti)
429{
430 des_ata* d = &hard_disk;
431
432 if (!access(vetto, quanti * DIM_BLOCK, false)) {
433 flog(LOG_WARN, "writehd_n: parametri non validi: %p, %d", vetto, quanti);
434 abort_p();
435 }
436
437 if (!quanti)
438 return;
439
440 sem_wait(d->mutex);
441 starthd_out(d, vetto, primo, quanti);
442 sem_wait(d->sincr);
443 sem_signal(d->mutex);
444}
445
446
453void dmastarthd_in(des_ata* d, natb vetti[], natl primo, natb quanti)
454{
455 if (!prepare_prd(d, vetti, quanti)) {
456 flog(LOG_ERR, "dmastarthd_in: numero di PRD insufficiente");
457 sem_signal(d->sincr);
458 return;
459 }
460
462 d->cont = 1;
463 paddr prd = trasforma(d->prd);
464 bm::prepare(prd, false);
465 hd::start_cmd(primo, quanti, hd::READ_DMA);
466 bm::start();
467}
468
471
477extern "C" void c_dmareadhd_n(natb vetti[], natl primo, natb quanti)
478{
479 des_ata* d = &hard_disk;
480
481 if (quanti * DIM_BLOCK > MAX_PRD * DIM_PAGINA) {
482 flog(LOG_WARN, "readhd_n: quanti %d troppo grande", quanti);
483 abort_p();
484 }
485
486 if (!access(vetti, quanti * DIM_BLOCK, true)) {
487 flog(LOG_WARN, "dmareadhd_n: parametri non validi: %p, %d", vetti, quanti);
488 abort_p();
489 }
490
491 if (!quanti)
492 return;
493
494 sem_wait(d->mutex);
495 dmastarthd_in(d, vetti, primo, quanti);
496 sem_wait(d->sincr);
497 sem_signal(d->mutex);
498}
499
500
507void dmastarthd_out(des_ata* d, natb vetto[], natl primo, natb quanti)
508{
509 if (!prepare_prd(d, vetto, quanti)) {
510 flog(LOG_ERR, "dmastarthd_out: numero di PRD insufficiente");
511 sem_signal(d->sincr);
512 return;
513 }
514
516 d->cont = 1; // informazione per il driver
517 paddr prd = trasforma(d->prd);
518 bm::prepare(prd, true);
519 hd::start_cmd(primo, quanti, hd::WRITE_DMA);
520 bm::start();
521}
522
525
531extern "C" void c_dmawritehd_n(natb vetto[], natl primo, natb quanti)
532{
533 des_ata* d = &hard_disk;
534
535 if (quanti * DIM_BLOCK > MAX_PRD * DIM_PAGINA) {
536 flog(LOG_WARN, "readhd_n: quanti %d troppo grande", quanti);
537 abort_p();
538 }
539
540 if (!access(vetto, quanti * DIM_BLOCK, false)) {
541 flog(LOG_WARN, "dmawritehd_n: parametri non validi: %p, %d", vetto, quanti);
542 abort_p();
543 }
544
545 if (!quanti)
546 return;
547
548 sem_wait(d->mutex);
549 dmastarthd_out(d, vetto, primo, quanti);
550 sem_wait(d->sincr);
551 sem_signal(d->mutex);
552}
553
554
557{
558 des_ata* d = &hard_disk;
559 for(;;) {
560 d->cont--;
561 hd::ack();
562 switch (d->comando) {
563 case hd::READ_SECT:
565 d->punt += DIM_BLOCK;
566 break;
567 case hd::WRITE_SECT:
568 if (d->cont != 0) {
570 d->punt += DIM_BLOCK;
571 }
572 break;
573 case hd::READ_DMA:
574 case hd::WRITE_DMA:
575 bm::ack();
576 break;
577 }
578 if (d->cont == 0)
579 sem_signal(d->sincr);
580 wfi();
581 }
582}
583
588{
589 natl id;
590 natb bus = 0, dev = 0, fun = 0;
591 des_ata* d;
592
593 d = &hard_disk;
594
595 if ( (d->mutex = sem_ini(1)) == 0xFFFFFFFF) {
596 flog(LOG_ERR, "hd: impossibile creare mutex");
597 return false;
598 }
599 if ( (d->sincr = sem_ini(0)) == 0xFFFFFFFF) {
600 flog(LOG_ERR, "hd: impossibile creare sincr");
601 return false;
602 }
603
604 if (!bm::find(bus, dev, fun)) {
605 flog(LOG_WARN, "hd: bus master non trovato");
606 return false;
607 }
608
609 if ( (d->prd = new (std::align_val_t{65536}) natl[2 * MAX_PRD]) == nullptr) {
610 flog(LOG_WARN, "hd: impossibile allocare vettore di PRD");
611 return false;
612 }
613
614 flog(LOG_INFO, "bm: %02x:%02x.%1d", bus, dev, fun);
615 bm::init(bus, dev, fun);
616
618 if (id == 0xFFFFFFFF) {
619 flog(LOG_ERR, "hd: impossibile creare proc. esterno");
620 return false;
621 }
622
624
625 return true;
626}
627
628
633
635extern "C" char _end[];
636
640extern "C" bool fill_io_gates();
641
651extern "C" void main_io(natq p)
652{
653 int *p_io_init_done = ptr_cast<int>(p);
654
657 if (ioheap_mutex == 0xFFFFFFFF) {
658 flog(LOG_ERR, "impossible creare semaforo ioheap_mutex");
659 abort_p();
660 }
661 char* end_ = allinea_ptr(_end, DIM_PAGINA);
662 heap_init(end_, DIM_IO_HEAP);
663 flog(LOG_INFO, "Heap del modulo I/O: %llxB [%p, %p)", DIM_IO_HEAP,
664 end_, end_ + DIM_IO_HEAP);
665 flog(LOG_INFO, "Inizializzo la console (kbd + vid)");
666 if (!console_init()) {
667 flog(LOG_ERR, "inizializzazione console fallita");
668 abort_p();
669 }
670 flog(LOG_INFO, "Inizializzo la gestione dell'hard disk");
671 if (!hd_init()) {
672 flog(LOG_ERR, "inizializzazione hard disk fallita");
673 abort_p();
674 }
675 *p_io_init_done = 1;
676 terminate_p();
677}
678
679
685
690{
691 natq rv;
693 rv = disponibile();
695 return rv;
696}
697
File incluso da tutti i moduli, sia nella parte C++ che nella parte assembler.
#define INTR_TIPO_KBD
tastiera
Definition costanti.h:77
#define DIM_IO_HEAP
dimensione dello heap del modulo I/O
Definition costanti.h:23
#define MIN_EXT_PRIO
priorità minima dei processi esterni
Definition costanti.h:15
#define INTR_TIPO_HD
hard disk
Definition costanti.h:78
#define MAX_PRD
numero massimo di PRD usati da dmaread/dmawrite
Definition costanti.h:27
unsigned long natq
unsigned long paddr
void dmastarthd_in(des_ata *d, natb vetti[], natl primo, natb quanti)
Avvia una operazione di ingresso in DMA dall'hard disk.
Definition io.cpp:453
void starthd_out(des_ata *d, natb vetto[], natl primo, natb quanti)
Avvia una operazione di uscita verso l'hard disk.
Definition io.cpp:411
void estern_hd(natq)
Processo esterno per le richieste di interruzione dell'hard disk.
Definition io.cpp:556
const natb HD_IRQ
Piedino dell'APIC per le richieste di interruzione dell'hard disk.
Definition io.cpp:331
bool prepare_prd(des_ata *d, natb *vett, natb quanti)
Prepara i descrittori per il Bus Mastering.
Definition io.cpp:341
bool hd_init()
Inizializza il sottosistema per la gestione dell'hard disk.
Definition io.cpp:587
void starthd_in(des_ata *d, natb vetti[], natl primo, natb quanti)
Avvia una operazione di ingresso dall'hard disk.
Definition io.cpp:370
void dmastarthd_out(des_ata *d, natb vetto[], natl primo, natb quanti)
Avvia una operazione di uscita in DMA verso l'hard disk.
Definition io.cpp:507
des_ata hard_disk
Descrittore dell'unico hard disk installato nel sistema.
Definition io.cpp:328
void c_dmareadhd_n(natb vetti[], natl primo, natb quanti)
Parte C++ della primitiva dmareadhd_n().
Definition io.cpp:477
void c_readhd_n(natb vetti[], natl primo, natb quanti)
Parte C++ della primitiva readhd_n().
Definition io.cpp:386
void c_dmawritehd_n(natb vetto[], natl primo, natb quanti)
Parte C++ della primitiva dmawritehd_n().
Definition io.cpp:531
void c_writehd_n(natb vetto[], natl primo, natb quanti)
Parte C++ della primitiva writehd_n().
Definition io.cpp:428
des_console console
Unica istanza di des_console.
Definition io.cpp:116
bool kbd_init()
Inizializza la tastiera.
Definition io.cpp:260
bool vid_init()
Inizializza il video (modalità testo)
Definition io.cpp:279
void estern_kbd(natq)
Processo esterno associato alla tastiera.
Definition io.cpp:196
void startkbd_in(des_console *d, char *buff, natq dim)
Avvia una operazione di lettura dalla tastiera.
Definition io.cpp:153
const int KBD_IRQ
Piedino dell'APIC per le richieste di interruzione della tastiera.
Definition io.cpp:255
bool console_init()
Inizializza la console (tastiera + video)
Definition io.cpp:289
natq c_readconsole(char *buff, natq quanti)
Parte C++ della primitiva readconsole()
Definition io.cpp:169
void c_iniconsole(natb cc)
Parte C++ della primitiva iniconsole()
Definition io.cpp:248
void c_writeconsole(const char *buff, natq quanti)
Parte C+++ della primitiva writeconsole()
Definition io.cpp:125
#define LIV_SISTEMA
#define DIM_PAGINA
#define DIM_BLOCK
void * alloc_aligned(size_t dim, std::align_val_t align)
void * alloc(size_t dim)
size_t disponibile()
void dealloc(void *p)
void heap_init(void *start, size_t size)
natq c_getiomeminfo()
Parte C++ della primitiva getiomeminfo()
Definition io.cpp:689
natl ioheap_mutex
Indice del semaforo di mutua esclusione per lo heap I/O.
Definition io.cpp:26
void main_io(natq p)
Corpo del processo main I/O.
Definition io.cpp:651
char _end[]
Ultimo indirizzo utilizzato dal modulo I/O (fornito dal collegatore)
Definition io.cpp:635
bool fill_io_gates()
Riempie i gate della IDT relativi alle primitive fornite dal modulo I/O.
unsigned char natb
unsigned int natl
void flog(log_sev sev, const char *fmt,...)
static T * allinea_ptr(T *p, natq a)
static To * ptr_cast(From v)
LOG_ERR
LOG_USR
LOG_INFO
LOG_WARN
paddr trasforma(paddr root_tab, vaddr v)
Primitive fornite dal modulo I/O.
void ack()
bool find(natb &bus, natb &dev, natb &fun)
void start()
void init(natb bus, natb dev, natb fun)
void prepare(paddr prd, bool write)
void output_sect(natb *buf)
void enable_intr()
void input_sect(natb *buf)
void start_cmd(natl lba, natb quanti, cmd cmd)
void ack()
READ_SECT
WRITE_DMA
WRITE_SECT
READ_DMA
void enable_intr()
void drain()
void disable_intr()
char char_read_intr()
void char_write(char c)
void clear()
void str_write(const char str[])
Descrittore di interfaccia ATA.
Definition io.cpp:312
natb * punt
Da dove leggere/dove scrivere il prossimo settore.
Definition io.cpp:322
natl * prd
Array dei descrittori per il Bus Mastering.
Definition io.cpp:324
natl sincr
Indice di un semaforo di sincronizzazione.
Definition io.cpp:318
natb comando
Ultimo comando inviato all'interfaccia.
Definition io.cpp:314
natb cont
Quanti settori resta da leggere o scrivere.
Definition io.cpp:320
natl mutex
Indice di un semaforo di mutua esclusione.
Definition io.cpp:316
Descrittore della console.
Definition io.cpp:102
natq dim
Dimensione del buffer passato a readconsole()
Definition io.cpp:112
natl mutex
Semaforo di mutua esclusione per l'accesso alla console.
Definition io.cpp:104
natl sincr
Semafor di sincronizzazione (per le letture da tastiera)
Definition io.cpp:106
natq cont
Quanti caratteri resta da leggere.
Definition io.cpp:110
char * punt
Dove scrivere il prossimo carattere letto.
Definition io.cpp:108
Primitive comuni definite dal modulo sistema.
natl sem_ini(int val)
Crea un nuovo semaforo.
void sem_wait(natl sem)
Estrae un gettone da un semaforo.
void abort_p()
Abortisce il processo corrente.
void sem_signal(natl sem)
Inserisce un gettone in un semaforo.
void terminate_p()
Termina il processo corrente.
Primitive realizzate dal modulo sistema e riservate al modulo I/O.
void phys_dealloc(void *ptr)
Dealloca memoria allocata tramite phys_alloc().
natl activate_pe(void f(natq), natq a, natl prio, natl liv, natb irq)
Crea un processo esterno.
bool access(const void *start, natq dim, bool writeable, bool shared=true)
Verifica dei problemi di Cavallo di Troia.
void * phys_alloc(size_t size, std::align_val_t align)
Alloca memoria che sia allineata in memoria fisica.
void wfi()
Attende la prossima richiesta di interruzione.