Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
 
2
/*
3
 Nome File : pxc.c
4
 Autore : Danilo Dealberti
5
          Claudio Melita
6
 Data : 16-11-1999
7
 Descrizione : modulo di implementazione delle funzioni del PXC200
8
 Modifiche :
9
*/
10
/*
11
 Note :
12
 Il seguente modulo permette Š in grado di supportare ogni frame grabber
13
 dotato del controllore single-chip Bt848/Bt848A/Bt849 della BrookTree (ora
14
 Conexant)
15
 Per variare la risoluzione di acquisizione o il formato dei dati in ingresso
16
 vanno variati i parametri contenuti nel seguente modulo , il quale Š
17
 specifico per immagini di 384x288 pixel codificate a 8 livelli di grigio
18
 Le modifiche possono essere effettuate consultando il manuale di descrizione del
19
 chip Bt848 disponibile al sito www.Conexant.com
20
*/
21
 
22
#include <kernel/func.h>
23
#include <sys/types.h>
24
#include <drivers/pci.h>
25
#include <drivers/pxc.h>
26
#include <drivers/llpci.h>
27
#include "../../drivers/pci/linuxpci.h"
28
 
29
#define appl2linear(x) (x)
30
 
31
// Prototipi locali
32
void PXC_fast(void);
33
void Generate_Program(DWORD *B1);
34
void Modify_Program(DWORD *B1);
35
 
36
// Variabili locali al modulo
37
static DWORD BaseAddr;
38
static BYTE IntLine;
39
static unsigned char *Corpo;
40
static unsigned char V_Corpo[7000];
41
static DWORD *Pun;
42
static DWORD Programma;
43
static DWORD Buffer1;
44
static int errore;
45
static PXC_Listeners Lista;
46
static BYTE bus,dev;
47
static TIME per;
48
static TIME Fotogramma;
49
static DWORD old;
50
static CAB Depositi;
51
static unsigned char *pointer;
52
 
53
 
54
TIME PXC_Initiate(int number) {
55
   struct pci_regs *reg;                  
56
   unsigned register int i;
57
   BYTE dep;
58
   DWORD dw;
59
//   MODEL m=BASE_MODEL;
60
//   TIME wcet;
61
 
62
 
63
   reg=NULL;
64
   if (pci_init()==1) {
65
      reg = (struct pci_regs *) pci_class((0x0400) << 8,0,&bus,&dev) ;
66
      if (reg != NULL) {
67
         // Ottiene l' indirizzo di base del frame grabber
68
         BaseAddr = (reg->IoBaseAddress-0x08); ;
69
         IntLine = reg->InterruptLine; // Ottiene la linea di interrupt
70
      } else {
71
         errore = 1;
72
         return 0;
73
      }
74
   } else {
75
      errore =2;
76
      return 0;
77
   }
78
 
79
   pcibios_read_config_dword(bus,dev,PCI_COMMAND,&dw);
80
   old=dw;
81
   dw |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER) ; // Abilita il mastering del BUS PCI e anche la mappatura in memoria
82
   pcibios_write_config_dword(bus,dev,PCI_COMMAND,dw);
83
 
84
   // Controllo della presenza di video input
85
   dep = (BYTE) lmempeekb((void *)(BaseAddr+PXC_DSTATUS));
86
 
87
   if (dep & 0x80) {
88
 
89
     // Creazione del CAB in base al numero di processi interessati
90
     Depositi = cab_create("",PXC_MAXX*PXC_MAXY*sizeof(unsigned char),number+2);
91
     if (Depositi<0) return 0;
92
 
93
      // Autoformat detected enabled
94
      lmempokeb((void *)(BaseAddr+PXC_IOFORM),0x58);
95
 
96
      // Fattore di scala orizzontale 2:1
97
      lmempokeb((void *)(BaseAddr+ PXC_E_HSCALE_HI),0x16);
98
      lmempokeb((void *)(BaseAddr+ PXC_E_HSCALE_LO),0x79);
99
      lmempokeb((void *)(BaseAddr+ PXC_O_HSCALE_HI),0x16);
100
      lmempokeb((void *)(BaseAddr+ PXC_O_HSCALE_LO),0x79);
101
 
102
      // Fattore di scala verticale 1:1
103
      lmempokeb((void *)(BaseAddr+ PXC_E_VSCALE_HI),0x60);
104
      lmempokeb((void *)(BaseAddr+ PXC_E_VSCALE_LO),0);
105
      lmempokeb((void *)(BaseAddr+ PXC_O_VSCALE_HI),0x60);
106
      lmempokeb((void *)(BaseAddr+ PXC_O_VSCALE_LO),0);
107
 
108
      // Numero di pixel orizzontali formanti l'immagine
109
      lmempokeb((void *)(BaseAddr+ PXC_E_HACTIVE_LO),0x80);
110
      lmempokeb((void *)(BaseAddr+ PXC_O_HACTIVE_LO),0x80);
111
 
112
      // Numero di pixel verticali formanti l'immagine
113
      lmempokeb((void *)(BaseAddr+ PXC_E_VACTIVE_LO),0x40);
114
      lmempokeb((void *)(BaseAddr+ PXC_O_VACTIVE_LO),0x40);
115
 
116
      // Temporizzazione verticale
117
      lmempokeb((void *)(BaseAddr+ PXC_E_VDELAY_LO),0x20);
118
      lmempokeb((void *)(BaseAddr+ PXC_O_VDELAY_LO),0x20);
119
 
120
      // Tempozizzazione Orizzontale
121
      lmempokeb((void *)(BaseAddr+ PXC_E_HDELAY_LO),0x4d);
122
      lmempokeb((void *)(BaseAddr+ PXC_O_HDELAY_LO),0x4d);
123
 
124
      // Parte alta di VACTIVE HACTIVE VDELAY HDELAY
125
      lmempokeb((void *)(BaseAddr+ PXC_E_CROP), 0x21);
126
      lmempokeb((void *)(BaseAddr+ PXC_O_CROP),0x21);
127
 
128
      // Temporizzazione del convertitore ADC e del periodo di burst
129
      lmempokeb((void *)(BaseAddr+ PXC_ADELAY),0x7f);
130
      lmempokeb((void *)(BaseAddr+ PXC_BDELAY),0x72);
131
 
132
      // Setta l'acquisizione a 8 livelli di grigio
133
      lmempokeb((void *)(BaseAddr+ PXC_COLOR_FMT), 0x66);
134
 
135
      // Generazione del programma nel buffer ottenuto dal CAB
136
      pointer = cab_reserve(Depositi);
137
      Generate_Program((DWORD *)pointer);
138
 
139
     // Cattura Full-Frame , sia even che odd field
140
     lmempokeb((void *)(BaseAddr+PXC_CAP_CTL),0x13);
141
 
142
     // Abilitazione delle interruzioni
143
     lmempoked((void *)(BaseAddr+PXC_INT_MASK),0x00001800);
144
 
145
     // Inserimento dell' indirizzo del programma RISC all' interno del
146
     // canale DMA
147
     lmempoked((void *)(BaseAddr+PXC_RISC_STRT_ADD),Programma);
148
 
149
     } else {
150
         errore=3;
151
         return 0;
152
     }
153
 
154
     // Inizializzazione della struttura dati utilizzata per
155
     // aggiungere processi ascoltatori dell' immagine
156
 
157
    for(i=0;i<PXC_MAX_LISTENERS;i++) {
158
         Lista.Elementi[i].proc=NIL;
159
         Lista.Elementi[i].DRel = 0;
160
    }
161
    Lista.Top=0;
162
 
163
    per = PXC_FRAME_TIME; // Ritorno periodo in us
164
 
165
    Fotogramma=0;
166
 
167
    return per;
168
}
169
/**************************************************************************/
170
void PXC_Start(void) {
171
   handler_set(IntLine, (void (*)(int))PXC_fast, NIL);
172
   lmempokew((void *)(BaseAddr+PXC_GPIO_DMA_CTL),0x0000);
173
   lmempokew((void *)(BaseAddr+PXC_GPIO_DMA_CTL),0x0003);
174
}
175
 
176
/**************************************************************************/
177
 
178
int PXC_Push_Listener(PID l, int drel)
179
{
180
   int pele;
181
 
182
   if (l == NIL) return 0;
183
   if (Lista.Top == PXC_MAX_LISTENERS) {
184
      errore=4;
185
      return 0; // Non vi sono pi— elementi liberi
186
   }
187
 
188
 
189
   pele = Lista.Top;
190
   Lista.Top++;
191
 
192
 // Setta tutto ci• che serve per il nuovo elemento
193
   Lista.Elementi[pele].proc=l;
194
   Lista.Elementi[pele].DRel = drel;
195
 
196
   return 1;
197
}
198
/**************************************************************************/
199
 
200
int PXC_Pop_Listener()
201
{
202
   if (Lista.Top > 0) {
203
      Lista.Top --;
204
      return 1;
205
   }
206
   return 0;
207
}
208
/**************************************************************************/
209
void PXC_Close(void)
210
{
211
//   DWORD dw;
212
 
213
 // Ferma il DMA
214
   lmempokew((void *)(BaseAddr+PXC_GPIO_DMA_CTL),0x0000);
215
   pcibios_write_config_dword(bus,dev,PCI_COMMAND,old);
216
 
217
   handler_remove(IntLine);
218
   for(;PXC_Pop_Listener();) ; // Li toglie tutti
219
 
220
   // Rimozione del CAB
221
   cab_delete(Depositi);
222
 
223
}
224
/*************************************************************************/
225
void PXC_fast(void) {
226
   DWORD pen;
227
   register int i;
228
 
229
   pen=lmempeekd((void *)(BaseAddr+PXC_INT_STAT));
230
 
231
   if (pen & 0x00000800) {
232
 
233
         // COMMIT al CAB
234
      cab_putmes(Depositi,pointer);
235
 
236
      // Interrompi il programma RISC
237
      lmempokew((void *)(BaseAddr+PXC_GPIO_DMA_CTL),0x0000);
238
 
239
      // Crea il nuovo programma in memoria dopo aver riservato il nuovo
240
      // CAB
241
      pointer=cab_reserve(Depositi);
242
 
243
      Modify_Program((DWORD *)pointer);
244
 
245
      // Riabilita il programma
246
      lmempokew((void *)(BaseAddr+PXC_GPIO_DMA_CTL),0x0003);
247
 
248
 
249
      Fotogramma++;
250
 
251
      // Attivazione dei task nel fast handler direttamente, visto il suo
252
      // tempo di esecuzione molto ridotto (decine di microsec contro un
253
      // interrupt period di 20 millisec )
254
      for(i=0;i<Lista.Top;i++)
255
 
256
         if (!(Fotogramma % Lista.Elementi[i].DRel)) {
257
           LEVEL l;
258
           PID p = Lista.Elementi[i].proc;
259
 
260
           if (proc_table[p].control & FREEZE_ACTIVATION)
261
             proc_table[p].frozen_activations++;
262
           else {
263
             l = proc_table[p].task_level;
264
             level_table[l]->task_activate(l,p);
265
             event_need_reschedule();
266
           }
267
 
268
//           task_activate(Lista.Elementi[i].proc);
269
         }
270
 
271
 
272
    } else {
273
  // C'Š un errore nell' acquisizione, per ora non lo trattiamo
274
    }
275
 
276
    lmempoked((void *)(BaseAddr+PXC_INT_STAT),pen); // EOI al Bt848
277
 
278
}
279
 
280
/*************************************************************************/
281
void Generate_Program(DWORD *B1)
282
 
283
{
284
 unsigned register int i;
285
 
286
      // Definizione del programma all' interno dello spazio di memoria puntato
287
      // da Programma , va DWORD aligned , quindi prima lo allineamo, poi
288
      // andiamo a scriverci dentro il programma, il quale pu• essere variabile
289
      // in funzione delle opzioni di ingresso
290
      Corpo = V_Corpo;
291
      Programma = appl2linear(Corpo);
292
      if (Programma % 4) {
293
         unsigned char diff;
294
 
295
        // Procediamo all' allineamento del buffer
296
         diff = (unsigned char)(((Programma / 4)+1) * 4 -Programma);
297
         Programma += diff;
298
         Corpo += diff;  // Anche il puntatore del buffer va aumentato
299
      }
300
 
301
      // Si innesca sempre da qui
302
      Pun = (DWORD *) Corpo;
303
 
304
      Buffer1 = appl2linear(B1);
305
      //Buffer2 = appl2linear(B2);
306
 
307
      (*Pun)=PXC_SYNC | PXC_FM1 ;
308
      Pun++;
309
      (*Pun)=0;
310
 
311
      for(i=0;i< PXC_MAXY;i++)
312
      {
313
         Pun++;
314
         (*Pun) = PXC_WRITE | PXC_SET_SOL | PXC_SET_EOL | PXC_MAXX ;
315
         Pun++;
316
         (*Pun)=(Buffer1+ i* PXC_MAXX);
317
      }
318
 
319
      Pun++;
320
      (*Pun) = PXC_SYNC | PXC_VRE | PXC_SET_IRQ ;
321
      Pun++;
322
      (*Pun) = 0;
323
 
324
      Pun++;
325
      (*Pun) = PXC_SYNC | PXC_FM1   ;
326
      Pun++;
327
      (*Pun) = 0;
328
      // Write mettendo SOL e EOL e come byte count 768 , come indirizzo
329
      // quello del buffer per il campo dispari
330
 
331
      for(i=0; i<PXC_MAXY; i++) {
332
         Pun++;
333
         (*Pun) = PXC_WRITE | PXC_SET_SOL | PXC_SET_EOL | PXC_MAXX ;
334
         Pun++;
335
         (*Pun)=(/*Buffer2*/Buffer1+i*PXC_MAXX);
336
      }
337
 
338
      Pun++;
339
      (*Pun) = PXC_SYNC | PXC_VRO ;
340
      Pun++;
341
      (*Pun)=0;
342
 
343
 
344
      // Jump all' indirizzo contenuto in programma e interrupt
345
      Pun++;
346
      (*Pun) = PXC_JUMP | PXC_SET_IRQ ;
347
      Pun++;
348
      (*Pun) = Programma;
349
 
350
     // Fine programma di istruzione del RISC DMA channels
351
}
352
/*********************************************************************/
353
void Modify_Program(DWORD *B1)
354
 
355
{
356
 unsigned register int i;
357
 
358
      // Si innesca sempre da qui
359
      Pun = (DWORD *) Corpo;
360
 
361
      Buffer1 = appl2linear(B1);
362
 
363
      Pun++;
364
 
365
      for(i=0;i< PXC_MAXY;i++)
366
      {
367
         Pun+=2;
368
         (*Pun)=(Buffer1+ i* PXC_MAXX);
369
      }
370
 
371
      Pun+=4;
372
      for(i=0; i<PXC_MAXY; i++) {
373
         Pun+=2;
374
         (*Pun)=(Buffer1+i*PXC_MAXX);
375
      }
376
 
377
     // Fine programma di istruzione del RISC DMA channels
378
}
379
/****************************************************************************/
380
CAB PXC_GetCab(void)
381
{
382
 return Depositi;
383
}