Annotation of driverkit/notes/DMADequeue, revision 1.1.1.1

1.1       root        1:                        DMA Dequeue algorithm
                      2:                        
                      3: Definitions: 
                      4: 
                      5: * a descriptor is "completed" (as far as the kernel is concerned) if at least one byte moved between the device and the descriptor. A descriptor can be "completed" even if it was aborted because of any error. A descriptor 'n' is NOT completed if a device-level error occurred while processing data from descriptor 'n-1', even of the TE fetched one or two buffers worth of data from descriptor 'n'.
                      6: 
                      7: * DMA read: transfer from device to memory
                      8: 
                      9: * DMA write: transfer from memory to device
                     10: 
                     11: Notes:
                     12: 
                     13: * We write -1 to a descriptor's rem_byte_count field when it is enqueued.
                     14: * We write -1000 (or some magic number less than -(max buffer size)) to the
                     15:   hw_count register every time we write the hw_curr_desc register.
                     16: * Once chan_dma_dequeue() is called with DEQUEUE_ALL, further calls specifying
                     17:   only DEQUEUE_COMPLETED are not guaranteed to return only completed frames.
                     18:   
                     19:   
                     20: chan_dma_dequeue(dequeue_spec_t dequeue_spec) {
                     21: 
                     22:        desc = head of software's descriptor chain;
                     23:        if(direction == DMA_READ) {
                     24:                if(desc->rem_byte_count != -1) {
                     25:                        /*
                     26:                         * Easy case; TE has written the rem_byte_count field, 
                     27:                         * indicating completion. 
                     28:                         */
                     29:                        dequeue_ok = TRUE;
                     30:                        goto got_one;
                     31:                }
                     32:                
                     33:                /*
                     34:                 * Continue - this descriptor could still be complete
                     35:                 * if EOR was not here.
                     36:                 */
                     37:        }
                     38:        if(desc_list_not_empty) {
                     39:                /*
                     40:                 * Channel running; another easy case. This descriptor is
                     41:                 * complete as long as it's not the current descriptor.
                     42:                 */
                     43:                if(desc != hw_curr_desc)
                     44:                        dequeue_ok = TRUE;
                     45:                else
                     46:                        dequeue_ok = FALSE;                     
                     47:        }
                     48:        else {
                     49:                /*
                     50:                 * Channel idle.
                     51:                 */
                     52:                if(desc != hw_curr_desc) {
                     53:                        /*
                     54:                         * Not current, must be completed.
                     55:                         */
                     56:                        dequeue_ok = TRUE;
                     57:                }
                     58:                else {  
                     59:                        /*
                     60:                         * This descriptor was either the last descriptor
                     61:                         * serviced by the TE or the next one to be serviced.
                     62:                         *
                     63:                         * We write -1000 to hw_count every time we write
                     64:                         * hw_curr_desc, so if it's still -1000, we know
                     65:                         * the TE hasn't gotten to this one yet.
                     66:                         */
                     67:                        if(hw_count == -1000) {
                     68:                                dequeue_ok = FALSE;
                     69:                        }
                     70:                        else {
                     71:                                /*
                     72:                                 * Tricky case. The TE at least started to work
                     73:                                 * on this descriptor, but we don't know if
                     74:                                 * any data from this descriptor moved to/from
                     75:                                 * the device. We have to examine the amount
                     76:                                 * of data moved from memory and the state of
                     77:                                 * the TE buffers...
                     78:                                 */
                     79:                                if(hw_count between 0 and -(max buffer size)) {
                     80:                                        /*
                     81:                                         * This implies completion by the TE.
                     82:                                         */
                     83:                                        dequeue_ok = TRUE;
                     84:                                } 
                     85:                                else {
                     86:                                        bytes_moved = desc->count - hw_count;
                     87:                                                                                                
                     88:                                        if(direction == DMA_READ) {
                     89:                                            /*
                     90:                                             * For data in, any bytes 
                     91:                                             * transferred
                     92:                                             * means that the descriptor is
                     93:                                             * complete.
                     94:                                             */
                     95:                                            if(bytes_moved == 0) {
                     96:                                                got_a_desc = FALSE;
                     97:                                            }
                     98:                                            else {
                     99:                                                got_a_desc = TRUE;
                    100:                                            }
                    101:                                            goto got_one;
                    102:                                        }
                    103: 
                    104:                                        if(bytes_moved > (2 * buffer size)) {
                    105:                                                /*
                    106:                                                 * some had to move to the
                    107:                                                 * device.
                    108:                                                 */
                    109:                                                dequeue_ok = TRUE;
                    110:                                        }
                    111:                                        else if(bytes_moved == 0) {
                    112:                                                /*
                    113:                                                 * We haven't touched this 
                    114:                                                 * descriptor's data.
                    115:                                                 */
                    116:                                                dequeue_ok = FALSE;
                    117:                                        }
                    118:                                        else if(bytes_moved == 1 buffer) {
                    119:                                            if(either "buffer full" flag set) {
                    120:                                                /*
                    121:                                                 * We couldn't have moved data
                    122:                                                 * to or from the device.
                    123:                                                 */
                    124:                                                dequeue_ok = FALSE;
                    125:                                            }
                    126:                                            else {
                    127:                                                dequeue_ok = TRUE;
                    128:                                            }
                    129:                                        }
                    130:                                        else  {
                    131:                                            /*
                    132:                                             * bytes_moved == 2 buffers.
                    133:                                             */
                    134:                                            if(BOTH "buffer full" flags set) {
                    135:                                                dequeue_ok = FALSE;
                    136:                                            }
                    137:                                            else {
                    138:                                                /*
                    139:                                                 * We moved 2 buffers from 
                    140:                                                 * memory but at least one
                    141:                                                 * of the buffers is not full, 
                    142:                                                 * so some data must have 
                    143:                                                 * moved to the device.
                    144:                                                 */
                    145:                                                dequeue_ok = TRUE;
                    146:                                            }
                    147:                                        }
                    148:                                }
                    149:                        }
                    150:                } /* desc == hw_curr */
                    151:        }         /* channel idle */
                    152:        
                    153: got_one:
                    154: 
                    155:        /*
                    156:         * Even if dequeue_ok is FALSE, we can still dequeue if the channel
                    157:         * isn't running and the caller said they wanted all descriptors.
                    158:         */
                    159:        if(!dequeue_ok && 
                    160:           (channel not running) && 
                    161:           (dequeue_spec == DEQUEUE_ALL)) {
                    162:                dequeue_ok = TRUE;
                    163:        }
                    164:        if(dequeue_ok) {
                    165:                grab this desc from s/w chain; 
                    166:                if this is the last descriptor of a frame {
                    167:                        dequeue the frame;
                    168:                        get return parameters from last descriptor;
                    169:                        unlock the VM associated with this frame;
                    170:                        free all descriptors and the frame;
                    171:                }
                    172:        }
                    173: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.