| 1 | /***************************************************************************** |
| 2 | ** FILE NAME : ifxhcd.h |
| 3 | ** PROJECT : IFX USB sub-system V3 |
| 4 | ** MODULES : IFX USB sub-system Host and Device driver |
| 5 | ** SRC VERSION : 1.0 |
| 6 | ** DATE : 1/Jan/2009 |
| 7 | ** AUTHOR : Chen, Howard |
| 8 | ** DESCRIPTION : This file contains the structures, constants, and interfaces for |
| 9 | ** the Host Contoller Driver (HCD). |
| 10 | ** |
| 11 | ** The Host Controller Driver (HCD) is responsible for translating requests |
| 12 | ** from the USB Driver into the appropriate actions on the IFXUSB controller. |
| 13 | ** It isolates the USBD from the specifics of the controller by providing an |
| 14 | ** API to the USBD. |
| 15 | ** FUNCTIONS : |
| 16 | ** COMPILER : gcc |
| 17 | ** REFERENCE : Synopsys DWC-OTG Driver 2.7 |
| 18 | ** COPYRIGHT : |
| 19 | ** Version Control Section ** |
| 20 | ** $Author$ |
| 21 | ** $Date$ |
| 22 | ** $Revisions$ |
| 23 | ** $Log$ Revision history |
| 24 | *****************************************************************************/ |
| 25 | |
| 26 | /*! |
| 27 | \defgroup IFXUSB_HCD HCD Interface |
| 28 | \ingroup IFXUSB_DRIVER_V3 |
| 29 | \brief The Host Controller Driver (HCD) is responsible for translating requests |
| 30 | from the USB Driver into the appropriate actions on the IFXUSB controller. |
| 31 | It isolates the USBD from the specifics of the controller by providing an |
| 32 | API to the USBD. |
| 33 | */ |
| 34 | |
| 35 | |
| 36 | /*! |
| 37 | \file ifxhcd.h |
| 38 | \ingroup IFXUSB_DRIVER_V3 |
| 39 | \brief This file contains the structures, constants, and interfaces for |
| 40 | the Host Contoller Driver (HCD). |
| 41 | */ |
| 42 | |
| 43 | #if !defined(__IFXHCD_H__) |
| 44 | #define __IFXHCD_H__ |
| 45 | |
| 46 | #include <linux/list.h> |
| 47 | #include <linux/usb.h> |
| 48 | |
| 49 | #ifdef __USE_TIMER_4_SOF__ |
| 50 | #include <linux/hrtimer.h> |
| 51 | #endif |
| 52 | #include <linux/usb/hcd.h> |
| 53 | |
| 54 | #include "ifxusb_cif.h" |
| 55 | #include "ifxusb_plat.h" |
| 56 | |
| 57 | |
| 58 | |
| 59 | /*! |
| 60 | \addtogroup IFXUSB_HCD |
| 61 | */ |
| 62 | /*@{*/ |
| 63 | |
| 64 | /* Phases for control transfers.*/ |
| 65 | typedef enum ifxhcd_control_phase { |
| 66 | IFXHCD_CONTROL_SETUP, |
| 67 | IFXHCD_CONTROL_DATA, |
| 68 | IFXHCD_CONTROL_STATUS |
| 69 | } ifxhcd_control_phase_e; |
| 70 | |
| 71 | /* Reasons for halting a host channel. */ |
| 72 | typedef enum ifxhcd_halt_status |
| 73 | { |
| 74 | HC_XFER_NO_HALT_STATUS, // Initial |
| 75 | HC_XFER_COMPLETE, // Xact complete without error, upward |
| 76 | HC_XFER_URB_COMPLETE, // Xfer complete without error, short upward |
| 77 | HC_XFER_STALL, // HC stopped abnormally, upward/downward |
| 78 | HC_XFER_XACT_ERR, // HC stopped abnormally, upward |
| 79 | HC_XFER_FRAME_OVERRUN, // HC stopped abnormally, upward |
| 80 | HC_XFER_BABBLE_ERR, // HC stopped abnormally, upward |
| 81 | HC_XFER_AHB_ERR, // HC stopped abnormally, upward |
| 82 | HC_XFER_DATA_TOGGLE_ERR, |
| 83 | HC_XFER_URB_DEQUEUE, // HC stopper manually, downward |
| 84 | HC_XFER_NAK // HC stopped by nak monitor, downward |
| 85 | } ifxhcd_halt_status_e; |
| 86 | |
| 87 | struct ifxhcd_urbd; |
| 88 | struct ifxhcd_hc ; |
| 89 | struct ifxhcd_epqh ; |
| 90 | struct ifxhcd_hcd; |
| 91 | |
| 92 | /*! |
| 93 | \brief A URB Descriptor (URBD) holds the state of a bulk, control, |
| 94 | interrupt, or isochronous transfer. A single URBD is created for each URB |
| 95 | (of one of these types) submitted to the HCD. The transfer associated with |
| 96 | a URBD may require one or multiple transactions. |
| 97 | |
| 98 | A URBD is linked to a EP Queue Head, which is entered in either the |
| 99 | isoc, intr or non-periodic schedule for execution. When a URBD is chosen for |
| 100 | execution, some or all of its transactions may be executed. After |
| 101 | execution, the state of the URBD is updated. The URBD may be retired if all |
| 102 | its transactions are complete or if an error occurred. Otherwise, it |
| 103 | remains in the schedule so more transactions can be executed later. |
| 104 | */ |
| 105 | typedef struct ifxhcd_urbd { |
| 106 | struct list_head urbd_list_entry; // Hook for EPQH->urbd_list and ifxhcd->urbd_complete_list |
| 107 | struct urb *urb; /*!< URB for this transfer */ |
| 108 | //struct urb { |
| 109 | // struct list_head urb_list; |
| 110 | // struct list_head anchor_list; |
| 111 | // struct usb_anchor * anchor; |
| 112 | // struct usb_device * dev; |
| 113 | // struct usb_host_endpoint * ep; |
| 114 | // unsigned int pipe; |
| 115 | // int status; |
| 116 | // unsigned int transfer_flags; |
| 117 | // void * transfer_buffer; |
| 118 | // dma_addr_t transfer_dma; |
| 119 | // u32 transfer_buffer_length; |
| 120 | // u32 actual_length; |
| 121 | // unsigned char * setup_packet; |
| 122 | // dma_addr_t setup_dma; |
| 123 | // int start_frame; |
| 124 | // int number_of_packets; |
| 125 | // int interval; |
| 126 | // int error_count; |
| 127 | // void * context; |
| 128 | // usb_complete_t complete; |
| 129 | // struct usb_iso_packet_descriptor iso_frame_desc[0]; |
| 130 | //}; |
| 131 | //urb_list For use by current owner of the URB. |
| 132 | //anchor_list membership in the list of an anchor |
| 133 | //anchor to anchor URBs to a common mooring |
| 134 | //dev Identifies the USB device to perform the request. |
| 135 | //ep Points to the endpoint's data structure. Will |
| 136 | // eventually replace pipe. |
| 137 | //pipe Holds endpoint number, direction, type, and more. |
| 138 | // Create these values with the eight macros available; u |
| 139 | // sb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is |
| 140 | // "ctrl", "bulk", "int" or "iso". For example |
| 141 | // usb_sndbulkpipe or usb_rcvintpipe. Endpoint numbers |
| 142 | // range from zero to fifteen. Note that "in" endpoint two |
| 143 | // is a different endpoint (and pipe) from "out" endpoint |
| 144 | // two. The current configuration controls the existence, |
| 145 | // type, and maximum packet size of any given endpoint. |
| 146 | //status This is read in non-iso completion functions to get |
| 147 | // the status of the particular request. ISO requests |
| 148 | // only use it to tell whether the URB was unlinked; |
| 149 | // detailed status for each frame is in the fields of |
| 150 | // the iso_frame-desc. |
| 151 | //transfer_flags A variety of flags may be used to affect how URB |
| 152 | // submission, unlinking, or operation are handled. |
| 153 | // Different kinds of URB can use different flags. |
| 154 | // URB_SHORT_NOT_OK |
| 155 | // URB_ISO_ASAP |
| 156 | // URB_NO_TRANSFER_DMA_MAP |
| 157 | // URB_NO_SETUP_DMA_MAP |
| 158 | // URB_NO_FSBR |
| 159 | // URB_ZERO_PACKET |
| 160 | // URB_NO_INTERRUPT |
| 161 | //transfer_buffer This identifies the buffer to (or from) which the I/O |
| 162 | // request will be performed (unless URB_NO_TRANSFER_DMA_MAP |
| 163 | // is set). This buffer must be suitable for DMA; allocate it |
| 164 | // with kmalloc or equivalent. For transfers to "in" |
| 165 | // endpoints, contents of this buffer will be modified. This |
| 166 | // buffer is used for the data stage of control transfers. |
| 167 | //transfer_dma When transfer_flags includes URB_NO_TRANSFER_DMA_MAP, the |
| 168 | // device driver is saying that it provided this DMA address, |
| 169 | // which the host controller driver should use in preference |
| 170 | // to the transfer_buffer. |
| 171 | //transfer_buffer_length How big is transfer_buffer. The transfer may be broken |
| 172 | // up into chunks according to the current maximum packet size |
| 173 | // for the endpoint, which is a function of the configuration |
| 174 | // and is encoded in the pipe. When the length is zero, neither |
| 175 | // transfer_buffer nor transfer_dma is used. |
| 176 | //actual_length This is read in non-iso completion functions, and it tells |
| 177 | // how many bytes (out of transfer_buffer_length) were transferred. |
| 178 | // It will normally be the same as requested, unless either an error |
| 179 | // was reported or a short read was performed. The URB_SHORT_NOT_OK |
| 180 | // transfer flag may be used to make such short reads be reported |
| 181 | // as errors. |
| 182 | //setup_packet Only used for control transfers, this points to eight bytes of |
| 183 | // setup data. Control transfers always start by sending this data |
| 184 | // to the device. Then transfer_buffer is read or written, if needed. |
| 185 | //setup_dma For control transfers with URB_NO_SETUP_DMA_MAP set, the device |
| 186 | // driver has provided this DMA address for the setup packet. The |
| 187 | // host controller driver should use this in preference to setup_packet. |
| 188 | //start_frame Returns the initial frame for isochronous transfers. |
| 189 | //number_of_packets Lists the number of ISO transfer buffers. |
| 190 | //interval Specifies the polling interval for interrupt or isochronous transfers. |
| 191 | // The units are frames (milliseconds) for for full and low speed devices, |
| 192 | // and microframes (1/8 millisecond) for highspeed ones. |
| 193 | //error_count Returns the number of ISO transfers that reported errors. |
| 194 | //context For use in completion functions. This normally points to request-specific |
| 195 | // driver context. |
| 196 | //complete Completion handler. This URB is passed as the parameter to the completion |
| 197 | // function. The completion function may then do what it likes with the URB, |
| 198 | // including resubmitting or freeing it. |
| 199 | //iso_frame_desc[0] Used to provide arrays of ISO transfer buffers and to collect the transfer |
| 200 | // status for each buffer. |
| 201 | |
| 202 | struct ifxhcd_epqh *epqh; |
| 203 | // Actual data portion, not SETUP or STATUS in case of CTRL XFER |
| 204 | // DMA adjusted |
| 205 | uint8_t *setup_buff; /*!< Pointer to the entire transfer buffer. (CPU accessable)*/ |
| 206 | uint8_t *xfer_buff; /*!< Pointer to the entire transfer buffer. (CPU accessable)*/ |
| 207 | uint32_t xfer_len; /*!< Total number of bytes to transfer in this xfer. */ |
| 208 | unsigned is_in :1; |
| 209 | unsigned is_active:1; |
| 210 | |
| 211 | // For ALL XFER |
| 212 | uint8_t error_count; /*!< Holds the number of bus errors that have occurred for a transaction |
| 213 | within this transfer. |
| 214 | */ |
| 215 | /*== AVM/BC 20101111 Needed for URB Complete List ==*/ |
| 216 | int status; |
| 217 | // For ISOC XFER only |
| 218 | #ifdef __EN_ISOC__ |
| 219 | int isoc_frame_index; /*!< Index of the next frame descriptor for an isochronous transfer. A |
| 220 | frame descriptor describes the buffer position and length of the |
| 221 | data to be transferred in the next scheduled (micro)frame of an |
| 222 | isochronous transfer. It also holds status for that transaction. |
| 223 | The frame index starts at 0. |
| 224 | */ |
| 225 | // For SPLITed ISOC XFER only |
| 226 | uint8_t isoc_split_pos; /*!< Position of the ISOC split on full/low speed */ |
| 227 | uint16_t isoc_split_offset;/*!< Position of the ISOC split in the buffer for the current frame */ |
| 228 | #endif |
| 229 | } ifxhcd_urbd_t; |
| 230 | |
| 231 | /*! |
| 232 | \brief A EP Queue Head (EPQH) holds the static characteristics of an endpoint and |
| 233 | maintains a list of transfers (URBDs) for that endpoint. A EPQH structure may |
| 234 | be entered in either the isoc, intr or non-periodic schedule. |
| 235 | */ |
| 236 | |
| 237 | typedef struct ifxhcd_epqh { |
| 238 | struct list_head epqh_list_entry; // Hook for EP Queues |
| 239 | struct list_head urbd_list; /*!< List of URBDs for this EPQH. */ |
| 240 | struct ifxhcd_hc *hc; /*!< Host channel currently processing transfers for this EPQH. */ |
| 241 | struct ifxhcd_urbd *urbd; /*!< URBD currently assigned to a host channel for this EPQH. */ |
| 242 | struct usb_host_endpoint *sysep; |
| 243 | uint8_t ep_type; /*!< Endpoint type. One of the following values: |
| 244 | - IFXUSB_EP_TYPE_CTRL |
| 245 | - IFXUSB_EP_TYPE_ISOC |
| 246 | - IFXUSB_EP_TYPE_BULK |
| 247 | - IFXUSB_EP_TYPE_INTR |
| 248 | */ |
| 249 | uint16_t mps; /*!< wMaxPacketSize Field of Endpoint Descriptor. */ |
| 250 | |
| 251 | /* == AVM/WK 20100710 Fix - Use toggle of usbcore ==*/ |
| 252 | /*uint8_t data_toggle;*/ /*!< Determines the PID of the next data packet |
| 253 | One of the following values: |
| 254 | - IFXHCD_HC_PID_DATA0 |
| 255 | - IFXHCD_HC_PID_DATA1 |
| 256 | */ |
| 257 | uint8_t is_active; |
| 258 | |
| 259 | uint8_t pkt_count_limit; |
| 260 | #ifdef __EPQD_DESTROY_TIMEOUT__ |
| 261 | struct timer_list destroy_timer; |
| 262 | #endif |
| 263 | |
| 264 | uint16_t wait_for_sof; |
| 265 | uint8_t need_split; /*!< Full/low speed endpoint on high-speed hub requires split. */ |
| 266 | uint16_t interval; /*!< Interval between transfers in (micro)frames. (for INTR)*/ |
| 267 | |
| 268 | uint16_t period_counter; /*!< Interval between transfers in (micro)frames. */ |
| 269 | uint8_t period_do; |
| 270 | |
| 271 | uint8_t aligned_checked; |
| 272 | |
| 273 | #if defined(__UNALIGNED_BUFFER_ADJ__) |
| 274 | uint8_t using_aligned_setup; |
| 275 | uint8_t *aligned_setup; |
| 276 | uint8_t using_aligned_buf; |
| 277 | uint8_t *aligned_buf; |
| 278 | unsigned aligned_buf_len : 19; |
| 279 | #endif |
| 280 | |
| 281 | uint8_t *dump_buf; |
| 282 | } ifxhcd_epqh_t; |
| 283 | |
| 284 | |
| 285 | #if defined(__HC_XFER_TIMEOUT__) |
| 286 | struct ifxusb_core_if; |
| 287 | struct ifxhcd_hc; |
| 288 | typedef struct hc_xfer_info |
| 289 | { |
| 290 | struct ifxusb_core_if *core_if; |
| 291 | struct ifxhcd_hc *hc; |
| 292 | } hc_xfer_info_t; |
| 293 | #endif //defined(__HC_XFER_TIMEOUT__) |
| 294 | |
| 295 | |
| 296 | /*! |
| 297 | \brief Host channel descriptor. This structure represents the state of a single |
| 298 | host channel when acting in host mode. It contains the data items needed to |
| 299 | transfer packets to an endpoint via a host channel. |
| 300 | */ |
| 301 | typedef struct ifxhcd_hc |
| 302 | { |
| 303 | struct list_head hc_list_entry ; // Hook to free hc |
| 304 | struct ifxhcd_epqh *epqh ; /*!< EP Queue Head for the transfer being processed by this channel. */ |
| 305 | |
| 306 | uint8_t hc_num ; /*!< Host channel number used for register address lookup */ |
| 307 | uint8_t *xfer_buff ; /*!< Pointer to the entire transfer buffer. */ |
| 308 | uint32_t xfer_count ; /*!< Number of bytes transferred so far. The offset of the begin of the buf */ |
| 309 | uint32_t xfer_len ; /*!< Total number of bytes to transfer in this xfer. */ |
| 310 | uint16_t start_pkt_count ; /*!< Packet count at start of transfer. Used to calculate the actual xfer size*/ |
| 311 | ifxhcd_halt_status_e halt_status; /*!< Reason for halting the host channel. */ |
| 312 | |
| 313 | unsigned dev_addr : 7; /*!< Device to access */ |
| 314 | unsigned ep_num : 4; /*!< EP to access */ |
| 315 | unsigned is_in : 1; /*!< EP direction. 0: OUT, 1: IN */ |
| 316 | unsigned speed : 2; /*!< EP speed. */ |
| 317 | unsigned ep_type : 2; /*!< Endpoint type. */ |
| 318 | unsigned mps :11; /*!< Max packet size in bytes */ |
| 319 | unsigned data_pid_start : 2; /*!< PID for initial transaction. */ |
| 320 | unsigned do_ping : 1; /*!< Set to 1 to indicate that a PING request should be issued on this |
| 321 | channel. If 0, process normally. |
| 322 | */ |
| 323 | |
| 324 | unsigned xfer_started : 1; /*!< Flag to indicate whether the transfer has been started. Set to 1 if |
| 325 | it has been started, 0 otherwise. |
| 326 | */ |
| 327 | unsigned halting : 1; /*!< Set to 1 if the host channel has been halted, but the core is not |
| 328 | finished flushing queued requests. Otherwise 0. |
| 329 | */ |
| 330 | unsigned short_rw : 1; /*!< When Tx, means termination needed. |
| 331 | When Rx, indicate Short Read */ |
| 332 | /* Split settings for the host channel */ |
| 333 | unsigned split : 2; /*!< Split: 0-Non Split, 1-SSPLIT, 2&3 CSPLIT */ |
| 334 | |
| 335 | /*== AVM/BC 20100701 - Workaround FullSpeed Interrupts with HiSpeed Hub ==*/ |
| 336 | unsigned nyet_count; |
| 337 | |
| 338 | /* nak monitor */ |
| 339 | unsigned nak_retry_r : 16; |
| 340 | unsigned nak_retry : 16; |
| 341 | #define nak_retry_max 40000 |
| 342 | unsigned nak_countdown : 8; |
| 343 | unsigned nak_countdown_r: 8; |
| 344 | #define nak_countdown_max 1 |
| 345 | |
| 346 | uint16_t wait_for_sof; |
| 347 | ifxhcd_control_phase_e control_phase; /*!< Current phase for control transfers (Setup, Data, or Status). */ |
| 348 | uint32_t ssplit_out_xfer_count; /*!< How many bytes transferred during SSPLIT OUT */ |
| 349 | #ifdef __DEBUG__ |
| 350 | uint32_t start_hcchar_val; |
| 351 | #endif |
| 352 | #ifdef __HC_XFER_TIMEOUT__ |
| 353 | hc_xfer_info_t hc_xfer_info; |
| 354 | struct timer_list hc_xfer_timer; |
| 355 | #endif |
| 356 | uint32_t hcchar; |
| 357 | |
| 358 | /* Split settings for the host channel */ |
| 359 | uint8_t hub_addr; /*!< Address of high speed hub */ |
| 360 | uint8_t port_addr; /*!< Port of the low/full speed device */ |
| 361 | #ifdef __EN_ISOC__ |
| 362 | uint8_t isoc_xact_pos; /*!< Split transaction position */ |
| 363 | #endif |
| 364 | } ifxhcd_hc_t; |
| 365 | |
| 366 | |
| 367 | /*! |
| 368 | \brief This structure holds the state of the HCD, including the non-periodic and |
| 369 | periodic schedules. |
| 370 | */ |
| 371 | typedef struct ifxhcd_hcd |
| 372 | { |
| 373 | struct device *dev; |
| 374 | struct hc_driver hc_driver; |
| 375 | ifxusb_core_if_t core_if; /*!< Pointer to the core interface structure. */ |
| 376 | struct usb_hcd *syshcd; |
| 377 | |
| 378 | volatile union ifxhcd_internal_flags |
| 379 | { |
| 380 | uint32_t d32; |
| 381 | struct |
| 382 | { |
| 383 | unsigned port_connect_status_change : 1; |
| 384 | unsigned port_connect_status : 1; |
| 385 | unsigned port_reset_change : 1; |
| 386 | unsigned port_enable_change : 1; |
| 387 | unsigned port_suspend_change : 1; |
| 388 | unsigned port_over_current_change : 1; |
| 389 | unsigned reserved : 27; |
| 390 | } b; |
| 391 | } flags; /*!< Internal HCD Flags */ |
| 392 | |
| 393 | struct ifxhcd_hc ifxhc[MAX_EPS_CHANNELS]; /*!< Array of pointers to the host channel descriptors. Allows accessing |
| 394 | a host channel descriptor given the host channel number. This is |
| 395 | useful in interrupt handlers. |
| 396 | */ |
| 397 | struct list_head free_hc_list; /*!< Free host channels in the controller. This is a list of ifxhcd_hc_t items. */ |
| 398 | uint8_t *status_buf; /*!< Buffer to use for any data received during the status phase of a |
| 399 | control transfer. Normally no data is transferred during the status |
| 400 | phase. This buffer is used as a bit bucket. |
| 401 | */ |
| 402 | #define IFXHCD_STATUS_BUF_SIZE 64 |
| 403 | |
| 404 | struct list_head epqh_np_active; // with URBD, with HC |
| 405 | struct list_head epqh_np_ready; // with URBD, No HC |
| 406 | |
| 407 | struct list_head epqh_intr_active; // with URBD, with HC |
| 408 | struct list_head epqh_intr_ready; // with URBD, no pass, No HC |
| 409 | |
| 410 | #ifdef __EN_ISOC__ |
| 411 | struct list_head epqh_isoc_active; // with URBD, with HC |
| 412 | struct list_head epqh_isoc_ready; // with URBD, no pass, No HC |
| 413 | #endif |
| 414 | |
| 415 | /*== AVM/BC 20101111 URB Complete List ==*/ |
| 416 | struct list_head urbd_complete_list; |
| 417 | |
| 418 | struct list_head epqh_stdby; |
| 419 | |
| 420 | /* AVM/BC 20101111 flags removed */ |
| 421 | //unsigned process_channels_in_use : 1; |
| 422 | //unsigned select_eps_in_use : 1; |
| 423 | |
| 424 | struct tasklet_struct select_eps; /*!< Tasket to do a reset */ |
| 425 | uint32_t lastframe; |
| 426 | spinlock_t lock; |
| 427 | #ifdef __USE_TIMER_4_SOF__ |
| 428 | struct hrtimer hr_timer; |
| 429 | #endif |
| 430 | } ifxhcd_hcd_t; |
| 431 | |
| 432 | /* Gets the ifxhcd_hcd from a struct usb_hcd */ |
| 433 | static inline ifxhcd_hcd_t *syshcd_to_ifxhcd(struct usb_hcd *syshcd) |
| 434 | { |
| 435 | return (ifxhcd_hcd_t *)(syshcd->hcd_priv[0]); |
| 436 | } |
| 437 | |
| 438 | /* Gets the struct usb_hcd that contains a ifxhcd_hcd_t. */ |
| 439 | static inline struct usb_hcd *ifxhcd_to_syshcd(ifxhcd_hcd_t *ifxhcd) |
| 440 | { |
| 441 | return (struct usb_hcd *)(ifxhcd->syshcd); |
| 442 | } |
| 443 | |
| 444 | /*! \brief HCD Create/Destroy Functions */ |
| 445 | /*@{*/ |
| 446 | extern int ifxhcd_init (ifxhcd_hcd_t *_ifxhcd); |
| 447 | extern void ifxhcd_remove(ifxhcd_hcd_t *_ifxhcd); |
| 448 | /*@}*/ |
| 449 | |
| 450 | /*! \brief Linux HC Driver API Functions */ |
| 451 | /*@{*/ |
| 452 | extern int ifxhcd_start(struct usb_hcd *hcd); |
| 453 | extern void ifxhcd_stop (struct usb_hcd *hcd); |
| 454 | extern int ifxhcd_get_frame_number(struct usb_hcd *hcd); |
| 455 | |
| 456 | |
| 457 | /*! |
| 458 | \brief This function does the setup for a data transfer for a host channel and |
| 459 | starts the transfer. May be called in either Slave mode or DMA mode. In |
| 460 | Slave mode, the caller must ensure that there is sufficient space in the |
| 461 | request queue and Tx Data FIFO. |
| 462 | |
| 463 | For an OUT transfer in Slave mode, it loads a data packet into the |
| 464 | appropriate FIFO. If necessary, additional data packets will be loaded in |
| 465 | the Host ISR. |
| 466 | |
| 467 | For an IN transfer in Slave mode, a data packet is requested. The data |
| 468 | packets are unloaded from the Rx FIFO in the Host ISR. If necessary, |
| 469 | additional data packets are requested in the Host ISR. |
| 470 | |
| 471 | For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ |
| 472 | register along with a packet count of 1 and the channel is enabled. This |
| 473 | causes a single PING transaction to occur. Other fields in HCTSIZ are |
| 474 | simply set to 0 since no data transfer occurs in this case. |
| 475 | |
| 476 | For a PING transfer in DMA mode, the HCTSIZ register is initialized with |
| 477 | all the information required to perform the subsequent data transfer. In |
| 478 | addition, the Do Ping bit is set in the HCTSIZ register. In this case, the |
| 479 | controller performs the entire PING protocol, then starts the data |
| 480 | transfer. |
| 481 | |
| 482 | @param _ifxhc Information needed to initialize the host channel. The xfer_len |
| 483 | value may be reduced to accommodate the max widths of the XferSize and |
| 484 | PktCnt fields in the HCTSIZn register. The multi_count value may be changed |
| 485 | to reflect the final xfer_len value. |
| 486 | */ |
| 487 | extern void ifxhcd_hc_start(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc); |
| 488 | |
| 489 | //extern int ifxhcd_urb_enqueue(struct usb_hcd *_syshcd, struct usb_host_endpoint *_sysep, struct urb *_urb, gfp_t mem_flags); |
| 490 | //extern int ifxhcd_urb_dequeue(struct usb_hcd *_syshcd, struct urb *_urb); |
| 491 | extern irqreturn_t ifxhcd_irq(struct usb_hcd *_syshcd); |
| 492 | int ifxhcd_urb_enqueue( struct usb_hcd *_syshcd, |
| 493 | /*--- struct usb_host_endpoint *_sysep, Parameter im 2.6.28 entfallen ---*/ |
| 494 | struct urb *_urb, |
| 495 | gfp_t _mem_flags); |
| 496 | int ifxhcd_urb_dequeue( struct usb_hcd *_syshcd, |
| 497 | struct urb *_urb, int status /* Parameter neu in 2.6.28 */); |
| 498 | |
| 499 | extern void ifxhcd_endpoint_disable(struct usb_hcd *_syshcd, struct usb_host_endpoint *_sysep); |
| 500 | |
| 501 | extern int ifxhcd_hub_status_data(struct usb_hcd *_syshcd, char *_buf); |
| 502 | extern int ifxhcd_hub_control( struct usb_hcd *_syshcd, |
| 503 | u16 _typeReq, |
| 504 | u16 _wValue, |
| 505 | u16 _wIndex, |
| 506 | char *_buf, |
| 507 | u16 _wLength); |
| 508 | |
| 509 | /*@}*/ |
| 510 | |
| 511 | /*! \brief Transaction Execution Functions */ |
| 512 | /*@{*/ |
| 513 | extern void ifxhcd_complete_urb (ifxhcd_hcd_t *_ifxhcd, ifxhcd_urbd_t *_urbd, int _status); |
| 514 | |
| 515 | /*@}*/ |
| 516 | |
| 517 | /*! \brief Deferred Transaction Execution Functions */ |
| 518 | /*@{*/ |
| 519 | |
| 520 | /*== AVM/BC 20101111 URB Complete List ==*/ |
| 521 | extern void defer_ifxhcd_complete_urb (ifxhcd_hcd_t *_ifxhcd, ifxhcd_urbd_t *_urbd, int _status); |
| 522 | |
| 523 | /*! |
| 524 | \brief Clears the transfer state for a host channel. This function is normally |
| 525 | called after a transfer is done and the host channel is being released. |
| 526 | */ |
| 527 | extern void ifxhcd_hc_cleanup(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc); |
| 528 | |
| 529 | /*! |
| 530 | \brief Attempts to halt a host channel. This function should only be called in |
| 531 | Slave mode or to abort a transfer in either Slave mode or DMA mode. Under |
| 532 | normal circumstances in DMA mode, the controller halts the channel when the |
| 533 | transfer is complete or a condition occurs that requires application |
| 534 | intervention. |
| 535 | |
| 536 | In slave mode, checks for a free request queue entry, then sets the Channel |
| 537 | Enable and Channel Disable bits of the Host Channel Characteristics |
| 538 | register of the specified channel to intiate the halt. If there is no free |
| 539 | request queue entry, sets only the Channel Disable bit of the HCCHARn |
| 540 | register to flush requests for this channel. In the latter case, sets a |
| 541 | flag to indicate that the host channel needs to be halted when a request |
| 542 | queue slot is open. |
| 543 | |
| 544 | In DMA mode, always sets the Channel Enable and Channel Disable bits of the |
| 545 | HCCHARn register. The controller ensures there is space in the request |
| 546 | queue before submitting the halt request. |
| 547 | |
| 548 | Some time may elapse before the core flushes any posted requests for this |
| 549 | host channel and halts. The Channel Halted interrupt handler completes the |
| 550 | deactivation of the host channel. |
| 551 | */ |
| 552 | extern void ifxhcd_hc_halt(ifxusb_core_if_t *_core_if, |
| 553 | ifxhcd_hc_t *_ifxhc, |
| 554 | ifxhcd_halt_status_e _halt_status); |
| 555 | |
| 556 | /*! |
| 557 | \brief Prepares a host channel for transferring packets to/from a specific |
| 558 | endpoint. The HCCHARn register is set up with the characteristics specified |
| 559 | in _ifxhc. Host channel interrupts that may need to be serviced while this |
| 560 | transfer is in progress are enabled. |
| 561 | */ |
| 562 | extern void ifxhcd_hc_init(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc); |
| 563 | |
| 564 | /*! |
| 565 | \brief This function is called to handle the disconnection of host port. |
| 566 | */ |
| 567 | int32_t ifxhcd_disconnect(ifxhcd_hcd_t *_ifxhcd); |
| 568 | /*@}*/ |
| 569 | |
| 570 | /*! \brief Interrupt Handler Functions */ |
| 571 | /*@{*/ |
| 572 | extern irqreturn_t ifxhcd_oc_irq(int _irq, void *_dev); |
| 573 | |
| 574 | extern int32_t ifxhcd_handle_oc_intr(ifxhcd_hcd_t *_ifxhcd); |
| 575 | extern int32_t ifxhcd_handle_intr (ifxhcd_hcd_t *_ifxhcd); |
| 576 | /*@}*/ |
| 577 | |
| 578 | |
| 579 | /*! \brief Schedule Queue Functions */ |
| 580 | /*@{*/ |
| 581 | extern ifxhcd_epqh_t *ifxhcd_epqh_create (ifxhcd_hcd_t *_ifxhcd, struct urb *_urb); |
| 582 | extern void ifxhcd_epqh_free ( ifxhcd_epqh_t *_epqh); |
| 583 | extern void select_eps (ifxhcd_hcd_t *_ifxhcd); |
| 584 | extern void process_channels(ifxhcd_hcd_t *_ifxhcd); |
| 585 | extern void process_channels_sub(ifxhcd_hcd_t *_ifxhcd); |
| 586 | extern void complete_channel(ifxhcd_hcd_t *_ifxhcd, ifxhcd_hc_t *_ifxhc, ifxhcd_urbd_t *_urbd); |
| 587 | extern void ifxhcd_epqh_ready(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh); |
| 588 | extern void ifxhcd_epqh_active(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh); |
| 589 | extern void ifxhcd_epqh_idle(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh); |
| 590 | extern void ifxhcd_epqh_idle_periodic(ifxhcd_epqh_t *_epqh); |
| 591 | extern int ifxhcd_urbd_create (ifxhcd_hcd_t *_ifxhcd,struct urb *_urb); |
| 592 | /*@}*/ |
| 593 | |
| 594 | /*! \brief Gets the usb_host_endpoint associated with an URB. */ |
| 595 | static inline struct usb_host_endpoint *ifxhcd_urb_to_endpoint(struct urb *_urb) |
| 596 | { |
| 597 | struct usb_device *dev = _urb->dev; |
| 598 | int ep_num = usb_pipeendpoint(_urb->pipe); |
| 599 | |
| 600 | return (usb_pipein(_urb->pipe))?(dev->ep_in[ep_num]):(dev->ep_out[ep_num]); |
| 601 | } |
| 602 | |
| 603 | /*! |
| 604 | * \brief Gets the endpoint number from a _bEndpointAddress argument. The endpoint is |
| 605 | * qualified with its direction (possible 32 endpoints per device). |
| 606 | */ |
| 607 | #define ifxhcd_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \ |
| 608 | ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4) |
| 609 | |
| 610 | |
| 611 | /* AVM/WK: not needed? |
| 612 | |
| 613 | extern struct usb_device *usb_alloc_dev (struct usb_device *parent, struct usb_bus *, unsigned port); |
| 614 | extern int usb_add_hcd (struct usb_hcd *syshcd, unsigned int irqnum, unsigned long irqflags); |
| 615 | extern void usb_remove_hcd (struct usb_hcd *syshcd); |
| 616 | extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, struct device *dev, char *bus_name); |
| 617 | extern void usb_hcd_giveback_urb (struct usb_hcd *syshcd, struct urb *urb); |
| 618 | extern void usb_put_hcd (struct usb_hcd *syshcd); |
| 619 | extern long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount); |
| 620 | |
| 621 | */ |
| 622 | /** Internal Functions */ |
| 623 | void ifxhcd_dump_state(ifxhcd_hcd_t *_ifxhcd); |
| 624 | extern char *syserr(int errno); |
| 625 | |
| 626 | /*@}*//*IFXUSB_HCD*/ |
| 627 | |
| 628 | #endif // __IFXHCD_H__ |
| 629 | |