summaryrefslogtreecommitdiff
path: root/2003/i/buzz/src/busp/busp.cc
blob: d830a3090a66a82951bee11dc18dfe5eec0bc11f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// busp.cc
// buzz - Programme du robot Efrei Robotique I1-I2 2003
// Copyright (C) 2003 Nicolas Schodet
//
#include "busp.h"
#include "kernel/pbus.h"

#include "erreur/erreur.h"

#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <iostream>	//Debug

#define BUSP_FILE "/dev/robotbusp"

// Pointeur vers l'instance unique.
Busp *Busp::m_instance = 0;

// Initialise le busp, open (), signal ().
Busp::Busp ()
{
    // Sauvegarde le pointeur d'instance.
    m_instance = this;
    // Ouvre le p�riph�rique.
    m_fd = open (BUSP_FILE, O_RDONLY);
    if (m_fd == -1)
	throw ErreurFatale ("Impossible d'ouvrir le p�riph�rique du bus"
			    " parall�le.\n");
    // Param�tre le handler de signaux.
    struct sigaction sa;
    sa.sa_handler = irq;
    sigemptyset (&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    sigaction (SIGUSR1, &sa, 0);	// Il n'y aura pas d'erreur, cf doc.
    // Active les interruptions.
    sti ();
    // Remplis le tableau d'inversion des donn�es.
    // Les fils sont soud�s � l'envers.
    for (int i = 0; i < 256; ++i)
      {
	m_inverse[i] =
	      (i << 7) & (1 << 7)
	    | (i << 5) & (1 << 6)
	    | (i << 3) & (1 << 5)
	    | (i << 1) & (1 << 4)
	    | (i >> 1) & (1 << 3)
	    | (i >> 3) & (1 << 2)
	    | (i >> 5) & (1 << 1)
	    | (i >> 7) & (1 << 0);
      }
}

// Destructeur.
Busp::~Busp ()
{
    // D�sactive les interruptions.
    cli ();
    // Ignore les signaux, on sait jammais.
    struct sigaction sa;
    sa.sa_handler = SIG_IGN;
    sigemptyset (&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    sigaction (SIGUSR1, &sa, 0);
    // Ferme le p�riph�rique.
    close (m_fd);
    // Efface le pointeur d'instance.
    m_instance = 0;
}

// Active les interruptions.
void
Busp::sti (void)
{
    ioctl (m_fd, PBUS_INTENABLE);
}

// D�sactive les interruptions.
void
Busp::cli (void)
{
    ioctl (m_fd, PBUS_INTDISABLE);
}

// Traite le signal envoy� par le kernel lors d'une interruption.
void
Busp::irq (int sig)
{
    Busp &busp = Busp::getInstance ();
    // D�sactivation des interuptions automatique.
    // R�cup�re le num�ro d'int�ruption.
    struct pbus_io io;
    ioctl (busp.m_fd, PBUS_INTREAD, &io);
    cout << "irq " << (int) io.ints << endl;
    // Sous-traite l'interruption.
    if (io.ints & BuspIr::m_irqMask)
	busp.m_ir.irq ();
    // Active � nouveau.
    busp.sti ();
}

// Ecrire sur le bus.
void
Busp::write (int addr, int data)
{
    struct pbus_io io;
    io.addr = addr;
    io.data = m_inverse[data];
    ioctl (m_fd, PBUS_WRITE, &io);
    cout << "write " << addr << " " << data << endl;
}

// Lire sur le bus.
int
Busp::read (int addr)
{
    struct pbus_io io;
    io.addr = addr;
    ioctl (m_fd, PBUS_READ, &io);
    cout << "read " << addr << " = " << (int) m_inverse[io.data] << endl;
    return m_inverse[io.data];
}