Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

dwc_otg_cfi.c

Go to the documentation of this file.
00001 /* ==========================================================================
00002  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
00003  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
00004  * otherwise expressly agreed to in writing between Synopsys and you.
00005  * 
00006  * The Software IS NOT an item of Licensed Software or Licensed Product under
00007  * any End User Software License Agreement or Agreement for Licensed Product
00008  * with Synopsys or any supplement thereto. You are permitted to use and
00009  * redistribute this Software in source and binary forms, with or without
00010  * modification, provided that redistributions of source code must retain this
00011  * notice. You may not view, use, disclose, copy or distribute this file or
00012  * any information contained herein except pursuant to this license grant from
00013  * Synopsys. If you do not agree with this notice, including the disclaimer
00014  * below, then you are not authorized to use the Software.
00015  * 
00016  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
00017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00019  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
00020  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00024  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00025  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00026  * DAMAGE.
00027  * ========================================================================== */
00028 
00035 #ifdef DWC_UTE_CFI
00036 
00037 #include "dwc_otg_pcd.h"
00038 #include "dwc_otg_cfi.h"
00039 
00041 #define DWC_CONSTANT_CPU_TO_LE16(x) (x)
00042 
00043 extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex);
00044 
00045 static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen);
00046 static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
00047                                  struct dwc_otg_pcd *pcd,
00048                                  struct cfi_usb_ctrlrequest *ctrl_req);
00049 static int cfi_set_feature_value(struct dwc_otg_pcd *pcd);
00050 static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
00051                              struct cfi_usb_ctrlrequest *req);
00052 static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
00053                                  struct cfi_usb_ctrlrequest *req);
00054 static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
00055                                 struct cfi_usb_ctrlrequest *req);
00056 static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
00057                              struct cfi_usb_ctrlrequest *req);
00058 static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep);
00059 
00060 static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if);
00061 static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue);
00062 static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue);
00063 
00064 static uint8_t resize_fifos(dwc_otg_core_if_t * core_if);
00065 
00067 static cfi_all_features_header_t all_props_desc_header = {
00068         .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100),
00069         .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG),
00070         .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9),
00071 };
00072 
00074 static cfi_feature_desc_header_t prop_descs[] = {
00075 
00076         /* FT_ID_DMA_MODE */
00077         {
00078          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE),
00079          .bmAttributes = CFI_FEATURE_ATTR_RW,
00080          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1),
00081          },
00082 
00083         /* FT_ID_DMA_BUFFER_SETUP */
00084         {
00085          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP),
00086          .bmAttributes = CFI_FEATURE_ATTR_RW,
00087          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
00088          },
00089 
00090         /* FT_ID_DMA_BUFF_ALIGN */
00091         {
00092          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN),
00093          .bmAttributes = CFI_FEATURE_ATTR_RW,
00094          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00095          },
00096 
00097         /* FT_ID_DMA_CONCAT_SETUP */
00098         {
00099          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP),
00100          .bmAttributes = CFI_FEATURE_ATTR_RW,
00101          //.wDataLength  = DWC_CONSTANT_CPU_TO_LE16(6),
00102          },
00103 
00104         /* FT_ID_DMA_CIRCULAR */
00105         {
00106          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR),
00107          .bmAttributes = CFI_FEATURE_ATTR_RW,
00108          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
00109          },
00110 
00111         /* FT_ID_THRESHOLD_SETUP */
00112         {
00113          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP),
00114          .bmAttributes = CFI_FEATURE_ATTR_RW,
00115          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
00116          },
00117 
00118         /* FT_ID_DFIFO_DEPTH */
00119         {
00120          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH),
00121          .bmAttributes = CFI_FEATURE_ATTR_RO,
00122          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00123          },
00124 
00125         /* FT_ID_TX_FIFO_DEPTH */
00126         {
00127          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH),
00128          .bmAttributes = CFI_FEATURE_ATTR_RW,
00129          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00130          },
00131 
00132         /* FT_ID_RX_FIFO_DEPTH */
00133         {
00134          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH),
00135          .bmAttributes = CFI_FEATURE_ATTR_RW,
00136          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00137          }
00138 };
00139 
00141 cfi_string_t prop_name_table[] = {
00142         {FT_ID_DMA_MODE, "dma_mode"},
00143         {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"},
00144         {FT_ID_DMA_BUFF_ALIGN, "buffer_align"},
00145         {FT_ID_DMA_CONCAT_SETUP, "concat_setup"},
00146         {FT_ID_DMA_CIRCULAR, "buffer_circular"},
00147         {FT_ID_THRESHOLD_SETUP, "threshold_setup"},
00148         {FT_ID_DFIFO_DEPTH, "dfifo_depth"},
00149         {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"},
00150         {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"},
00151         {}
00152 };
00153 
00154 /************************************************************************/
00155 
00161 const uint8_t *get_prop_name(uint16_t prop_id, int *len)
00162 {
00163         cfi_string_t *pstr;
00164         *len = 0;
00165 
00166         for (pstr = prop_name_table; pstr && pstr->s; pstr++) {
00167                 if (pstr->id == prop_id) {
00168                         *len = DWC_STRLEN(pstr->s);
00169                         return pstr->s;
00170                 }
00171         }
00172         return NULL;
00173 }
00174 
00180 int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl)
00181 {
00182         int retval = 0;
00183         dwc_otg_pcd_ep_t *ep = NULL;
00184         cfiobject_t *cfi = pcd->cfi;
00185         struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
00186         uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength);
00187         uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue);
00188         uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex);
00189         uint32_t regaddr = 0;
00190         uint32_t regval = 0;
00191 
00192         /* Save this Control Request in the CFI object. 
00193          * The data field will be assigned in the data stage completion CB function.
00194          */
00195         cfi->ctrl_req = *ctrl;
00196         cfi->ctrl_req.data = NULL;
00197 
00198         cfi->need_gadget_att = 0;
00199         cfi->need_status_in_complete = 0;
00200 
00201         switch (ctrl->bRequest) {
00202         case VEN_CORE_GET_FEATURES:
00203                 retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN);
00204                 if (retval >= 0) {
00205                         //dump_msg(cfi->buf_in.buf, retval);
00206                         ep = &pcd->ep0;
00207 
00208                         retval = min((uint16_t) retval, wLen);
00209                         /* Transfer this buffer to the host through the EP0-IN EP */
00210                         ep->dwc_ep.dma_addr = cfi->buf_in.addr;
00211                         ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
00212                         ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
00213                         ep->dwc_ep.xfer_len = retval;
00214                         ep->dwc_ep.xfer_count = 0;
00215                         ep->dwc_ep.sent_zlp = 0;
00216                         ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00217 
00218                         pcd->ep0_pending = 1;
00219                         dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00220                 }
00221                 retval = 0;
00222                 break;
00223 
00224         case VEN_CORE_GET_FEATURE:
00225                 CFI_INFO("VEN_CORE_GET_FEATURE\n");
00226                 retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN,
00227                                                pcd, ctrl);
00228                 if (retval >= 0) {
00229                         ep = &pcd->ep0;
00230 
00231                         retval = min((uint16_t) retval, wLen);
00232                         /* Transfer this buffer to the host through the EP0-IN EP */
00233                         ep->dwc_ep.dma_addr = cfi->buf_in.addr;
00234                         ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
00235                         ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
00236                         ep->dwc_ep.xfer_len = retval;
00237                         ep->dwc_ep.xfer_count = 0;
00238                         ep->dwc_ep.sent_zlp = 0;
00239                         ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00240 
00241                         pcd->ep0_pending = 1;
00242                         dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00243                 }
00244                 CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval);
00245                 dump_msg(cfi->buf_in.buf, retval);
00246                 break;
00247 
00248         case VEN_CORE_SET_FEATURE:
00249                 CFI_INFO("VEN_CORE_SET_FEATURE\n");
00250                 /* Set up an XFER to get the data stage of the control request,
00251                  * which is the new value of the feature to be modified.
00252                  */
00253                 ep = &pcd->ep0;
00254                 ep->dwc_ep.is_in = 0;
00255                 ep->dwc_ep.dma_addr = cfi->buf_out.addr;
00256                 ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
00257                 ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
00258                 ep->dwc_ep.xfer_len = wLen;
00259                 ep->dwc_ep.xfer_count = 0;
00260                 ep->dwc_ep.sent_zlp = 0;
00261                 ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00262 
00263                 pcd->ep0_pending = 1;
00264                 /* Read the control write's data stage */
00265                 dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00266                 retval = 0;
00267                 break;
00268 
00269         case VEN_CORE_RESET_FEATURES:
00270                 CFI_INFO("VEN_CORE_RESET_FEATURES\n");
00271                 cfi->need_gadget_att = 1;
00272                 cfi->need_status_in_complete = 1;
00273                 retval = cfi_preproc_reset(pcd, ctrl);
00274                 CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval);
00275                 break;
00276 
00277         case VEN_CORE_ACTIVATE_FEATURES:
00278                 CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n");
00279                 break;
00280 
00281         case VEN_CORE_READ_REGISTER:
00282                 CFI_INFO("VEN_CORE_READ_REGISTER\n");
00283                 /* wValue optionally contains the HI WORD of the register offset and
00284                  * wIndex contains the LOW WORD of the register offset 
00285                  */
00286                 if (wValue == 0) {
00287                         /* @TODO - MAS - fix the access to the base field */
00288                         regaddr = 0;
00289                         //regaddr = (uint32_t) pcd->otg_dev->os_dep.base;
00290                         //GET_CORE_IF(pcd)->co
00291                         regaddr |= wIndex;
00292                 } else {
00293                         regaddr = (wValue << 16) | wIndex;
00294                 }
00295 
00296                 /* Read a 32-bit value of the memory at the regaddr */
00297                 regval = DWC_READ_REG32((uint32_t *) regaddr);
00298 
00299                 ep = &pcd->ep0;
00300                 dwc_memcpy(cfi->buf_in.buf, &regval, sizeof(uint32_t));
00301                 ep->dwc_ep.is_in = 1;
00302                 ep->dwc_ep.dma_addr = cfi->buf_in.addr;
00303                 ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
00304                 ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
00305                 ep->dwc_ep.xfer_len = wLen;
00306                 ep->dwc_ep.xfer_count = 0;
00307                 ep->dwc_ep.sent_zlp = 0;
00308                 ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00309 
00310                 pcd->ep0_pending = 1;
00311                 dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00312                 cfi->need_gadget_att = 0;
00313                 retval = 0;
00314                 break;
00315 
00316         case VEN_CORE_WRITE_REGISTER:
00317                 CFI_INFO("VEN_CORE_WRITE_REGISTER\n");
00318                 /* Set up an XFER to get the data stage of the control request,
00319                  * which is the new value of the register to be modified.
00320                  */
00321                 ep = &pcd->ep0;
00322                 ep->dwc_ep.is_in = 0;
00323                 ep->dwc_ep.dma_addr = cfi->buf_out.addr;
00324                 ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
00325                 ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
00326                 ep->dwc_ep.xfer_len = wLen;
00327                 ep->dwc_ep.xfer_count = 0;
00328                 ep->dwc_ep.sent_zlp = 0;
00329                 ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00330 
00331                 pcd->ep0_pending = 1;
00332                 /* Read the control write's data stage */
00333                 dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00334                 retval = 0;
00335                 break;
00336 
00337         default:
00338                 retval = -DWC_E_NOT_SUPPORTED;
00339                 break;
00340         }
00341 
00342         return retval;
00343 }
00344 
00356 static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen)
00357 {
00358         cfi_feature_desc_header_t *prop_hdr = prop_descs;
00359         cfi_feature_desc_header_t *prop;
00360         cfi_all_features_header_t *all_props_hdr = &all_props_desc_header;
00361         cfi_all_features_header_t *tmp;
00362         uint8_t *tmpbuf = buf;
00363         const uint8_t *pname = NULL;
00364         int i, j, namelen = 0, totlen;
00365 
00366         /* Prepare and copy the core features into the buffer */
00367         CFI_INFO("%s:\n", __func__);
00368 
00369         tmp = (cfi_all_features_header_t *) tmpbuf;
00370         *tmp = *all_props_hdr;
00371         tmpbuf += CFI_ALL_FEATURES_HDR_LEN;
00372 
00373         j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t);
00374         for (i = 0; i < j; i++, prop_hdr++) {
00375                 pname = get_prop_name(prop_hdr->wFeatureID, &namelen);
00376                 prop = (cfi_feature_desc_header_t *) tmpbuf;
00377                 *prop = *prop_hdr;
00378 
00379                 prop->bNameLen = namelen;
00380                 prop->wLength =
00381                     DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN +
00382                                              namelen);
00383 
00384                 tmpbuf += CFI_FEATURE_DESC_HDR_LEN;
00385                 dwc_memcpy(tmpbuf, pname, namelen);
00386                 tmpbuf += namelen;
00387         }
00388 
00389         totlen = tmpbuf - buf;
00390 
00391         if (totlen > 0) {
00392                 tmp = (cfi_all_features_header_t *) buf;
00393                 tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen);
00394         }
00395 
00396         return totlen;
00397 }
00398 
00402 static void cfi_release(cfiobject_t * cfiobj)
00403 {
00404         cfi_ep_t *cfiep;
00405         dwc_list_link_t *tmp;
00406 
00407         CFI_INFO("%s\n", __func__);
00408 
00409         if (cfiobj->buf_in.buf) {
00410                 DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf,
00411                              cfiobj->buf_in.addr);
00412                 cfiobj->buf_in.buf = NULL;
00413         }
00414 
00415         if (cfiobj->buf_out.buf) {
00416                 DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf,
00417                              cfiobj->buf_out.addr);
00418                 cfiobj->buf_out.buf = NULL;
00419         }
00420 
00421         /* Free the Buffer Setup values for each EP */
00422         //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) {
00423         DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) {
00424                 cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
00425                 cfi_free_ep_bs_dyn_data(cfiep);
00426         }
00427 }
00428 
00432 static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep)
00433 {
00434         if (cfiep->bm_sg) {
00435                 DWC_FREE(cfiep->bm_sg);
00436                 cfiep->bm_sg = NULL;
00437         }
00438 
00439         if (cfiep->bm_align) {
00440                 DWC_FREE(cfiep->bm_align);
00441                 cfiep->bm_align = NULL;
00442         }
00443 
00444         if (cfiep->bm_concat) {
00445                 if (NULL != cfiep->bm_concat->wTxBytes) {
00446                         DWC_FREE(cfiep->bm_concat->wTxBytes);
00447                         cfiep->bm_concat->wTxBytes = NULL;
00448                 }
00449                 DWC_FREE(cfiep->bm_concat);
00450                 cfiep->bm_concat = NULL;
00451         }
00452 }
00453 
00459 static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep)
00460 {
00461         int retval = 0;
00462 
00463         cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t));
00464         if (NULL == cfiep->bm_sg) {
00465                 CFI_INFO("Failed to allocate memory for SG feature value\n");
00466                 return -DWC_E_NO_MEMORY;
00467         }
00468         dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
00469 
00470         /* For the Concatenation feature's default value we do not allocate
00471          * memory for the wTxBytes field - it will be done in the set_feature_value
00472          * request handler.
00473          */
00474         cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t));
00475         if (NULL == cfiep->bm_concat) {
00476                 CFI_INFO
00477                     ("Failed to allocate memory for CONCATENATION feature value\n");
00478                 DWC_FREE(cfiep->bm_sg);
00479                 return -DWC_E_NO_MEMORY;
00480         }
00481         dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
00482 
00483         cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t));
00484         if (NULL == cfiep->bm_align) {
00485                 CFI_INFO
00486                     ("Failed to allocate memory for Alignment feature value\n");
00487                 DWC_FREE(cfiep->bm_sg);
00488                 DWC_FREE(cfiep->bm_concat);
00489                 return -DWC_E_NO_MEMORY;
00490         }
00491         dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t));
00492 
00493         return retval;
00494 }
00495 
00507 static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
00508                          struct dwc_otg_pcd_ep *ep)
00509 {
00510         cfi_ep_t *cfiep;
00511         int retval = -DWC_E_NOT_SUPPORTED;
00512 
00513         CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__,
00514                  "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress);
00515         /* MAS - Check whether this endpoint already is in the list */
00516         cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
00517 
00518         if (NULL == cfiep) {
00519                 /* Allocate a cfi_ep_t object */
00520                 cfiep = DWC_ALLOC(sizeof(cfi_ep_t));
00521                 if (NULL == cfiep) {
00522                         CFI_INFO
00523                             ("Unable to allocate memory for <cfiep> in function %s\n",
00524                              __func__);
00525                         return -DWC_E_NO_MEMORY;
00526                 }
00527                 dwc_memset(cfiep, 0, sizeof(cfi_ep_t));
00528 
00529                 /* Save the dwc_otg_pcd_ep pointer in the cfiep object */
00530                 cfiep->ep = ep;
00531 
00532                 /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */
00533                 ep->dwc_ep.descs =
00534                     DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP *
00535                                   sizeof(dwc_otg_dma_desc_t),
00536                                   &ep->dwc_ep.descs_dma_addr);
00537 
00538                 if (NULL == ep->dwc_ep.descs) {
00539                         DWC_FREE(cfiep);
00540                         return -DWC_E_NO_MEMORY;
00541                 }
00542 
00543                 DWC_LIST_INIT(&cfiep->lh);
00544 
00545                 /* Set the buffer mode to BM_STANDARD. It will be modified 
00546                  * when building descriptors for a specific buffer mode */
00547                 ep->dwc_ep.buff_mode = BM_STANDARD;
00548 
00549                 /* Create and initialize the default values for this EP's Buffer modes */
00550                 if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0)
00551                         return retval;
00552 
00553                 /* Add the cfi_ep_t object to the CFI object's list of active endpoints */
00554                 DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh);
00555                 retval = 0;
00556         } else {                /* The sought EP already is in the list */
00557                 CFI_INFO("%s: The sought EP already is in the list\n",
00558                          __func__);
00559         }
00560 
00561         return retval;
00562 }
00563 
00569 static int cfi_ctrl_write_complete(struct cfiobject *cfi,
00570                                    struct dwc_otg_pcd *pcd)
00571 {
00572         uint32_t addr, reg_value;
00573         uint16_t wIndex, wValue;
00574         uint8_t bRequest;
00575         uint8_t *buf = cfi->buf_out.buf;
00576         //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved;
00577         struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req;
00578         int retval = -DWC_E_NOT_SUPPORTED;
00579 
00580         CFI_INFO("%s\n", __func__);
00581 
00582         bRequest = ctrl_req->bRequest;
00583         wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
00584         wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
00585 
00586         /* 
00587          * Save the pointer to the data stage in the ctrl_req's <data> field.
00588          * The request should be already saved in the command stage by now.
00589          */
00590         ctrl_req->data = cfi->buf_out.buf;
00591         cfi->need_status_in_complete = 0;
00592         cfi->need_gadget_att = 0;
00593 
00594         switch (bRequest) {
00595         case VEN_CORE_WRITE_REGISTER:
00596                 /* The buffer contains raw data of the new value for the register */
00597                 reg_value = *((uint32_t *) buf);
00598                 if (wValue == 0) {
00599                         addr = 0;
00600                         //addr = (uint32_t) pcd->otg_dev->os_dep.base;
00601                         addr += wIndex;
00602                 } else {
00603                         addr = (wValue << 16) | wIndex;
00604                 }
00605 
00606                 //writel(reg_value, addr);
00607 
00608                 retval = 0;
00609                 cfi->need_status_in_complete = 1;
00610                 break;
00611 
00612         case VEN_CORE_SET_FEATURE:
00613                 /* The buffer contains raw data of the new value of the feature */
00614                 retval = cfi_set_feature_value(pcd);
00615                 if (retval < 0)
00616                         return retval;
00617 
00618                 cfi->need_status_in_complete = 1;
00619                 break;
00620 
00621         default:
00622                 break;
00623         }
00624 
00625         return retval;
00626 }
00627 
00631 static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00632                                dwc_otg_pcd_request_t * req)
00633 {
00634         struct dwc_otg_pcd_ep *ep = cfiep->ep;
00635         ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg;
00636         struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
00637         struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
00638         dma_addr_t buff_addr = req->dma;
00639         int i;
00640         uint32_t txsize, off;
00641 
00642         txsize = sgval->wSize;
00643         off = sgval->bOffset;
00644 
00645 //      CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n", 
00646 //              __func__, cfiep->ep->ep.name, txsize, off);
00647 
00648         for (i = 0; i < sgval->bCount; i++) {
00649                 desc->status.b.bs = BS_HOST_BUSY;
00650                 desc->buf = buff_addr;
00651                 desc->status.b.l = 0;
00652                 desc->status.b.ioc = 0;
00653                 desc->status.b.sp = 0;
00654                 desc->status.b.bytes = txsize;
00655                 desc->status.b.bs = BS_HOST_READY;
00656 
00657                 /* Set the next address of the buffer */
00658                 buff_addr += txsize + off;
00659                 desc_last = desc;
00660                 desc++;
00661         }
00662 
00663         /* Set the last, ioc and sp bits on the Last DMA Descriptor */
00664         desc_last->status.b.l = 1;
00665         desc_last->status.b.ioc = 1;
00666         desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
00667         /* Save the last DMA descriptor pointer */
00668         cfiep->dma_desc_last = desc_last;
00669         cfiep->desc_count = sgval->bCount;
00670 }
00671 
00675 static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00676                                    dwc_otg_pcd_request_t * req)
00677 {
00678         struct dwc_otg_pcd_ep *ep = cfiep->ep;
00679         ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat;
00680         struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
00681         struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
00682         dma_addr_t buff_addr = req->dma;
00683         int i;
00684         uint16_t *txsize;
00685 
00686         txsize = concatval->wTxBytes;
00687 
00688         for (i = 0; i < concatval->hdr.bDescCount; i++) {
00689                 desc->buf = buff_addr;
00690                 desc->status.b.bs = BS_HOST_BUSY;
00691                 desc->status.b.l = 0;
00692                 desc->status.b.ioc = 0;
00693                 desc->status.b.sp = 0;
00694                 desc->status.b.bytes = *txsize;
00695                 desc->status.b.bs = BS_HOST_READY;
00696 
00697                 txsize++;
00698                 /* Set the next address of the buffer */
00699                 buff_addr += UGETW(ep->desc->wMaxPacketSize);
00700                 desc_last = desc;
00701                 desc++;
00702         }
00703 
00704         /* Set the last, ioc and sp bits on the Last DMA Descriptor */
00705         desc_last->status.b.l = 1;
00706         desc_last->status.b.ioc = 1;
00707         desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
00708         cfiep->dma_desc_last = desc_last;
00709         cfiep->desc_count = concatval->hdr.bDescCount;
00710 }
00711 
00715 static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00716                                  dwc_otg_pcd_request_t * req)
00717 {
00718         /* @todo: MAS - add implementation when this feature needs to be tested */
00719 }
00720 
00724 static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00725                                   dwc_otg_pcd_request_t * req)
00726 {
00727         struct dwc_otg_pcd_ep *ep = cfiep->ep;
00728         ddma_align_buffer_setup_t *alignval = cfiep->bm_align;
00729         struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
00730         dma_addr_t buff_addr = req->dma;
00731 
00732         desc->status.b.bs = BS_HOST_BUSY;
00733         desc->status.b.l = 1;
00734         desc->status.b.ioc = 1;
00735         desc->status.b.sp = ep->dwc_ep.sent_zlp;
00736         desc->status.b.bytes = req->length;
00737         /* Adjust the buffer alignment */
00738         desc->buf = (buff_addr + alignval->bAlign);
00739         desc->status.b.bs = BS_HOST_READY;
00740         cfiep->dma_desc_last = desc;
00741         cfiep->desc_count = 1;
00742 }
00743 
00748 static void cfi_build_descriptors(struct cfiobject *cfi,
00749                                   struct dwc_otg_pcd *pcd,
00750                                   struct dwc_otg_pcd_ep *ep,
00751                                   dwc_otg_pcd_request_t * req)
00752 {
00753         cfi_ep_t *cfiep;
00754 
00755         /* Get the cfiep by the dwc_otg_pcd_ep */
00756         cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
00757         if (NULL == cfiep) {
00758                 CFI_INFO("%s: Unable to find a matching active endpoint\n",
00759                          __func__);
00760                 return;
00761         }
00762 
00763         cfiep->xfer_len = req->length;
00764 
00765         /* Iterate through all the DMA descriptors */
00766         switch (cfiep->ep->dwc_ep.buff_mode) {
00767         case BM_SG:
00768                 cfi_build_sg_descs(cfi, cfiep, req);
00769                 break;
00770 
00771         case BM_CONCAT:
00772                 cfi_build_concat_descs(cfi, cfiep, req);
00773                 break;
00774 
00775         case BM_CIRCULAR:
00776                 cfi_build_circ_descs(cfi, cfiep, req);
00777                 break;
00778 
00779         case BM_ALIGN:
00780                 cfi_build_align_descs(cfi, cfiep, req);
00781                 break;
00782 
00783         default:
00784                 break;
00785         }
00786 }
00787 
00791 static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
00792                               struct dwc_otg_pcd_ep *ep, dma_addr_t * dma,
00793                               unsigned size, gfp_t flags)
00794 {
00795         return DWC_DMA_ALLOC(size, dma);
00796 }
00797 
00801 int init_cfi(cfiobject_t * cfiobj)
00802 {
00803         CFI_INFO("%s\n", __func__);
00804 
00805         /* Allocate a buffer for IN XFERs */
00806         cfiobj->buf_in.buf =
00807             DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr);
00808         if (NULL == cfiobj->buf_in.buf) {
00809                 CFI_INFO("Unable to allocate buffer for INs\n");
00810                 return -DWC_E_NO_MEMORY;
00811         }
00812 
00813         /* Allocate a buffer for OUT XFERs */
00814         cfiobj->buf_out.buf =
00815             DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr);
00816         if (NULL == cfiobj->buf_out.buf) {
00817                 CFI_INFO("Unable to allocate buffer for OUT\n");
00818                 return -DWC_E_NO_MEMORY;
00819         }
00820 
00821         /* Initialize the callback function pointers */
00822         cfiobj->ops.release = cfi_release;
00823         cfiobj->ops.ep_enable = cfi_ep_enable;
00824         cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete;
00825         cfiobj->ops.build_descriptors = cfi_build_descriptors;
00826         cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf;
00827 
00828         /* Initialize the list of active endpoints in the CFI object */
00829         DWC_LIST_INIT(&cfiobj->active_eps);
00830 
00831         return 0;
00832 }
00833 
00839 static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
00840                                  struct dwc_otg_pcd *pcd,
00841                                  struct cfi_usb_ctrlrequest *ctrl_req)
00842 {
00843         int retval = -DWC_E_NOT_SUPPORTED;
00844         struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
00845         uint16_t dfifo, rxfifo, txfifo;
00846 
00847         switch (ctrl_req->wIndex) {
00848                 /* Whether the DDMA is enabled or not */
00849         case FT_ID_DMA_MODE:
00850                 *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0;
00851                 retval = 1;
00852                 break;
00853 
00854         case FT_ID_DMA_BUFFER_SETUP:
00855                 retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req);
00856                 break;
00857 
00858         case FT_ID_DMA_BUFF_ALIGN:
00859                 retval = cfi_ep_get_align_val(buf, pcd, ctrl_req);
00860                 break;
00861 
00862         case FT_ID_DMA_CONCAT_SETUP:
00863                 retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req);
00864                 break;
00865 
00866         case FT_ID_DMA_CIRCULAR:
00867                 CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n");
00868                 break;
00869 
00870         case FT_ID_THRESHOLD_SETUP:
00871                 CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n");
00872                 break;
00873 
00874         case FT_ID_DFIFO_DEPTH:
00875                 dfifo = get_dfifo_size(coreif);
00876                 *((uint16_t *) buf) = dfifo;
00877                 retval = sizeof(uint16_t);
00878                 break;
00879 
00880         case FT_ID_TX_FIFO_DEPTH:
00881                 retval = get_txfifo_size(pcd, ctrl_req->wValue);
00882                 if (retval >= 0) {
00883                         txfifo = retval;
00884                         *((uint16_t *) buf) = txfifo;
00885                         retval = sizeof(uint16_t);
00886                 }
00887                 break;
00888 
00889         case FT_ID_RX_FIFO_DEPTH:
00890                 retval = get_rxfifo_size(coreif, ctrl_req->wValue);
00891                 if (retval >= 0) {
00892                         rxfifo = retval;
00893                         *((uint16_t *) buf) = rxfifo;
00894                         retval = sizeof(uint16_t);
00895                 }
00896                 break;
00897         }
00898 
00899         return retval;
00900 }
00901 
00905 static int cfi_reset_sg_val(cfi_ep_t * cfiep)
00906 {
00907         dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
00908         return 0;
00909 }
00910 
00914 static int cfi_reset_align_val(cfi_ep_t * cfiep)
00915 {
00916         dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
00917         return 0;
00918 }
00919 
00925 static int cfi_reset_concat_val(cfi_ep_t * cfiep)
00926 {
00927         /* First we need to free the wTxBytes field */
00928         if (cfiep->bm_concat->wTxBytes) {
00929                 DWC_FREE(cfiep->bm_concat->wTxBytes);
00930                 cfiep->bm_concat->wTxBytes = NULL;
00931         }
00932 
00933         dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
00934         return 0;
00935 }
00936 
00940 static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep)
00941 {
00942         cfi_reset_sg_val(cfiep);
00943         cfi_reset_align_val(cfiep);
00944         cfi_reset_concat_val(cfiep);
00945         return 0;
00946 }
00947 
00948 static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr,
00949                                      uint8_t rx_rst, uint8_t tx_rst)
00950 {
00951         int retval = -DWC_E_INVALID;
00952         uint16_t tx_siz[15];
00953         uint16_t rx_siz = 0;
00954         dwc_otg_pcd_ep_t *ep = NULL;
00955         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
00956         dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
00957 
00958         if (rx_rst) {
00959                 rx_siz = params->dev_rx_fifo_size;
00960                 params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz;
00961         }
00962 
00963         if (tx_rst) {
00964                 if (ep_addr == 0) {
00965                         int i;
00966 
00967                         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
00968                                 tx_siz[i] =
00969                                     core_if->core_params->dev_tx_fifo_size[i];
00970                                 core_if->core_params->dev_tx_fifo_size[i] =
00971                                     core_if->init_txfsiz[i];
00972                         }
00973                 } else {
00974 
00975                         ep = get_ep_by_addr(pcd, ep_addr);
00976 
00977                         if (NULL == ep) {
00978                                 CFI_INFO
00979                                     ("%s: Unable to get the endpoint addr=0x%02x\n",
00980                                      __func__, ep_addr);
00981                                 return -DWC_E_INVALID;
00982                         }
00983 
00984                         tx_siz[0] =
00985                             params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num -
00986                                                      1];
00987                         params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] =
00988                             GET_CORE_IF(pcd)->init_txfsiz[ep->
00989                                                           dwc_ep.tx_fifo_num -
00990                                                           1];
00991                 }
00992         }
00993 
00994         if (resize_fifos(GET_CORE_IF(pcd))) {
00995                 retval = 0;
00996         } else {
00997                 CFI_INFO
00998                     ("%s: Error resetting the feature Reset All(FIFO size)\n",
00999                      __func__);
01000                 if (rx_rst) {
01001                         params->dev_rx_fifo_size = rx_siz;
01002                 }
01003 
01004                 if (tx_rst) {
01005                         if (ep_addr == 0) {
01006                                 int i;
01007                                 for (i = 0; i < core_if->hwcfg4.b.num_in_eps;
01008                                      i++) {
01009                                         core_if->
01010                                             core_params->dev_tx_fifo_size[i] =
01011                                             tx_siz[i];
01012                                 }
01013                         } else {
01014                                 params->dev_tx_fifo_size[ep->
01015                                                          dwc_ep.tx_fifo_num -
01016                                                          1] = tx_siz[0];
01017                         }
01018                 }
01019                 retval = -DWC_E_INVALID;
01020         }
01021         return retval;
01022 }
01023 
01024 static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr)
01025 {
01026         int retval = 0;
01027         cfi_ep_t *cfiep;
01028         cfiobject_t *cfi = pcd->cfi;
01029         dwc_list_link_t *tmp;
01030 
01031         retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1);
01032         if (retval < 0) {
01033                 return retval;
01034         }
01035 
01036         /* If the EP address is known then reset the features for only that EP */
01037         if (addr) {
01038                 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01039                 if (NULL == cfiep) {
01040                         CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01041                                  __func__, addr);
01042                         return -DWC_E_INVALID;
01043                 }
01044                 retval = cfi_ep_reset_all_setup_vals(cfiep);
01045                 cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
01046         }
01047         /* Otherwise (wValue == 0), reset all features of all EP's */
01048         else {
01049                 /* Traverse all the active EP's and reset the feature(s) value(s) */
01050                 //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
01051                 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01052                         cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01053                         retval = cfi_ep_reset_all_setup_vals(cfiep);
01054                         cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
01055                         if (retval < 0) {
01056                                 CFI_INFO
01057                                     ("%s: Error resetting the feature Reset All\n",
01058                                      __func__);
01059                                 return retval;
01060                         }
01061                 }
01062         }
01063         return retval;
01064 }
01065 
01066 static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd,
01067                                            uint8_t addr)
01068 {
01069         int retval = 0;
01070         cfi_ep_t *cfiep;
01071         cfiobject_t *cfi = pcd->cfi;
01072         dwc_list_link_t *tmp;
01073 
01074         /* If the EP address is known then reset the features for only that EP */
01075         if (addr) {
01076                 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01077                 if (NULL == cfiep) {
01078                         CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01079                                  __func__, addr);
01080                         return -DWC_E_INVALID;
01081                 }
01082                 retval = cfi_reset_sg_val(cfiep);
01083         }
01084         /* Otherwise (wValue == 0), reset all features of all EP's */
01085         else {
01086                 /* Traverse all the active EP's and reset the feature(s) value(s) */
01087                 //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
01088                 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01089                         cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01090                         retval = cfi_reset_sg_val(cfiep);
01091                         if (retval < 0) {
01092                                 CFI_INFO
01093                                     ("%s: Error resetting the feature Buffer Setup\n",
01094                                      __func__);
01095                                 return retval;
01096                         }
01097                 }
01098         }
01099         return retval;
01100 }
01101 
01102 static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr)
01103 {
01104         int retval = 0;
01105         cfi_ep_t *cfiep;
01106         cfiobject_t *cfi = pcd->cfi;
01107         dwc_list_link_t *tmp;
01108 
01109         /* If the EP address is known then reset the features for only that EP */
01110         if (addr) {
01111                 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01112                 if (NULL == cfiep) {
01113                         CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01114                                  __func__, addr);
01115                         return -DWC_E_INVALID;
01116                 }
01117                 retval = cfi_reset_concat_val(cfiep);
01118         }
01119         /* Otherwise (wValue == 0), reset all features of all EP's */
01120         else {
01121                 /* Traverse all the active EP's and reset the feature(s) value(s) */
01122                 //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
01123                 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01124                         cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01125                         retval = cfi_reset_concat_val(cfiep);
01126                         if (retval < 0) {
01127                                 CFI_INFO
01128                                     ("%s: Error resetting the feature Concatenation Value\n",
01129                                      __func__);
01130                                 return retval;
01131                         }
01132                 }
01133         }
01134         return retval;
01135 }
01136 
01137 static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr)
01138 {
01139         int retval = 0;
01140         cfi_ep_t *cfiep;
01141         cfiobject_t *cfi = pcd->cfi;
01142         dwc_list_link_t *tmp;
01143 
01144         /* If the EP address is known then reset the features for only that EP */
01145         if (addr) {
01146                 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01147                 if (NULL == cfiep) {
01148                         CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01149                                  __func__, addr);
01150                         return -DWC_E_INVALID;
01151                 }
01152                 retval = cfi_reset_align_val(cfiep);
01153         }
01154         /* Otherwise (wValue == 0), reset all features of all EP's */
01155         else {
01156                 /* Traverse all the active EP's and reset the feature(s) value(s) */
01157                 //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
01158                 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01159                         cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01160                         retval = cfi_reset_align_val(cfiep);
01161                         if (retval < 0) {
01162                                 CFI_INFO
01163                                     ("%s: Error resetting the feature Aliignment Value\n",
01164                                      __func__);
01165                                 return retval;
01166                         }
01167                 }
01168         }
01169         return retval;
01170 
01171 }
01172 
01173 static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
01174                              struct cfi_usb_ctrlrequest *req)
01175 {
01176         int retval = 0;
01177 
01178         switch (req->wIndex) {
01179         case 0:
01180                 /* Reset all features */
01181                 retval = cfi_handle_reset_all(pcd, req->wValue & 0xff);
01182                 break;
01183 
01184         case FT_ID_DMA_BUFFER_SETUP:
01185                 /* Reset the SG buffer setup */
01186                 retval =
01187                     cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff);
01188                 break;
01189 
01190         case FT_ID_DMA_CONCAT_SETUP:
01191                 /* Reset the Concatenation buffer setup */
01192                 retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff);
01193                 break;
01194 
01195         case FT_ID_DMA_BUFF_ALIGN:
01196                 /* Reset the Alignment buffer setup */
01197                 retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff);
01198                 break;
01199 
01200         case FT_ID_TX_FIFO_DEPTH:
01201                 retval =
01202                     cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1);
01203                 pcd->cfi->need_gadget_att = 0;
01204                 break;
01205 
01206         case FT_ID_RX_FIFO_DEPTH:
01207                 retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0);
01208                 pcd->cfi->need_gadget_att = 0;
01209                 break;
01210         default:
01211                 break;
01212         }
01213         return retval;
01214 }
01215 
01219 static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
01220 {
01221         uint8_t inaddr, outaddr;
01222         cfi_ep_t *epin, *epout;
01223         ddma_sg_buffer_setup_t *psgval;
01224         uint32_t desccount, size;
01225 
01226         CFI_INFO("%s\n", __func__);
01227 
01228         psgval = (ddma_sg_buffer_setup_t *) buf;
01229         desccount = (uint32_t) psgval->bCount;
01230         size = (uint32_t) psgval->wSize;
01231 
01232         /* Check the DMA descriptor count */
01233         if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) {
01234                 CFI_INFO
01235                     ("%s: The count of DMA Descriptors should be between 1 and %d\n",
01236                      __func__, MAX_DMA_DESCS_PER_EP);
01237                 return -DWC_E_INVALID;
01238         }
01239 
01240         /* Check the DMA descriptor count */
01241 
01242         if (size == 0) {
01243 
01244                 CFI_INFO("%s: The transfer size should be at least 1 byte\n",
01245                          __func__);
01246 
01247                 return -DWC_E_INVALID;
01248 
01249         }
01250 
01251         inaddr = psgval->bInEndpointAddress;
01252         outaddr = psgval->bOutEndpointAddress;
01253 
01254         epin = get_cfi_ep_by_addr(pcd->cfi, inaddr);
01255         epout = get_cfi_ep_by_addr(pcd->cfi, outaddr);
01256 
01257         if (NULL == epin || NULL == epout) {
01258                 CFI_INFO
01259                     ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n",
01260                      __func__, inaddr, outaddr);
01261                 return -DWC_E_INVALID;
01262         }
01263 
01264         epin->ep->dwc_ep.buff_mode = BM_SG;
01265         dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
01266 
01267         epout->ep->dwc_ep.buff_mode = BM_SG;
01268         dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
01269 
01270         return 0;
01271 }
01272 
01276 static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
01277 {
01278         cfi_ep_t *ep;
01279         uint8_t addr;
01280         ddma_align_buffer_setup_t *palignval;
01281 
01282         palignval = (ddma_align_buffer_setup_t *) buf;
01283         addr = palignval->bEndpointAddress;
01284 
01285         ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01286 
01287         if (NULL == ep) {
01288                 CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
01289                          __func__, addr);
01290                 return -DWC_E_INVALID;
01291         }
01292 
01293         ep->ep->dwc_ep.buff_mode = BM_ALIGN;
01294         dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t));
01295 
01296         return 0;
01297 }
01298 
01302 static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
01303 {
01304         uint8_t addr;
01305         cfi_ep_t *ep;
01306         struct _ddma_concat_buffer_setup_hdr *pConcatValHdr;
01307         uint16_t *pVals;
01308         uint32_t desccount;
01309         int i;
01310         uint16_t mps;
01311 
01312         pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf;
01313         desccount = (uint32_t) pConcatValHdr->bDescCount;
01314         pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN);
01315 
01316         /* Check the DMA descriptor count */
01317         if (desccount > MAX_DMA_DESCS_PER_EP) {
01318                 CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n",
01319                          __func__, MAX_DMA_DESCS_PER_EP);
01320                 return -DWC_E_INVALID;
01321         }
01322 
01323         addr = pConcatValHdr->bEndpointAddress;
01324         ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01325         if (NULL == ep) {
01326                 CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
01327                          __func__, addr);
01328                 return -DWC_E_INVALID;
01329         }
01330 
01331         mps = UGETW(ep->ep->desc->wMaxPacketSize);
01332 
01333 #if 0
01334         for (i = 0; i < desccount; i++) {
01335                 CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]);
01336         }
01337         CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps);
01338 #endif
01339 
01340         /* Check the wTxSizes to be less than or equal to the mps */
01341         for (i = 0; i < desccount; i++) {
01342                 if (pVals[i] > mps) {
01343                         CFI_INFO
01344                             ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n",
01345                              __func__, i, pVals[i]);
01346                         return -DWC_E_INVALID;
01347                 }
01348         }
01349 
01350         ep->ep->dwc_ep.buff_mode = BM_CONCAT;
01351         dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN);
01352 
01353         /* Free the previously allocated storage for the wTxBytes */
01354         if (ep->bm_concat->wTxBytes) {
01355                 DWC_FREE(ep->bm_concat->wTxBytes);
01356         }
01357 
01358         /* Allocate a new storage for the wTxBytes field */
01359         ep->bm_concat->wTxBytes =
01360             DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount);
01361         if (NULL == ep->bm_concat->wTxBytes) {
01362                 CFI_INFO("%s: Unable to allocate memory\n", __func__);
01363                 return -DWC_E_NO_MEMORY;
01364         }
01365 
01366         /* Copy the new values into the wTxBytes filed */
01367         dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN,
01368                    sizeof(uint16_t) * pConcatValHdr->bDescCount);
01369 
01370         return 0;
01371 }
01372 
01381 static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if)
01382 {
01383         dwc_otg_core_params_t *params = core_if->core_params;
01384         uint16_t dfifo_total = 0;
01385         int i;
01386 
01387         /* The shared RxFIFO size */
01388         dfifo_total =
01389             params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
01390 
01391         /* Add up each TxFIFO size to the total */
01392         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01393                 dfifo_total += params->dev_tx_fifo_size[i];
01394         }
01395 
01396         return dfifo_total;
01397 }
01398 
01407 static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue)
01408 {
01409         switch (wValue >> 8) {
01410         case 0:
01411                 return (core_if->pwron_rxfsiz <
01412                         32768) ? core_if->pwron_rxfsiz : 32768;
01413                 break;
01414         case 1:
01415                 return core_if->core_params->dev_rx_fifo_size;
01416                 break;
01417         default:
01418                 return -DWC_E_INVALID;
01419                 break;
01420         }
01421 }
01422 
01431 static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue)
01432 {
01433         dwc_otg_pcd_ep_t *ep;
01434 
01435         ep = get_ep_by_addr(pcd, wValue & 0xff);
01436 
01437         if (NULL == ep) {
01438                 CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
01439                          __func__, wValue & 0xff);
01440                 return -DWC_E_INVALID;
01441         }
01442 
01443         if (!ep->dwc_ep.is_in) {
01444                 CFI_INFO
01445                     ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n",
01446                      __func__, wValue & 0xff);
01447                 return -DWC_E_INVALID;
01448         }
01449 
01450         switch (wValue >> 8) {
01451         case 0:
01452                 return (GET_CORE_IF(pcd)->pwron_txfsiz
01453                         [ep->dwc_ep.tx_fifo_num - 1] <
01454                         768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->
01455                                                               dwc_ep.tx_fifo_num
01456                                                               - 1] : 32768;
01457                 break;
01458         case 1:
01459                 return GET_CORE_IF(pcd)->core_params->
01460                     dev_tx_fifo_size[ep->dwc_ep.num - 1];
01461                 break;
01462         default:
01463                 return -DWC_E_INVALID;
01464                 break;
01465         }
01466 }
01467 
01477 static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if)
01478 {
01479         uint16_t dfifo_actual = 0;
01480         dwc_otg_core_params_t *params = core_if->core_params;
01481         uint16_t start_addr = 0;
01482         int i;
01483 
01484         dfifo_actual =
01485             params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
01486 
01487         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01488                 dfifo_actual += params->dev_tx_fifo_size[i];
01489         }
01490 
01491         if (dfifo_actual > core_if->total_fifo_size) {
01492                 return 0;
01493         }
01494 
01495         if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16)
01496                 return 0;
01497 
01498         if (params->dev_nperio_tx_fifo_size > 32768
01499             || params->dev_nperio_tx_fifo_size < 16)
01500                 return 0;
01501 
01502         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01503 
01504                 if (params->dev_tx_fifo_size[i] > 768
01505                     || params->dev_tx_fifo_size[i] < 4)
01506                         return 0;
01507         }
01508 
01509         if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz)
01510                 return 0;
01511         start_addr = params->dev_rx_fifo_size;
01512 
01513         if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz)
01514                 return 0;
01515         start_addr += params->dev_nperio_tx_fifo_size;
01516 
01517         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01518 
01519                 if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i])
01520                         return 0;
01521                 start_addr += params->dev_tx_fifo_size[i];
01522         }
01523 
01524         return 1;
01525 }
01526 
01535 static uint8_t resize_fifos(dwc_otg_core_if_t * core_if)
01536 {
01537         int i = 0;
01538         dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
01539         dwc_otg_core_params_t *params = core_if->core_params;
01540         uint32_t rx_fifo_size;
01541         fifosize_data_t nptxfifosize;
01542         fifosize_data_t txfifosize[15];
01543 
01544         uint32_t rx_fsz_bak;
01545         uint32_t nptxfsz_bak;
01546         uint32_t txfsz_bak[15];
01547 
01548         uint16_t start_address;
01549         uint8_t retval = 1;
01550 
01551         if (!check_fifo_sizes(core_if)) {
01552                 return 0;
01553         }
01554 
01555         /* Configure data FIFO sizes */
01556         if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
01557                 rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz);
01558                 rx_fifo_size = params->dev_rx_fifo_size;
01559                 DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
01560 
01561                 /*
01562                  * Tx FIFOs These FIFOs are numbered from 1 to 15.
01563                  * Indexes of the FIFO size module parameters in the
01564                  * dev_tx_fifo_size array and the FIFO size registers in
01565                  * the dtxfsiz array run from 0 to 14.
01566                  */
01567 
01568                 /* Non-periodic Tx FIFO */
01569                 nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz);
01570                 nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
01571                 start_address = params->dev_rx_fifo_size;
01572                 nptxfifosize.b.startaddr = start_address;
01573 
01574                 DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
01575 
01576                 start_address += nptxfifosize.b.depth;
01577 
01578                 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01579                         txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]);
01580 
01581                         txfifosize[i].b.depth = params->dev_tx_fifo_size[i];
01582                         txfifosize[i].b.startaddr = start_address;
01583                         DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
01584                                         txfifosize[i].d32);
01585 
01586                         start_address += txfifosize[i].b.depth;
01587                 }
01588 
01590                 if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) {
01591                         retval = 0;
01592                 }
01593 
01594                 if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) {
01595                         retval = 0;
01596                 }
01597 
01598                 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01599                         if (txfifosize[i].d32 !=
01600                             DWC_READ_REG32(&global_regs->dtxfsiz[i])) {
01601                                 retval = 0;
01602                         }
01603                 }
01604 
01606                 if (retval == 0) {
01607                         DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak);
01608 
01609                         /* Non-periodic Tx FIFO */
01610                         DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak);
01611 
01612                         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01613                                 DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
01614                                                 txfsz_bak[i]);
01615                         }
01616                 }
01617         } else {
01618                 return 0;
01619         }
01620 
01621         /* Flush the FIFOs */
01622         dwc_otg_flush_tx_fifo(core_if, 0x10);   /* all Tx FIFOs */
01623         dwc_otg_flush_rx_fifo(core_if);
01624 
01625         return retval;
01626 }
01627 
01631 static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
01632 {
01633         int retval;
01634         uint32_t fsiz;
01635         uint16_t size;
01636         uint16_t ep_addr;
01637         dwc_otg_pcd_ep_t *ep;
01638         dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
01639         tx_fifo_size_setup_t *ptxfifoval;
01640 
01641         ptxfifoval = (tx_fifo_size_setup_t *) buf;
01642         ep_addr = ptxfifoval->bEndpointAddress;
01643         size = ptxfifoval->wDepth;
01644 
01645         ep = get_ep_by_addr(pcd, ep_addr);
01646 
01647         CFI_INFO
01648             ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n",
01649              __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num);
01650 
01651         if (NULL == ep) {
01652                 CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
01653                          __func__, ep_addr);
01654                 return -DWC_E_INVALID;
01655         }
01656 
01657         fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1];
01658         params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size;
01659 
01660         if (resize_fifos(GET_CORE_IF(pcd))) {
01661                 retval = 0;
01662         } else {
01663                 CFI_INFO
01664                     ("%s: Error setting the feature Tx FIFO Size for EP%d\n",
01665                      __func__, ep_addr);
01666                 params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz;
01667                 retval = -DWC_E_INVALID;
01668         }
01669 
01670         return retval;
01671 }
01672 
01676 static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
01677 {
01678         int retval;
01679         uint32_t fsiz;
01680         uint16_t size;
01681         dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
01682         rx_fifo_size_setup_t *prxfifoval;
01683 
01684         prxfifoval = (rx_fifo_size_setup_t *) buf;
01685         size = prxfifoval->wDepth;
01686 
01687         fsiz = params->dev_rx_fifo_size;
01688         params->dev_rx_fifo_size = size;
01689 
01690         if (resize_fifos(GET_CORE_IF(pcd))) {
01691                 retval = 0;
01692         } else {
01693                 CFI_INFO("%s: Error setting the feature Rx FIFO Size\n",
01694                          __func__);
01695                 params->dev_rx_fifo_size = fsiz;
01696                 retval = -DWC_E_INVALID;
01697         }
01698 
01699         return retval;
01700 }
01701 
01705 static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
01706                              struct cfi_usb_ctrlrequest *req)
01707 {
01708         int retval = -DWC_E_INVALID;
01709         uint8_t addr;
01710         cfi_ep_t *ep;
01711 
01712         /* The Low Byte of the wValue contains a non-zero address of the endpoint */
01713         addr = req->wValue & 0xFF;
01714         if (addr == 0)          /* The address should be non-zero */
01715                 return retval;
01716 
01717         ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01718         if (NULL == ep) {
01719                 CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
01720                          __func__, addr);
01721                 return retval;
01722         }
01723 
01724         dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN);
01725         retval = BS_SG_VAL_DESC_LEN;
01726         return retval;
01727 }
01728 
01733 static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
01734                                  struct cfi_usb_ctrlrequest *req)
01735 {
01736         int retval = -DWC_E_INVALID;
01737         uint8_t addr;
01738         cfi_ep_t *ep;
01739         uint8_t desc_count;
01740 
01741         /* The Low Byte of the wValue contains a non-zero address of the endpoint */
01742         addr = req->wValue & 0xFF;
01743         if (addr == 0)          /* The address should be non-zero */
01744                 return retval;
01745 
01746         ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01747         if (NULL == ep) {
01748                 CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
01749                          __func__, addr);
01750                 return retval;
01751         }
01752 
01753         /* Copy the header to the buffer */
01754         dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN);
01755         /* Advance the buffer pointer by the header size */
01756         buf += BS_CONCAT_VAL_HDR_LEN;
01757 
01758         desc_count = ep->bm_concat->hdr.bDescCount;
01759         /* Copy alll the wTxBytes to the buffer */
01760         dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count);
01761 
01762         retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count;
01763         return retval;
01764 }
01765 
01772 static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
01773                                 struct cfi_usb_ctrlrequest *req)
01774 {
01775         int retval = -DWC_E_INVALID;
01776         uint8_t addr;
01777         cfi_ep_t *ep;
01778 
01779         /* The Low Byte of the wValue contains a non-zero address of the endpoint */
01780         addr = req->wValue & 0xFF;
01781         if (addr == 0)          /* The address should be non-zero */
01782                 return retval;
01783 
01784         ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01785         if (NULL == ep) {
01786                 CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
01787                          __func__, addr);
01788                 return retval;
01789         }
01790 
01791         dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN);
01792         retval = BS_ALIGN_VAL_HDR_LEN;
01793 
01794         return retval;
01795 }
01796 
01804 static int cfi_set_feature_value(struct dwc_otg_pcd *pcd)
01805 {
01806         int retval = -DWC_E_NOT_SUPPORTED;
01807         uint16_t wIndex, wValue;
01808         uint8_t bRequest;
01809         struct dwc_otg_core_if *coreif;
01810         cfiobject_t *cfi = pcd->cfi;
01811         struct cfi_usb_ctrlrequest *ctrl_req;
01812         uint8_t *buf;
01813         ctrl_req = &cfi->ctrl_req;
01814 
01815         buf = pcd->cfi->ctrl_req.data;
01816 
01817         coreif = GET_CORE_IF(pcd);
01818         bRequest = ctrl_req->bRequest;
01819         wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
01820         wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
01821 
01822         /* See which feature is to be modified */
01823         switch (wIndex) {
01824         case FT_ID_DMA_BUFFER_SETUP:
01825                 /* Modify the feature */
01826                 if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0)
01827                         return retval;
01828 
01829                 /* And send this request to the gadget */
01830                 cfi->need_gadget_att = 1;
01831                 break;
01832 
01833         case FT_ID_DMA_BUFF_ALIGN:
01834                 if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0)
01835                         return retval;
01836                 cfi->need_gadget_att = 1;
01837                 break;
01838 
01839         case FT_ID_DMA_CONCAT_SETUP:
01840                 /* Modify the feature */
01841                 if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0)
01842                         return retval;
01843                 cfi->need_gadget_att = 1;
01844                 break;
01845 
01846         case FT_ID_DMA_CIRCULAR:
01847                 CFI_INFO("FT_ID_DMA_CIRCULAR\n");
01848                 break;
01849 
01850         case FT_ID_THRESHOLD_SETUP:
01851                 CFI_INFO("FT_ID_THRESHOLD_SETUP\n");
01852                 break;
01853 
01854         case FT_ID_DFIFO_DEPTH:
01855                 CFI_INFO("FT_ID_DFIFO_DEPTH\n");
01856                 break;
01857 
01858         case FT_ID_TX_FIFO_DEPTH:
01859                 CFI_INFO("FT_ID_TX_FIFO_DEPTH\n");
01860                 if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0)
01861                         return retval;
01862                 cfi->need_gadget_att = 0;
01863                 break;
01864 
01865         case FT_ID_RX_FIFO_DEPTH:
01866                 CFI_INFO("FT_ID_RX_FIFO_DEPTH\n");
01867                 if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0)
01868                         return retval;
01869                 cfi->need_gadget_att = 0;
01870                 break;
01871         }
01872 
01873         return retval;
01874 }
01875 
01876 #endif //DWC_UTE_CFI

Generated on Thu Oct 27 03:56:37 2011 for DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver by  doxygen 1.3.9.1