UDI/meta_bus - Switch to MEI
[tpg/acess2.git] / KernelLand / Modules / Interfaces / UDI / udi_lib / physio / pio.c
1 /**
2  * \file udi_lib/physio/pio.c
3  * \author John Hodge (thePowersGang)
4  */
5 #define DEBUG   0
6 #include <udi.h>
7 #include <udi_physio.h>
8 #include <acess.h>
9 #include <udi_internal.h>
10
11 typedef void    _udi_pio_do_io_op_t(uint32_t child_ID, udi_ubit32_t regset_idx, udi_ubit32_t ofs, size_t len,
12         void *data, bool isOutput);
13
14 // === STRUCTURES ===
15 struct udi_pio_handle_s
16 {
17         tUDI_DriverInstance     *Inst;
18         udi_index_t     RegionIdx;
19
20         _udi_pio_do_io_op_t     *IOFunc;
21         udi_ubit32_t    ChildID;
22         udi_index_t     RegSet;
23         
24         udi_ubit32_t    Offset;
25         udi_ubit32_t    Length;
26         
27         size_t  nTransOps;
28         udi_pio_trans_t *TransOps;
29         
30         udi_ubit16_t    PIOAttributes;
31         udi_ubit32_t    Pace;
32         udi_index_t     Domain;
33
34         // TODO: Cached labels
35 //      size_t  Labels[];
36 };
37
38 // === IMPORTS ===
39 extern _udi_pio_do_io_op_t      pci_pio_do_io;
40
41 // === EXPORTS ===
42 EXPORT(udi_pio_map);
43 EXPORT(udi_pio_unmap);
44 EXPORT(udi_pio_atmic_sizes);
45 EXPORT(udi_pio_abort_sequence);
46 EXPORT(udi_pio_trans);
47 EXPORT(udi_pio_probe);
48
49 // === CODE ===
50 void udi_pio_map(udi_pio_map_call_t *callback, udi_cb_t *gcb,
51         udi_ubit32_t regset_idx, udi_ubit32_t base_offset, udi_ubit32_t length,
52         udi_pio_trans_t *trans_list, udi_ubit16_t list_length,
53         udi_ubit16_t pio_attributes, udi_ubit32_t pace, udi_index_t serialization_domain)
54 {
55         LOG("gcb=%p,regset_idx=%i,base_offset=0x%x,length=0x%x,trans_list=%p,list_length=%i,...",
56                 gcb, regset_idx, base_offset, length, trans_list, list_length);
57         char bus_type[16] = {0};
58         udi_instance_attr_type_t        type;
59         type = udi_instance_attr_get_internal(gcb, "bus_type", 0, bus_type, sizeof(bus_type), NULL);
60         if(type != UDI_ATTR_STRING) {
61                 Log_Warning("UDI", "No/invalid bus_type attribute");
62                 callback(gcb, UDI_NULL_PIO_HANDLE);
63                 return ;
64         }
65
66
67         _udi_pio_do_io_op_t     *io_op;
68         if( strcmp(bus_type, "pci") == 0 ) {
69                 // Ask PCI binding
70                 io_op = pci_pio_do_io;
71         }
72         else {
73                 // Oops, unknown
74                 Log_Warning("UDI", "Unknown bus type %s", bus_type);
75                 callback(gcb, UDI_NULL_PIO_HANDLE);
76                 return ;
77         }
78
79         udi_pio_handle_t ret = malloc( sizeof(struct udi_pio_handle_s) );
80         ret->Inst = UDI_int_ChannelGetInstance(gcb, false, &ret->RegionIdx);
81         ret->ChildID = ret->Inst->ParentChildBinding->ChildID;
82         ret->RegSet = regset_idx;
83         ret->IOFunc = io_op;
84         ret->Offset = base_offset;
85         ret->Length = length;
86         ret->TransOps = trans_list;
87         // TODO: Pre-scan to get labels
88         ret->nTransOps = list_length;
89         ret->PIOAttributes = pio_attributes;
90         ret->Pace = pace;
91         // TODO: Validate serialization_domain
92         ret->Domain = serialization_domain;
93         
94         callback(gcb, ret);
95 }
96
97 void udi_pio_unmap(udi_pio_handle_t pio_handle)
98 {
99         UNIMPLEMENTED();
100 }
101
102 udi_ubit32_t udi_pio_atmic_sizes(udi_pio_handle_t pio_handle)
103 {
104         UNIMPLEMENTED();
105         return 0;
106 }
107
108 void udi_pio_abort_sequence(udi_pio_handle_t pio_handle, udi_size_t scratch_requirement)
109 {
110         UNIMPLEMENTED();
111 }
112
113 size_t _get_label(udi_pio_handle_t pio_handle, udi_index_t label)
114 {
115         udi_pio_trans_t *ops = pio_handle->TransOps;
116         size_t  ip = 0;
117         if( label == 0 )
118                 return 0;
119         for( ; ip < pio_handle->nTransOps; ip ++ ) {
120                 if( ops[ip].pio_op == UDI_PIO_LABEL && ops[ip].operand == label )
121                         return ip;
122         }
123         return 0;
124 }
125
126 typedef union
127 {
128         udi_ubit32_t    words[32/4];;
129 } _trans_value_t;
130
131 void _zero_upper(int sizelog2, _trans_value_t *val)
132 {
133         switch(sizelog2)
134         {
135         case UDI_PIO_1BYTE:
136                 val->words[0] &= 0x00FF;
137         case UDI_PIO_2BYTE:
138                 val->words[0] &= 0xFFFF;
139         case UDI_PIO_4BYTE:
140                 val->words[1] = 0;
141         case UDI_PIO_8BYTE:
142                 val->words[2] = 0;
143                 val->words[3] = 0;
144         case UDI_PIO_16BYTE:
145                 val->words[4] = 0;
146                 val->words[5] = 0;
147                 val->words[6] = 0;
148                 val->words[7] = 0;
149         case UDI_PIO_32BYTE:
150                 break;
151         }
152 }
153
154 int _compare_zero(_trans_value_t *val, int sizelog2)
155 {
156          int    is_z=1;
157          int    is_n=0;
158         switch(sizelog2)
159         {
160         case UDI_PIO_32BYTE:
161                 is_z = is_z && (val->words[7] == 0);
162                 is_z = is_z && (val->words[6] == 0);
163                 is_z = is_z && (val->words[5] == 0);
164                 is_z = is_z && (val->words[4] == 0);
165         case UDI_PIO_16BYTE:
166                 is_z = is_z && (val->words[3] == 0);
167                 is_z = is_z && (val->words[2] == 0);
168         case UDI_PIO_8BYTE:
169                 is_z = is_z && (val->words[1] == 0);
170         case UDI_PIO_4BYTE:
171                 is_z = is_z && (val->words[0] == 0);
172                 is_n = (val->words[ (1<<sizelog2)/4-1 ] >> 31) != 0;
173                 break;
174         case UDI_PIO_2BYTE:
175                 is_z = (val->words[0] & 0xFFFF) == 0;
176                 is_n = (val->words[0] >> 15) != 0;
177                 break;
178         case UDI_PIO_1BYTE:
179                 is_z = (val->words[0] & 0xFFFF) == 0;
180                 is_n = (val->words[0] >> 7) != 0;
181                 break;
182         }
183         
184         return is_z | (is_n << 1);
185 }
186
187 static inline void _operation_shift_left(int sizelog2, _trans_value_t *dstval, int count)
188 {
189         const int nwords = (1<<sizelog2)/4;
190         ASSERTC(count, <=, 32);
191         if( sizelog2 <= UDI_PIO_4BYTE ) {
192                 dstval->words[0] <<= count;
193         }
194         else if( count == 0 ) {
195                 // nop
196         }
197         else if( count == 32 ) {
198                 for(int i = nwords - 1; i --; )
199                         dstval->words[i+1] = dstval->words[i];
200                 dstval->words[0] = 0;
201         }
202         else {
203                 for( int i = nwords - 1; i --; )
204                         dstval->words[i+1] = (dstval->words[i+1] << count)
205                                 | (dstval->words[i] >> (32 - count));
206                 dstval->words[0] = dstval->words[0] << count;
207         }
208         _zero_upper(sizelog2, dstval);
209 }
210 static inline void _operation_shift_right(int sizelog2, _trans_value_t *dstval, int count)
211 {
212         const int nwords = (1<<sizelog2)/4;
213         ASSERTC(count, <=, 32);
214         if( sizelog2 <= UDI_PIO_4BYTE ) {
215                 dstval->words[0] >>= count;
216         }
217         else if( count == 0 ) {
218                 // nop
219         }
220         else if( count == 32 ) {
221                 for(int i = 0; i < nwords-1; i++ )
222                         dstval->words[i] = dstval->words[i+1];
223                 dstval->words[nwords-1] = 0;
224         }
225         else {
226                 for(int i = 0; i < nwords-1; i++ )
227                         dstval->words[i] = (dstval->words[i] >> count)
228                                 | (dstval->words[i+1] << (32 - count));
229                 dstval->words[nwords-1] = dstval->words[nwords-1] >> count;
230         }
231         _zero_upper(sizelog2, dstval);
232 }
233 static inline void _operation_and(int sizelog2, _trans_value_t *dstval, const _trans_value_t *srcval)
234 {
235         for( int i = 0; i < ((1 <<sizelog2)+3)/4; i ++ )
236                 dstval->words[i] &= srcval->words[i];
237         _zero_upper(sizelog2, dstval);
238 }
239 static inline void _operation_or(int sizelog2, _trans_value_t *dstval, const _trans_value_t *srcval)
240 {
241         for( int i = 0; i < ((1 <<sizelog2)+3)/4; i ++ )
242                 dstval->words[i] |= srcval->words[i];
243         _zero_upper(sizelog2, dstval);
244 }
245 static inline void _operation_xor(int sizelog2, _trans_value_t *dstval, const _trans_value_t *srcval)
246 {
247         for( int i = 0; i < ((1 <<sizelog2)+3)/4; i ++ )
248                 dstval->words[i] ^= srcval->words[i];
249         _zero_upper(sizelog2, dstval);
250 }
251 static inline void _operation_add(int sizelog2, _trans_value_t *dstval, const _trans_value_t *srcval)
252 {
253          int    c = 0;
254         for( int i = 0; i < ((1 <<sizelog2)+3)/4; i ++ ) {
255                  int    new_c = (dstval->words[i] + srcval->words[i]) < srcval->words[i];
256                 dstval->words[i] += srcval->words[i] + c;
257                 c = new_c;
258         }
259         _zero_upper(sizelog2, dstval);
260 }
261 static inline void _operation_sub(int sizelog2, _trans_value_t *dstval, const _trans_value_t *srcval)
262 {
263         if( sizelog2 <= UDI_PIO_4BYTE ) {
264                 // Single word doesn't need the borrow logic
265                 // - including it would cause bugs
266                 dstval->words[0] -= srcval->words[0];
267         }
268         else {
269                  int    b = 0;
270                 for( int i = ((1 <<sizelog2)+3)/4; i --; ) {
271                          int    new_b = (dstval->words[i] < srcval->words[i] + b);
272                         dstval->words[i] -= srcval->words[i] + b;
273                         b = new_b;
274                 }
275         }
276         _zero_upper(sizelog2, dstval);
277 }
278
279 #if DEBUG
280 static const char *caMEM_MODES[] = {"DIRECT","SCRATCH","BUF","MEM"};
281 #endif
282 static inline int _read_mem(udi_cb_t *gcb, udi_buf_t *buf, void *mem_ptr,
283         udi_ubit8_t op, int sizelog2,
284         const _trans_value_t *reg, _trans_value_t *val)
285 {
286         udi_ubit32_t    ofs = reg->words[0];
287         udi_size_t      size = 1 << sizelog2;
288         switch(op)
289         {
290         case UDI_PIO_DIRECT:
291                 memcpy(val, reg, size);
292                 _zero_upper(sizelog2, val);
293                 break;
294         case UDI_PIO_SCRATCH:
295                 ASSERTCR( (ofs & (size-1)), ==, 0, 1);
296                 memcpy(val, gcb->scratch + ofs, size);
297                 //LOG("scr %p+%i => %i %x,...", gcb->scratch, ofs, size, val->words[0]);
298                 break;
299         case UDI_PIO_BUF:
300                 ASSERT(buf);
301                 udi_buf_read(buf, ofs, size, val);
302                 //LOG("buf %p+%i => %i %x,...", buf, ofs, size, val->words[0]);
303                 break;
304         case UDI_PIO_MEM:
305                 ASSERTCR( (ofs & (size-1)), ==, 0, 1 );
306                 memcpy(val, mem_ptr + ofs, size);
307                 //LOG("mem %p+%i => %i %x,...", mem_ptr, ofs, size, val->words[0]);
308                 break;
309         }
310         return 0;
311 }
312
313 static inline int _write_mem(udi_cb_t *gcb, udi_buf_t *buf, void *mem_ptr,
314         udi_ubit8_t op, int sizelog2,
315         _trans_value_t *reg, const _trans_value_t *val)
316 {
317         udi_ubit32_t    ofs = reg->words[0];
318         udi_size_t      size = 1 << sizelog2;
319         switch(op)
320         {
321         case UDI_PIO_DIRECT:
322                 //LOG("reg %p = %i %x,...", reg, size, val->words[0]);
323                 memcpy(reg, val, size);
324                 _zero_upper(sizelog2, reg);
325                 break;
326         case UDI_PIO_SCRATCH:
327                 ASSERTCR( (ofs & (size-1)), ==, 0, 1);
328                 //LOG("scr %p+%i = %i %x,...", gcb->scratch, ofs, size, val->words[0]);
329                 memcpy(gcb->scratch + ofs, val, size);
330                 break;
331         case UDI_PIO_BUF:
332                 ASSERT(buf);
333                 //LOG("buf %p+%i = %i %x,...", buf, ofs, size, val->words[0]);
334                 udi_buf_write(NULL,NULL, val, size, buf, ofs, size, UDI_NULL_BUF_PATH);
335                 break;
336         case UDI_PIO_MEM:
337                 ASSERTCR( (ofs & (size-1)), ==, 0, 1);
338                 //LOG("mem %p+%i = %i %x,...", mem_ptr, ofs, size, val->words[0]);
339                 memcpy(mem_ptr + ofs, val, size);
340                 break;
341         }
342         return 0;
343 }
344
345 void udi_pio_trans(udi_pio_trans_call_t *callback, udi_cb_t *gcb,
346         udi_pio_handle_t pio_handle, udi_index_t start_label,
347         udi_buf_t *buf, void *mem_ptr)
348 {
349         LOG("pio_handle=%p,start_label=%i,buf=%p,mem_ptr=%p",
350                 pio_handle, start_label, buf, mem_ptr);
351         _trans_value_t  registers[8];
352         _trans_value_t  tmpval;
353
354         ASSERT(pio_handle);
355         
356         udi_ubit16_t    ret_status = 0;
357         
358         udi_pio_trans_t *ops = pio_handle->TransOps;
359         size_t  ip = _get_label(pio_handle, start_label);
360         
361         while( ip < pio_handle->nTransOps )
362         {
363                 udi_ubit8_t     pio_op = ops[ip].pio_op;
364                 udi_ubit8_t     tran_size = ops[ip].tran_size;
365                 udi_ubit16_t    operand = ops[ip].operand;
366                 LOG("%2i: %02x %i 0x%04x", ip, pio_op, tran_size, operand);
367                 ASSERTC(tran_size, <=, UDI_PIO_32BYTE);
368                 ip ++;
369                 if( !(pio_op & 0x80) )
370                 {
371                         // Class A
372                         _trans_value_t  *reg = &registers[pio_op&7];
373                         switch(pio_op & 0x60)
374                         {
375                         case UDI_PIO_IN:
376                                 pio_handle->IOFunc(pio_handle->ChildID, pio_handle->RegSet,
377                                         operand, tran_size, &tmpval, false);
378                                 LOG("IN %x = %i %x", operand, tran_size, tmpval.words[0]);
379                                 _write_mem(gcb, buf, mem_ptr, (pio_op&0x18), tran_size, reg, &tmpval);
380                                 break;
381                         case UDI_PIO_OUT:
382                                 _read_mem(gcb, buf, mem_ptr, (pio_op&0x18), tran_size, reg, &tmpval);
383                                 LOG("OUT %x = %i %x", operand, tran_size, tmpval.words[0]);
384                                 pio_handle->IOFunc(pio_handle->ChildID, pio_handle->RegSet,
385                                         operand, tran_size, &tmpval, true);
386                                 break;
387                         case UDI_PIO_LOAD:
388                                 _read_mem(gcb, buf, mem_ptr, (pio_op&0x18), tran_size, reg, &registers[operand]);
389                                 LOG("LOAD R%x = %i %x", operand, tran_size, registers[operand].words[0]);
390                                 _zero_upper(tran_size, &registers[operand]);
391                                 break;
392                         case UDI_PIO_STORE:
393                                 LOG("STORE R%x (%i %x)", operand, tran_size, registers[operand].words[0]);
394                                 _write_mem(gcb, buf, mem_ptr, (pio_op&0x18), tran_size, reg, &registers[operand]);
395                                 break;
396                         }
397                 }
398                 else if( pio_op < 0xF0 )
399                 {
400                          int    reg_num = pio_op & 7;
401                         _trans_value_t  *reg = &registers[reg_num];
402                         // Class B
403                         switch(pio_op & 0xF8)
404                         {
405                         case UDI_PIO_LOAD_IMM:
406                                 ASSERTC(ip + (1<<tran_size)/2-1, <=, pio_handle->nTransOps);
407                                 if( tran_size == UDI_PIO_1BYTE ) {
408                                         Log_Error("UDI", "udi_pio_trans - %p [%i] LOAD_IMM with 1 byte",
409                                                 ops, ip-1);
410                                         goto error;
411                                 }
412                                 switch(tran_size)
413                                 {
414                                 case UDI_PIO_32BYTE:
415                                         reg->words[7] = (ops[ip+14].operand << 16) | ops[ip+13].operand;
416                                         reg->words[6] = (ops[ip+12].operand << 16) | ops[ip+11].operand;
417                                         reg->words[5] = (ops[ip+10].operand << 16) | ops[ip+ 9].operand;
418                                         reg->words[4] = (ops[ip+ 8].operand << 16) | ops[ip+ 7].operand;
419                                 case UDI_PIO_16BYTE:
420                                         reg->words[3] = (ops[ip+ 6].operand << 16) | ops[ip+ 5].operand;
421                                         reg->words[2] = (ops[ip+ 4].operand << 16) | ops[ip+ 3].operand;
422                                 case UDI_PIO_8BYTE:
423                                         reg->words[1] = (ops[ip+ 2].operand << 16) | ops[ip+ 1].operand;
424                                 case UDI_PIO_4BYTE:
425                                         reg->words[0] = (ops[ip+ 0].operand << 16) | operand;
426                                 case UDI_PIO_2BYTE:
427                                 case UDI_PIO_1BYTE:
428                                         reg->words[0] = operand;
429                                         break;
430                                 }
431                                 LOG("LOAD IMM ");
432                                 _zero_upper(tran_size, reg);
433                                 ip += (1<<tran_size)/2-1;
434                                 break;
435                         case UDI_PIO_CSKIP: {
436                                 int cnd = _compare_zero(reg, tran_size);
437                                 switch(operand)
438                                 {
439                                 case UDI_PIO_NZ:
440                                         LOG("CSKIP NZ R%i (%i %x)", reg_num, tran_size, reg->words[0]);
441                                         if( !(cnd & 1) )
442                                                 ip ++;
443                                         break;
444                                 case UDI_PIO_Z:
445                                         LOG("CSKIP Z R%i (%i %x)", reg_num, tran_size, reg->words[0]);
446                                         if( cnd & 1 )
447                                                 ip ++;
448                                         break;
449                                 case UDI_PIO_NNEG:
450                                         LOG("CSKIP NNEG R%i (%i %x)", reg_num, tran_size, reg->words[0]);
451                                         if( !(cnd & 2) )
452                                                 ip ++;
453                                         break;
454                                 case UDI_PIO_NEG:
455                                         LOG("CSKIP NEG R%i (%i %x)", reg_num, tran_size, reg->words[0]);
456                                         if( cnd & 2 )
457                                                 ip ++;
458                                         break;
459                                 }
460                                 break; }
461                         case UDI_PIO_IN_IND:
462                                 LOG("IN IND");
463                                 pio_handle->IOFunc(pio_handle->ChildID, pio_handle->RegSet,
464                                         registers[operand].words[0], tran_size, reg, false);
465                                 _zero_upper(tran_size, reg);
466                                 break;
467                         case UDI_PIO_OUT_IND:
468                                 LOG("OUT IND");
469                                 pio_handle->IOFunc(pio_handle->ChildID, pio_handle->RegSet,
470                                         registers[operand].words[0], tran_size, reg, true);
471                                 break;
472                         case UDI_PIO_SHIFT_LEFT:
473                                 _operation_shift_left(tran_size, reg, operand);
474                                 break;
475                         case UDI_PIO_SHIFT_RIGHT:
476                                 _operation_shift_right(tran_size, reg, operand);
477                                 break;
478                         case UDI_PIO_AND:
479                                 _operation_and(tran_size, reg, &registers[operand]);
480                                 break;
481                         case UDI_PIO_AND_IMM:
482                                 LOG("AND_IMM R%i &= 0x%x", reg_num, operand);
483                                 tmpval.words[0] = operand;
484                                 _zero_upper(UDI_PIO_2BYTE, &tmpval);
485                                 _operation_and(tran_size, reg, &tmpval);
486                                 break;
487                         case UDI_PIO_OR:
488                                 _operation_or(tran_size, reg, &registers[operand]);
489                                 break;
490                         case UDI_PIO_OR_IMM:
491                                 LOG("OR_IMM R%i |= 0x%x", reg_num, operand);
492                                 tmpval.words[0] = operand;
493                                 _zero_upper(UDI_PIO_4BYTE, &tmpval);
494                                 _operation_or(tran_size, reg, &tmpval);
495                                 break;
496                         case UDI_PIO_XOR:
497                                 _operation_xor(tran_size, reg, &registers[operand]);
498                                 break;
499                         case UDI_PIO_ADD:
500                                 LOG("ADD R%i += R%i", reg_num, operand);
501                                 ASSERTC(operand, <, 8);
502                                 _operation_add(tran_size, reg, &registers[operand]);
503                                 break;
504                         case UDI_PIO_ADD_IMM:
505                                 tmpval.words[0] = operand;
506                                 if( operand & (1 <<16) ) {
507                                         tmpval.words[0] |= 0xFFFF0000;
508                                         memset(&tmpval.words[1], 0xFF, 4*(8-1));
509                                 }
510                                 else {
511                                         _zero_upper(UDI_PIO_4BYTE, &tmpval);
512                                 }
513                                 LOG("ADD R%i += 0x%x", reg_num, tmpval.words[0]);
514                                 _operation_add(tran_size, reg, &tmpval);
515                                 break;
516                         case UDI_PIO_SUB:
517                                 LOG("SUB R%i -= R%i", reg_num, operand);
518                                 ASSERTC(operand, <, 8);
519                                 _operation_sub(tran_size, reg, &registers[operand]);
520                                 break;
521                         default:
522                                 Log_Error("UDI", "udi_pio_trans - Class B %x unhandled!",
523                                         pio_op & 0xF8);
524                                 goto error;
525                         }
526                 }
527                 else
528                 {
529                         // Class C
530                         switch(pio_op)
531                         {
532                         case UDI_PIO_BRANCH:
533                                 LOG("BRANCH %i", operand);
534                                 ip = _get_label(pio_handle, operand);
535                                 break;
536                         case UDI_PIO_LABEL:
537                                 // nop
538                                 LOG("LABEL %i", operand);
539                                 break;
540                         case UDI_PIO_REP_IN_IND:
541                         case UDI_PIO_REP_OUT_IND: {
542                                 bool dir_is_out = (pio_op == UDI_PIO_REP_OUT_IND);
543                                 udi_ubit8_t     mode    = operand & 0x18;
544                                 udi_ubit32_t    cnt     = registers[(operand>>13) & 7].words[0];
545                                  int    pio_stride      =           (operand>>10) & 3;
546                                 udi_ubit32_t    pio_ofs = registers[(operand>>7) & 7].words[0];
547                                  int    mem_stride      =           (operand>>5) & 3;
548                                 _trans_value_t  *mem_reg=&registers[(operand>>0) & 7];
549                                 udi_ubit32_t    saved_mem_reg = mem_reg->words[0];
550
551                                 if( pio_stride > 0 )
552                                         pio_stride = 1<<(tran_size+pio_stride-1);
553                                 if( mem_stride > 0 )
554                                         mem_stride = 1<<(tran_size+mem_stride-1);
555                         
556                                 LOG("REP_%s_IND %i IO=%x+%i %s Mem=%x+%i",
557                                         (dir_is_out ? "OUT": "IN"), cnt,
558                                         pio_ofs, pio_stride,
559                                         caMEM_MODES[mode>>3], saved_mem_reg, mem_stride
560                                         );
561
562                                 while( cnt -- )
563                                 {
564                                         if( dir_is_out )
565                                                 _read_mem(gcb,buf,mem_ptr, mode, tran_size,
566                                                         mem_reg, &tmpval);
567                                         pio_handle->IOFunc(pio_handle->ChildID, pio_handle->RegSet,
568                                                 pio_ofs, tran_size, &tmpval, dir_is_out);
569                                         if( !dir_is_out )
570                                                 _write_mem(gcb,buf,mem_ptr, mode, tran_size,
571                                                         mem_reg, &tmpval);
572                                         pio_ofs += pio_stride;
573                                         if( mode != UDI_PIO_DIRECT )
574                                                 mem_reg->words[0] += mem_stride;
575                                 }
576                                 if( mode != UDI_PIO_DIRECT )
577                                         mem_reg->words[0] = saved_mem_reg;
578                                 
579                                 break; }
580                         case UDI_PIO_DELAY:
581                                 LOG("DELAY %i", operand);
582                                 Log_Notice("UDI", "udi_pio_trans - TODO: DELAY");
583                                 break;
584                         case UDI_PIO_BARRIER:
585                                 LOG("BARRIER");
586                                 Log_Notice("UDI", "udi_pio_trans - TODO: BARRIER");
587                                 break;
588                         case UDI_PIO_SYNC:
589                                 LOG("SYNC");
590                                 Log_Notice("UDI", "udi_pio_trans - TODO: SYNC");
591                                 break;
592                         case UDI_PIO_SYNC_OUT:
593                                 LOG("SYNC_OUT");
594                                 Log_Notice("UDI", "udi_pio_trans - TODO: SYNC_OUT");
595                                 break;
596                         case UDI_PIO_DEBUG:
597                                 LOG("DEBUG %x", operand);
598                                 // nop
599                                 break;
600                         case UDI_PIO_END:
601                                 ASSERTC(operand, <, 8);
602                                 ASSERTC(tran_size, <=, UDI_PIO_2BYTE);
603                                 if( tran_size == UDI_PIO_2BYTE )
604                                         ret_status = registers[operand].words[0] & 0xFFFF;
605                                 else
606                                         ret_status = registers[operand].words[0] & 0xFF;
607                                 LOG("END R%i 0x%x", operand, ret_status);
608                                 goto end;
609                         case UDI_PIO_END_IMM:
610                                 LOG("END IMM 0x%x", operand);
611                                 ASSERTC(tran_size, ==, UDI_PIO_2BYTE);
612                                 ret_status = operand;
613                                 goto end;
614                         default:
615                                 Log_Error("UDI", "udi_pio_trans - Class C %x unimplemented",
616                                         pio_op);
617                                 goto error;
618                         }
619                 }
620         }
621         
622         if( ip == pio_handle->nTransOps ) {
623                 Log_Notice("UDI", "udi_pio_trans - %p: Overran transaction list",
624                         ops);
625         }
626 end:
627         callback(gcb, buf, UDI_OK, ret_status);
628         return ;
629 error:
630         callback(gcb, buf, UDI_STAT_HW_PROBLEM, 0);
631 }
632
633 void udi_pio_probe(udi_pio_probe_call_t *callback, udi_cb_t *gcb,
634         udi_pio_handle_t pio_handle, void *mem_ptr, udi_ubit32_t pio_offset,
635         udi_ubit8_t tran_size, udi_ubit8_t direction)
636 {
637         UNIMPLEMENTED();
638 }
639

UCC git Repository :: git.ucc.asn.au