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

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