00001 /* 00002 * Copyright (c) 2011 Jan Vesely 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 00009 * - Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * - Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * - The name of the author may not be used to endorse or promote products 00015 * derived from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00018 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00019 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00020 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 */ 00034 #ifndef DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H 00035 #define DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H 00036 00037 #include <assert.h> 00038 #include <stdint.h> 00039 00040 #include <usb/host/endpoint.h> 00041 00042 #include "../utils/malloc32.h" 00043 #include "transfer_descriptor.h" 00044 00045 #include "completion_codes.h" 00046 00047 typedef struct ed { 00048 volatile uint32_t status; 00049 #define ED_STATUS_FA_MASK (0x7f) /* USB device address */ 00050 #define ED_STATUS_FA_SHIFT (0) 00051 #define ED_STATUS_EN_MASK (0xf) /* USB endpoint address */ 00052 #define ED_STATUS_EN_SHIFT (7) 00053 #define ED_STATUS_D_MASK (0x3) /* direction */ 00054 #define ED_STATUS_D_SHIFT (11) 00055 #define ED_STATUS_D_OUT (0x1) 00056 #define ED_STATUS_D_IN (0x2) 00057 #define ED_STATUS_D_TRANSFER (0x3) 00058 00059 #define ED_STATUS_S_FLAG (1 << 13) /* speed flag: 1 = low */ 00060 #define ED_STATUS_K_FLAG (1 << 14) /* skip flag (no not execute this ED) */ 00061 #define ED_STATUS_F_FLAG (1 << 15) /* format: 1 = isochronous*/ 00062 #define ED_STATUS_MPS_MASK (0x3ff) /* max_packet_size*/ 00063 #define ED_STATUS_MPS_SHIFT (16) 00064 00065 volatile uint32_t td_tail; 00066 #define ED_TDTAIL_PTR_MASK (0xfffffff0) 00067 #define ED_TDTAIL_PTR_SHIFT (0) 00068 00069 volatile uint32_t td_head; 00070 #define ED_TDHEAD_PTR_MASK (0xfffffff0) 00071 #define ED_TDHEAD_PTR_SHIFT (0) 00072 #define ED_TDHEAD_ZERO_MASK (0x3) 00073 #define ED_TDHEAD_ZERO_SHIFT (2) 00074 #define ED_TDHEAD_TOGGLE_CARRY (0x2) 00075 #define ED_TDHEAD_HALTED_FLAG (0x1) 00076 00077 volatile uint32_t next; 00078 #define ED_NEXT_PTR_MASK (0xfffffff0) 00079 #define ED_NEXT_PTR_SHIFT (0) 00080 } __attribute__((packed)) ed_t; 00081 00082 void ed_init(ed_t *instance, endpoint_t *ep); 00083 00084 static inline void ed_set_td(ed_t *instance, td_t *td) 00085 { 00086 assert(instance); 00087 uintptr_t pa = addr_to_phys(td); 00088 instance->td_head = 00089 ((pa & ED_TDHEAD_PTR_MASK) 00090 | (instance->td_head & ~ED_TDHEAD_PTR_MASK)); 00091 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 00092 } 00093 00094 static inline void ed_set_end_td(ed_t *instance, td_t *td) 00095 { 00096 assert(instance); 00097 uintptr_t pa = addr_to_phys(td); 00098 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 00099 } 00100 00101 static inline void ed_append_ed(ed_t *instance, ed_t *next) 00102 { 00103 assert(instance); 00104 assert(next); 00105 uint32_t pa = addr_to_phys(next); 00106 assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa); 00107 instance->next = pa; 00108 } 00109 00110 static inline int ed_toggle_get(ed_t *instance) 00111 { 00112 assert(instance); 00113 return (instance->td_head & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0; 00114 } 00115 00116 static inline void ed_toggle_set(ed_t *instance, int toggle) 00117 { 00118 assert(instance); 00119 assert(toggle == 0 || toggle == 1); 00120 if (toggle == 1) { 00121 instance->td_head |= ED_TDHEAD_TOGGLE_CARRY; 00122 } else { 00123 /* clear halted flag when reseting toggle */ 00124 instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY; 00125 instance->td_head &= ~ED_TDHEAD_HALTED_FLAG; 00126 } 00127 } 00128 #endif 00129