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 
00034 #ifdef DWC_UTE_CFI
00035 
00036 #include "dwc_otg_pcd.h"
00037 #include "dwc_otg_cfi.h"
00038 
00040 #define DWC_CONSTANT_CPU_TO_LE16(x) (x)
00041 
00042 extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex);
00043 
00044 static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen);
00045 static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
00046                                  struct dwc_otg_pcd *pcd,
00047                                  struct cfi_usb_ctrlrequest *ctrl_req);
00048 static int cfi_set_feature_value(struct dwc_otg_pcd *pcd);
00049 static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
00050                              struct cfi_usb_ctrlrequest *req);
00051 static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
00052                                  struct cfi_usb_ctrlrequest *req);
00053 static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
00054                                 struct cfi_usb_ctrlrequest *req);
00055 static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
00056                              struct cfi_usb_ctrlrequest *req);
00057 static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep);
00058 
00059 static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if);
00060 static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue);
00061 static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue);
00062 
00063 static uint8_t resize_fifos(dwc_otg_core_if_t * core_if);
00064 
00066 static cfi_all_features_header_t all_props_desc_header = {
00067         .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100),
00068         .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG),
00069         .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9),
00070 };
00071 
00073 static cfi_feature_desc_header_t prop_descs[] = {
00074 
00075         /* FT_ID_DMA_MODE */
00076         {
00077          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE),
00078          .bmAttributes = CFI_FEATURE_ATTR_RW,
00079          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1),
00080          },
00081 
00082         /* FT_ID_DMA_BUFFER_SETUP */
00083         {
00084          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP),
00085          .bmAttributes = CFI_FEATURE_ATTR_RW,
00086          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
00087          },
00088 
00089         /* FT_ID_DMA_BUFF_ALIGN */
00090         {
00091          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN),
00092          .bmAttributes = CFI_FEATURE_ATTR_RW,
00093          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00094          },
00095 
00096         /* FT_ID_DMA_CONCAT_SETUP */
00097         {
00098          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP),
00099          .bmAttributes = CFI_FEATURE_ATTR_RW,
00100          //.wDataLength  = DWC_CONSTANT_CPU_TO_LE16(6),
00101          },
00102 
00103         /* FT_ID_DMA_CIRCULAR */
00104         {
00105          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR),
00106          .bmAttributes = CFI_FEATURE_ATTR_RW,
00107          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
00108          },
00109 
00110         /* FT_ID_THRESHOLD_SETUP */
00111         {
00112          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP),
00113          .bmAttributes = CFI_FEATURE_ATTR_RW,
00114          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
00115          },
00116 
00117         /* FT_ID_DFIFO_DEPTH */
00118         {
00119          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH),
00120          .bmAttributes = CFI_FEATURE_ATTR_RO,
00121          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00122          },
00123 
00124         /* FT_ID_TX_FIFO_DEPTH */
00125         {
00126          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH),
00127          .bmAttributes = CFI_FEATURE_ATTR_RW,
00128          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00129          },
00130 
00131         /* FT_ID_RX_FIFO_DEPTH */
00132         {
00133          .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH),
00134          .bmAttributes = CFI_FEATURE_ATTR_RW,
00135          .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
00136          }
00137 };
00138 
00140 cfi_string_t prop_name_table[] = {
00141         {FT_ID_DMA_MODE, "dma_mode"},
00142         {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"},
00143         {FT_ID_DMA_BUFF_ALIGN, "buffer_align"},
00144         {FT_ID_DMA_CONCAT_SETUP, "concat_setup"},
00145         {FT_ID_DMA_CIRCULAR, "buffer_circular"},
00146         {FT_ID_THRESHOLD_SETUP, "threshold_setup"},
00147         {FT_ID_DFIFO_DEPTH, "dfifo_depth"},
00148         {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"},
00149         {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"},
00150         {}
00151 };
00152 
00153 /************************************************************************/
00154 
00160 const uint8_t *get_prop_name(uint16_t prop_id, int *len)
00161 {
00162         cfi_string_t *pstr;
00163         *len = 0;
00164 
00165         for (pstr = prop_name_table; pstr && pstr->s; pstr++) {
00166                 if (pstr->id == prop_id) {
00167                         *len = DWC_STRLEN(pstr->s);
00168                         return pstr->s;
00169                 }
00170         }
00171         return NULL;
00172 }
00173 
00179 int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl)
00180 {
00181         int retval = 0;
00182         dwc_otg_pcd_ep_t *ep = NULL;
00183         cfiobject_t *cfi = pcd->cfi;
00184         struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
00185         uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength);
00186         uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue);
00187         uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex);
00188         uint32_t regaddr = 0;
00189         uint32_t regval = 0;
00190 
00191         /* Save this Control Request in the CFI object. 
00192          * The data field will be assigned in the data stage completion CB function.
00193          */
00194         cfi->ctrl_req = *ctrl;
00195         cfi->ctrl_req.data = NULL;
00196 
00197         cfi->need_gadget_att = 0;
00198         cfi->need_status_in_complete = 0;
00199 
00200         switch (ctrl->bRequest) {
00201         case VEN_CORE_GET_FEATURES:
00202                 retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN);
00203                 if (retval >= 0) {
00204                         //dump_msg(cfi->buf_in.buf, retval);
00205                         ep = &pcd->ep0;
00206 
00207                         retval = min((uint16_t) retval, wLen);
00208                         /* Transfer this buffer to the host through the EP0-IN EP */
00209                         ep->dwc_ep.dma_addr = cfi->buf_in.addr;
00210                         ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
00211                         ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
00212                         ep->dwc_ep.xfer_len = retval;
00213                         ep->dwc_ep.xfer_count = 0;
00214                         ep->dwc_ep.sent_zlp = 0;
00215                         ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00216 
00217                         pcd->ep0_pending = 1;
00218                         dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00219                 }
00220                 retval = 0;
00221                 break;
00222 
00223         case VEN_CORE_GET_FEATURE:
00224                 CFI_INFO("VEN_CORE_GET_FEATURE\n");
00225                 retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN,
00226                                                pcd, ctrl);
00227                 if (retval >= 0) {
00228                         ep = &pcd->ep0;
00229 
00230                         retval = min((uint16_t) retval, wLen);
00231                         /* Transfer this buffer to the host through the EP0-IN EP */
00232                         ep->dwc_ep.dma_addr = cfi->buf_in.addr;
00233                         ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
00234                         ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
00235                         ep->dwc_ep.xfer_len = retval;
00236                         ep->dwc_ep.xfer_count = 0;
00237                         ep->dwc_ep.sent_zlp = 0;
00238                         ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00239 
00240                         pcd->ep0_pending = 1;
00241                         dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00242                 }
00243                 CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval);
00244                 dump_msg(cfi->buf_in.buf, retval);
00245                 break;
00246 
00247         case VEN_CORE_SET_FEATURE:
00248                 CFI_INFO("VEN_CORE_SET_FEATURE\n");
00249                 /* Set up an XFER to get the data stage of the control request,
00250                  * which is the new value of the feature to be modified.
00251                  */
00252                 ep = &pcd->ep0;
00253                 ep->dwc_ep.is_in = 0;
00254                 ep->dwc_ep.dma_addr = cfi->buf_out.addr;
00255                 ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
00256                 ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
00257                 ep->dwc_ep.xfer_len = wLen;
00258                 ep->dwc_ep.xfer_count = 0;
00259                 ep->dwc_ep.sent_zlp = 0;
00260                 ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00261 
00262                 pcd->ep0_pending = 1;
00263                 /* Read the control write's data stage */
00264                 dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00265                 retval = 0;
00266                 break;
00267 
00268         case VEN_CORE_RESET_FEATURES:
00269                 CFI_INFO("VEN_CORE_RESET_FEATURES\n");
00270                 cfi->need_gadget_att = 1;
00271                 cfi->need_status_in_complete = 1;
00272                 retval = cfi_preproc_reset(pcd, ctrl);
00273                 CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval);
00274                 break;
00275 
00276         case VEN_CORE_ACTIVATE_FEATURES:
00277                 CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n");
00278                 break;
00279 
00280         case VEN_CORE_READ_REGISTER:
00281                 CFI_INFO("VEN_CORE_READ_REGISTER\n");
00282                 /* wValue optionally contains the HI WORD of the register offset and
00283                  * wIndex contains the LOW WORD of the register offset 
00284                  */
00285                 if (wValue == 0) {
00286                         /* @TODO - MAS - fix the access to the base field */
00287                         regaddr = 0;
00288                         //regaddr = (uint32_t) pcd->otg_dev->base;
00289                         //GET_CORE_IF(pcd)->co
00290                         regaddr |= wIndex;
00291                 } else {
00292                         regaddr = (wValue << 16) | wIndex;
00293                 }
00294 
00295                 /* Read a 32-bit value of the memory at the regaddr */
00296                 regval = dwc_read_reg32((uint32_t *) regaddr);
00297 
00298                 ep = &pcd->ep0;
00299                 dwc_memcpy(cfi->buf_in.buf, &regval, sizeof(uint32_t));
00300                 ep->dwc_ep.is_in = 1;
00301                 ep->dwc_ep.dma_addr = cfi->buf_in.addr;
00302                 ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
00303                 ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
00304                 ep->dwc_ep.xfer_len = wLen;
00305                 ep->dwc_ep.xfer_count = 0;
00306                 ep->dwc_ep.sent_zlp = 0;
00307                 ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00308 
00309                 pcd->ep0_pending = 1;
00310                 dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00311                 cfi->need_gadget_att = 0;
00312                 retval = 0;
00313                 break;
00314 
00315         case VEN_CORE_WRITE_REGISTER:
00316                 CFI_INFO("VEN_CORE_WRITE_REGISTER\n");
00317                 /* Set up an XFER to get the data stage of the control request,
00318                  * which is the new value of the register to be modified.
00319                  */
00320                 ep = &pcd->ep0;
00321                 ep->dwc_ep.is_in = 0;
00322                 ep->dwc_ep.dma_addr = cfi->buf_out.addr;
00323                 ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
00324                 ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
00325                 ep->dwc_ep.xfer_len = wLen;
00326                 ep->dwc_ep.xfer_count = 0;
00327                 ep->dwc_ep.sent_zlp = 0;
00328                 ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
00329 
00330                 pcd->ep0_pending = 1;
00331                 /* Read the control write's data stage */
00332                 dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
00333                 retval = 0;
00334                 break;
00335 
00336         default:
00337                 retval = -DWC_E_NOT_SUPPORTED;
00338                 break;
00339         }
00340 
00341         return retval;
00342 }
00343 
00355 static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen)
00356 {
00357         cfi_feature_desc_header_t *prop_hdr = prop_descs;
00358         cfi_feature_desc_header_t *prop;
00359         cfi_all_features_header_t *all_props_hdr = &all_props_desc_header;
00360         cfi_all_features_header_t *tmp;
00361         uint8_t *tmpbuf = buf;
00362         const uint8_t *pname = NULL;
00363         int i, j, namelen = 0, totlen;
00364 
00365         /* Prepare and copy the core features into the buffer */
00366         CFI_INFO("%s:\n", __func__);
00367 
00368         tmp = (cfi_all_features_header_t *) tmpbuf;
00369         *tmp = *all_props_hdr;
00370         tmpbuf += CFI_ALL_FEATURES_HDR_LEN;
00371 
00372         j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t);
00373         for (i = 0; i < j; i++, prop_hdr++) {
00374                 pname = get_prop_name(prop_hdr->wFeatureID, &namelen);
00375                 prop = (cfi_feature_desc_header_t *) tmpbuf;
00376                 *prop = *prop_hdr;
00377 
00378                 prop->bNameLen = namelen;
00379                 prop->wLength =
00380                     DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN +
00381                                              namelen);
00382 
00383                 tmpbuf += CFI_FEATURE_DESC_HDR_LEN;
00384                 dwc_memcpy(tmpbuf, pname, namelen);
00385                 tmpbuf += namelen;
00386         }
00387 
00388         totlen = tmpbuf - buf;
00389 
00390         if (totlen > 0) {
00391                 tmp = (cfi_all_features_header_t *) buf;
00392                 tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen);
00393         }
00394 
00395         return totlen;
00396 }
00397 
00401 static void cfi_release(cfiobject_t * cfiobj)
00402 {
00403         cfi_ep_t *cfiep;
00404         dwc_list_link_t *tmp;
00405 
00406         CFI_INFO("%s\n", __func__);
00407 
00408         if (cfiobj->buf_in.buf) {
00409                 dwc_dma_free(CFI_IN_BUF_LEN, cfiobj->buf_in.buf,
00410                              cfiobj->buf_in.addr);
00411                 cfiobj->buf_in.buf = NULL;
00412         }
00413 
00414         if (cfiobj->buf_out.buf) {
00415                 dwc_dma_free(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf,
00416                              cfiobj->buf_out.addr);
00417                 cfiobj->buf_out.buf = NULL;
00418         }
00419 
00420         /* Free the Buffer Setup values for each EP */
00421         //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) {
00422         DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) {
00423                 cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
00424                 cfi_free_ep_bs_dyn_data(cfiep);
00425         }
00426 }
00427 
00431 static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep)
00432 {
00433         if (cfiep->bm_sg) {
00434                 dwc_free(cfiep->bm_sg);
00435                 cfiep->bm_sg = NULL;
00436         }
00437 
00438         if (cfiep->bm_align) {
00439                 dwc_free(cfiep->bm_align);
00440                 cfiep->bm_align = NULL;
00441         }
00442 
00443         if (cfiep->bm_concat) {
00444                 if (NULL != cfiep->bm_concat->wTxBytes) {
00445                         dwc_free(cfiep->bm_concat->wTxBytes);
00446                         cfiep->bm_concat->wTxBytes = NULL;
00447                 }
00448                 dwc_free(cfiep->bm_concat);
00449                 cfiep->bm_concat = NULL;
00450         }
00451 }
00452 
00458 static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep)
00459 {
00460         int retval = 0;
00461 
00462         cfiep->bm_sg = dwc_alloc(sizeof(ddma_sg_buffer_setup_t));
00463         if (NULL == cfiep->bm_sg) {
00464                 CFI_INFO("Failed to allocate memory for SG feature value\n");
00465                 return -DWC_E_NO_MEMORY;
00466         }
00467         dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
00468 
00469         /* For the Concatenation feature's default value we do not allocate
00470          * memory for the wTxBytes field - it will be done in the set_feature_value
00471          * request handler.
00472          */
00473         cfiep->bm_concat = dwc_alloc(sizeof(ddma_concat_buffer_setup_t));
00474         if (NULL == cfiep->bm_concat) {
00475                 CFI_INFO
00476                     ("Failed to allocate memory for CONCATENATION feature value\n");
00477                 dwc_free(cfiep->bm_sg);
00478                 return -DWC_E_NO_MEMORY;
00479         }
00480         dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
00481 
00482         cfiep->bm_align = dwc_alloc(sizeof(ddma_align_buffer_setup_t));
00483         if (NULL == cfiep->bm_align) {
00484                 CFI_INFO
00485                     ("Failed to allocate memory for Alignment feature value\n");
00486                 dwc_free(cfiep->bm_sg);
00487                 dwc_free(cfiep->bm_concat);
00488                 return -DWC_E_NO_MEMORY;
00489         }
00490         dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t));
00491 
00492         return retval;
00493 }
00494 
00506 static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
00507                          struct dwc_otg_pcd_ep *ep)
00508 {
00509         cfi_ep_t *cfiep;
00510         int retval = -DWC_E_NOT_SUPPORTED;
00511 
00512         CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__,
00513                  "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress);
00514         /* MAS - Check whether this endpoint already is in the list */
00515         cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
00516 
00517         if (NULL == cfiep) {
00518                 /* Allocate a cfi_ep_t object */
00519                 cfiep = dwc_alloc(sizeof(cfi_ep_t));
00520                 if (NULL == cfiep) {
00521                         CFI_INFO
00522                             ("Unable to allocate memory for <cfiep> in function %s\n",
00523                              __func__);
00524                         return -DWC_E_NO_MEMORY;
00525                 }
00526                 dwc_memset(cfiep, 0, sizeof(cfi_ep_t));
00527 
00528                 /* Save the dwc_otg_pcd_ep pointer in the cfiep object */
00529                 cfiep->ep = ep;
00530 
00531                 /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */
00532                 ep->dwc_ep.descs =
00533                     dwc_dma_alloc(MAX_DMA_DESCS_PER_EP *
00534                                   sizeof(dwc_otg_dma_desc_t),
00535                                   &ep->dwc_ep.descs_dma_addr);
00536 
00537                 if (NULL == ep->dwc_ep.descs) {
00538                         dwc_free(cfiep);
00539                         return -DWC_E_NO_MEMORY;
00540                 }
00541 
00542                 DWC_LIST_INIT(&cfiep->lh);
00543 
00544                 /* Set the buffer mode to BM_STANDARD. It will be modified 
00545                  * when building descriptors for a specific buffer mode */
00546                 ep->dwc_ep.buff_mode = BM_STANDARD;
00547 
00548                 /* Create and initialize the default values for this EP's Buffer modes */
00549                 if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0)
00550                         return retval;
00551 
00552                 /* Add the cfi_ep_t object to the CFI object's list of active endpoints */
00553                 DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh);
00554                 retval = 0;
00555         } else {                /* The sought EP already is in the list */
00556                 CFI_INFO("%s: The sought EP already is in the list\n",
00557                          __func__);
00558         }
00559 
00560         return retval;
00561 }
00562 
00568 static int cfi_ctrl_write_complete(struct cfiobject *cfi,
00569                                    struct dwc_otg_pcd *pcd)
00570 {
00571         uint32_t addr, reg_value;
00572         uint16_t wIndex, wValue;
00573         uint8_t bRequest;
00574         uint8_t *buf = cfi->buf_out.buf;
00575         //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved;
00576         struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req;
00577         int retval = -DWC_E_NOT_SUPPORTED;
00578 
00579         CFI_INFO("%s\n", __func__);
00580 
00581         bRequest = ctrl_req->bRequest;
00582         wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
00583         wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
00584 
00585         /* 
00586          * Save the pointer to the data stage in the ctrl_req's <data> field.
00587          * The request should be already saved in the command stage by now.
00588          */
00589         ctrl_req->data = cfi->buf_out.buf;
00590         cfi->need_status_in_complete = 0;
00591         cfi->need_gadget_att = 0;
00592 
00593         switch (bRequest) {
00594         case VEN_CORE_WRITE_REGISTER:
00595                 /* The buffer contains raw data of the new value for the register */
00596                 reg_value = *((uint32_t *) buf);
00597                 if (wValue == 0) {
00598                         addr = 0;
00599                         //addr = (uint32_t) pcd->otg_dev->base;
00600                         addr += wIndex;
00601                 } else {
00602                         addr = (wValue << 16) | wIndex;
00603                 }
00604 
00605                 //writel(reg_value, addr);
00606 
00607                 retval = 0;
00608                 cfi->need_status_in_complete = 1;
00609                 break;
00610 
00611         case VEN_CORE_SET_FEATURE:
00612                 /* The buffer contains raw data of the new value of the feature */
00613                 retval = cfi_set_feature_value(pcd);
00614                 if (retval < 0)
00615                         return retval;
00616 
00617                 cfi->need_status_in_complete = 1;
00618                 break;
00619 
00620         default:
00621                 break;
00622         }
00623 
00624         return retval;
00625 }
00626 
00630 static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00631                                dwc_otg_pcd_request_t * req)
00632 {
00633         struct dwc_otg_pcd_ep *ep = cfiep->ep;
00634         ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg;
00635         struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
00636         struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
00637         dma_addr_t buff_addr = req->dma;
00638         int i;
00639         uint32_t txsize, off;
00640 
00641         txsize = sgval->wSize;
00642         off = sgval->bOffset;
00643 
00644 //      CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n", 
00645 //              __func__, cfiep->ep->ep.name, txsize, off);
00646 
00647         for (i = 0; i < sgval->bCount; i++) {
00648                 desc->status.b.bs = BS_HOST_BUSY;
00649                 desc->buf = buff_addr;
00650                 desc->status.b.l = 0;
00651                 desc->status.b.ioc = 0;
00652                 desc->status.b.sp = 0;
00653                 desc->status.b.bytes = txsize;
00654                 desc->status.b.bs = BS_HOST_READY;
00655 
00656                 /* Set the next address of the buffer */
00657                 buff_addr += txsize + off;
00658                 desc_last = desc;
00659                 desc++;
00660         }
00661 
00662         /* Set the last, ioc and sp bits on the Last DMA Descriptor */
00663         desc_last->status.b.l = 1;
00664         desc_last->status.b.ioc = 1;
00665         desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
00666         /* Save the last DMA descriptor pointer */
00667         cfiep->dma_desc_last = desc_last;
00668         cfiep->desc_count = sgval->bCount;
00669 }
00670 
00674 static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00675                                    dwc_otg_pcd_request_t * req)
00676 {
00677         struct dwc_otg_pcd_ep *ep = cfiep->ep;
00678         ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat;
00679         struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
00680         struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
00681         dma_addr_t buff_addr = req->dma;
00682         int i;
00683         uint16_t *txsize;
00684 
00685         txsize = concatval->wTxBytes;
00686 
00687         for (i = 0; i < concatval->hdr.bDescCount; i++) {
00688                 desc->buf = buff_addr;
00689                 desc->status.b.bs = BS_HOST_BUSY;
00690                 desc->status.b.l = 0;
00691                 desc->status.b.ioc = 0;
00692                 desc->status.b.sp = 0;
00693                 desc->status.b.bytes = *txsize;
00694                 desc->status.b.bs = BS_HOST_READY;
00695 
00696                 txsize++;
00697                 /* Set the next address of the buffer */
00698                 buff_addr += UGETW(ep->desc->wMaxPacketSize);
00699                 desc_last = desc;
00700                 desc++;
00701         }
00702 
00703         /* Set the last, ioc and sp bits on the Last DMA Descriptor */
00704         desc_last->status.b.l = 1;
00705         desc_last->status.b.ioc = 1;
00706         desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
00707         cfiep->dma_desc_last = desc_last;
00708         cfiep->desc_count = concatval->hdr.bDescCount;
00709 }
00710 
00714 static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00715                                  dwc_otg_pcd_request_t * req)
00716 {
00717         /* @todo: MAS - add implementation when this feature needs to be tested */
00718 }
00719 
00723 static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
00724                                   dwc_otg_pcd_request_t * req)
00725 {
00726         struct dwc_otg_pcd_ep *ep = cfiep->ep;
00727         ddma_align_buffer_setup_t *alignval = cfiep->bm_align;
00728         struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
00729         dma_addr_t buff_addr = req->dma;
00730 
00731         desc->status.b.bs = BS_HOST_BUSY;
00732         desc->status.b.l = 1;
00733         desc->status.b.ioc = 1;
00734         desc->status.b.sp = ep->dwc_ep.sent_zlp;
00735         desc->status.b.bytes = req->length;
00736         /* Adjust the buffer alignment */
00737         desc->buf = (buff_addr + alignval->bAlign);
00738         desc->status.b.bs = BS_HOST_READY;
00739         cfiep->dma_desc_last = desc;
00740         cfiep->desc_count = 1;
00741 }
00742 
00747 static void cfi_build_descriptors(struct cfiobject *cfi,
00748                                   struct dwc_otg_pcd *pcd,
00749                                   struct dwc_otg_pcd_ep *ep,
00750                                   dwc_otg_pcd_request_t * req)
00751 {
00752         cfi_ep_t *cfiep;
00753 
00754         /* Get the cfiep by the dwc_otg_pcd_ep */
00755         cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
00756         if (NULL == cfiep) {
00757                 CFI_INFO("%s: Unable to find a matching active endpoint\n",
00758                          __func__);
00759                 return;
00760         }
00761 
00762         cfiep->xfer_len = req->length;
00763 
00764         /* Iterate through all the DMA descriptors */
00765         switch (cfiep->ep->dwc_ep.buff_mode) {
00766         case BM_SG:
00767                 cfi_build_sg_descs(cfi, cfiep, req);
00768                 break;
00769 
00770         case BM_CONCAT:
00771                 cfi_build_concat_descs(cfi, cfiep, req);
00772                 break;
00773 
00774         case BM_CIRCULAR:
00775                 cfi_build_circ_descs(cfi, cfiep, req);
00776                 break;
00777 
00778         case BM_ALIGN:
00779                 cfi_build_align_descs(cfi, cfiep, req);
00780                 break;
00781 
00782         default:
00783                 break;
00784         }
00785 }
00786 
00790 static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
00791                               struct dwc_otg_pcd_ep *ep, dma_addr_t * dma,
00792                               unsigned size, gfp_t flags)
00793 {
00794         return dwc_dma_alloc(size, dma);
00795 }
00796 
00800 int init_cfi(cfiobject_t * cfiobj)
00801 {
00802         CFI_INFO("%s\n", __func__);
00803 
00804         /* Allocate a buffer for IN XFERs */
00805         cfiobj->buf_in.buf =
00806             dwc_dma_alloc(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr);
00807         if (NULL == cfiobj->buf_in.buf) {
00808                 CFI_INFO("Unable to allocate buffer for INs\n");
00809                 return -DWC_E_NO_MEMORY;
00810         }
00811 
00812         /* Allocate a buffer for OUT XFERs */
00813         cfiobj->buf_out.buf =
00814             dwc_dma_alloc(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr);
00815         if (NULL == cfiobj->buf_out.buf) {
00816                 CFI_INFO("Unable to allocate buffer for OUT\n");
00817                 return -DWC_E_NO_MEMORY;
00818         }
00819 
00820         /* Initialize the callback function pointers */
00821         cfiobj->ops.release = cfi_release;
00822         cfiobj->ops.ep_enable = cfi_ep_enable;
00823         cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete;
00824         cfiobj->ops.build_descriptors = cfi_build_descriptors;
00825         cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf;
00826 
00827         /* Initialize the list of active endpoints in the CFI object */
00828         DWC_LIST_INIT(&cfiobj->active_eps);
00829 
00830         return 0;
00831 }
00832 
00838 static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
00839                                  struct dwc_otg_pcd *pcd,
00840                                  struct cfi_usb_ctrlrequest *ctrl_req)
00841 {
00842         int retval = -DWC_E_NOT_SUPPORTED;
00843         struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
00844         uint16_t dfifo, rxfifo, txfifo;
00845 
00846         switch (ctrl_req->wIndex) {
00847                 /* Whether the DDMA is enabled or not */
00848         case FT_ID_DMA_MODE:
00849                 *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0;
00850                 retval = 1;
00851                 break;
00852 
00853         case FT_ID_DMA_BUFFER_SETUP:
00854                 retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req);
00855                 break;
00856 
00857         case FT_ID_DMA_BUFF_ALIGN:
00858                 retval = cfi_ep_get_align_val(buf, pcd, ctrl_req);
00859                 break;
00860 
00861         case FT_ID_DMA_CONCAT_SETUP:
00862                 retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req);
00863                 break;
00864 
00865         case FT_ID_DMA_CIRCULAR:
00866                 CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n");
00867                 break;
00868 
00869         case FT_ID_THRESHOLD_SETUP:
00870                 CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n");
00871                 break;
00872 
00873         case FT_ID_DFIFO_DEPTH:
00874                 dfifo = get_dfifo_size(coreif);
00875                 *((uint16_t *) buf) = dfifo;
00876                 retval = sizeof(uint16_t);
00877                 break;
00878 
00879         case FT_ID_TX_FIFO_DEPTH:
00880                 retval = get_txfifo_size(pcd, ctrl_req->wValue);
00881                 if (retval >= 0) {
00882                         txfifo = retval;
00883                         *((uint16_t *) buf) = txfifo;
00884                         retval = sizeof(uint16_t);
00885                 }
00886                 break;
00887 
00888         case FT_ID_RX_FIFO_DEPTH:
00889                 retval = get_rxfifo_size(coreif, ctrl_req->wValue);
00890                 if (retval >= 0) {
00891                         rxfifo = retval;
00892                         *((uint16_t *) buf) = rxfifo;
00893                         retval = sizeof(uint16_t);
00894                 }
00895                 break;
00896         }
00897 
00898         return retval;
00899 }
00900 
00904 static int cfi_reset_sg_val(cfi_ep_t * cfiep)
00905 {
00906         dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
00907         return 0;
00908 }
00909 
00913 static int cfi_reset_align_val(cfi_ep_t * cfiep)
00914 {
00915         dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
00916         return 0;
00917 }
00918 
00924 static int cfi_reset_concat_val(cfi_ep_t * cfiep)
00925 {
00926         /* First we need to free the wTxBytes field */
00927         if (cfiep->bm_concat->wTxBytes) {
00928                 dwc_free(cfiep->bm_concat->wTxBytes);
00929                 cfiep->bm_concat->wTxBytes = NULL;
00930         }
00931 
00932         dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
00933         return 0;
00934 }
00935 
00939 static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep)
00940 {
00941         cfi_reset_sg_val(cfiep);
00942         cfi_reset_align_val(cfiep);
00943         cfi_reset_concat_val(cfiep);
00944         return 0;
00945 }
00946 
00947 static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr,
00948                                      uint8_t rx_rst, uint8_t tx_rst)
00949 {
00950         int retval = -DWC_E_INVALID;
00951         uint16_t tx_siz[15];
00952         uint16_t rx_siz = 0;
00953         dwc_otg_pcd_ep_t *ep = NULL;
00954         dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
00955         dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
00956 
00957         if (rx_rst) {
00958                 rx_siz = params->dev_rx_fifo_size;
00959                 params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz;
00960         }
00961 
00962         if (tx_rst) {
00963                 if (ep_addr == 0) {
00964                         int i;
00965 
00966                         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
00967                                 tx_siz[i] =
00968                                     core_if->core_params->dev_tx_fifo_size[i];
00969                                 core_if->core_params->dev_tx_fifo_size[i] =
00970                                     core_if->init_txfsiz[i];
00971                         }
00972                 } else {
00973 
00974                         ep = get_ep_by_addr(pcd, ep_addr);
00975 
00976                         if (NULL == ep) {
00977                                 CFI_INFO
00978                                     ("%s: Unable to get the endpoint addr=0x%02x\n",
00979                                      __func__, ep_addr);
00980                                 return -DWC_E_INVALID;
00981                         }
00982 
00983                         tx_siz[0] =
00984                             params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num -
00985                                                      1];
00986                         params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] =
00987                             GET_CORE_IF(pcd)->init_txfsiz[ep->dwc_ep.
00988                                                           tx_fifo_num - 1];
00989                 }
00990         }
00991 
00992         if (resize_fifos(GET_CORE_IF(pcd))) {
00993                 retval = 0;
00994         } else {
00995                 CFI_INFO
00996                     ("%s: Error resetting the feature Reset All(FIFO size)\n",
00997                      __func__);
00998                 if (rx_rst) {
00999                         params->dev_rx_fifo_size = rx_siz;
01000                 }
01001 
01002                 if (tx_rst) {
01003                         if (ep_addr == 0) {
01004                                 int i;
01005                                 for (i = 0; i < core_if->hwcfg4.b.num_in_eps;
01006                                      i++) {
01007                                         core_if->core_params->
01008                                             dev_tx_fifo_size[i] = tx_siz[i];
01009                                 }
01010                         } else {
01011                                 params->dev_tx_fifo_size[ep->dwc_ep.
01012                                                          tx_fifo_num - 1] =
01013                                     tx_siz[0];
01014                         }
01015                 }
01016                 retval = -DWC_E_INVALID;
01017         }
01018         return retval;
01019 }
01020 
01021 static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr)
01022 {
01023         int retval = 0;
01024         cfi_ep_t *cfiep;
01025         cfiobject_t *cfi = pcd->cfi;
01026         dwc_list_link_t *tmp;
01027 
01028         retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1);
01029         if (retval < 0) {
01030                 return retval;
01031         }
01032 
01033         /* If the EP address is known then reset the features for only that EP */
01034         if (addr) {
01035                 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01036                 if (NULL == cfiep) {
01037                         CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01038                                  __func__, addr);
01039                         return -DWC_E_INVALID;
01040                 }
01041                 retval = cfi_ep_reset_all_setup_vals(cfiep);
01042                 cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
01043         }
01044         /* Otherwise (wValue == 0), reset all features of all EP's */
01045         else {
01046                 /* Traverse all the active EP's and reset the feature(s) value(s) */
01047                 //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
01048                 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01049                         cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01050                         retval = cfi_ep_reset_all_setup_vals(cfiep);
01051                         cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
01052                         if (retval < 0) {
01053                                 CFI_INFO
01054                                     ("%s: Error resetting the feature Reset All\n",
01055                                      __func__);
01056                                 return retval;
01057                         }
01058                 }
01059         }
01060         return retval;
01061 }
01062 
01063 static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd,
01064                                            uint8_t addr)
01065 {
01066         int retval = 0;
01067         cfi_ep_t *cfiep;
01068         cfiobject_t *cfi = pcd->cfi;
01069         dwc_list_link_t *tmp;
01070 
01071         /* If the EP address is known then reset the features for only that EP */
01072         if (addr) {
01073                 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01074                 if (NULL == cfiep) {
01075                         CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01076                                  __func__, addr);
01077                         return -DWC_E_INVALID;
01078                 }
01079                 retval = cfi_reset_sg_val(cfiep);
01080         }
01081         /* Otherwise (wValue == 0), reset all features of all EP's */
01082         else {
01083                 /* Traverse all the active EP's and reset the feature(s) value(s) */
01084                 //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
01085                 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01086                         cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01087                         retval = cfi_reset_sg_val(cfiep);
01088                         if (retval < 0) {
01089                                 CFI_INFO
01090                                     ("%s: Error resetting the feature Buffer Setup\n",
01091                                      __func__);
01092                                 return retval;
01093                         }
01094                 }
01095         }
01096         return retval;
01097 }
01098 
01099 static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr)
01100 {
01101         int retval = 0;
01102         cfi_ep_t *cfiep;
01103         cfiobject_t *cfi = pcd->cfi;
01104         dwc_list_link_t *tmp;
01105 
01106         /* If the EP address is known then reset the features for only that EP */
01107         if (addr) {
01108                 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01109                 if (NULL == cfiep) {
01110                         CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01111                                  __func__, addr);
01112                         return -DWC_E_INVALID;
01113                 }
01114                 retval = cfi_reset_concat_val(cfiep);
01115         }
01116         /* Otherwise (wValue == 0), reset all features of all EP's */
01117         else {
01118                 /* Traverse all the active EP's and reset the feature(s) value(s) */
01119                 //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
01120                 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01121                         cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01122                         retval = cfi_reset_concat_val(cfiep);
01123                         if (retval < 0) {
01124                                 CFI_INFO
01125                                     ("%s: Error resetting the feature Concatenation Value\n",
01126                                      __func__);
01127                                 return retval;
01128                         }
01129                 }
01130         }
01131         return retval;
01132 }
01133 
01134 static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr)
01135 {
01136         int retval = 0;
01137         cfi_ep_t *cfiep;
01138         cfiobject_t *cfi = pcd->cfi;
01139         dwc_list_link_t *tmp;
01140 
01141         /* If the EP address is known then reset the features for only that EP */
01142         if (addr) {
01143                 cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
01144                 if (NULL == cfiep) {
01145                         CFI_INFO("%s: Error getting the EP address 0x%02x\n",
01146                                  __func__, addr);
01147                         return -DWC_E_INVALID;
01148                 }
01149                 retval = cfi_reset_align_val(cfiep);
01150         }
01151         /* Otherwise (wValue == 0), reset all features of all EP's */
01152         else {
01153                 /* Traverse all the active EP's and reset the feature(s) value(s) */
01154                 //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
01155                 DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
01156                         cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
01157                         retval = cfi_reset_align_val(cfiep);
01158                         if (retval < 0) {
01159                                 CFI_INFO
01160                                     ("%s: Error resetting the feature Aliignment Value\n",
01161                                      __func__);
01162                                 return retval;
01163                         }
01164                 }
01165         }
01166         return retval;
01167 
01168 }
01169 
01170 static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
01171                              struct cfi_usb_ctrlrequest *req)
01172 {
01173         int retval = 0;
01174 
01175         switch (req->wIndex) {
01176         case 0:
01177                 /* Reset all features */
01178                 retval = cfi_handle_reset_all(pcd, req->wValue & 0xff);
01179                 break;
01180 
01181         case FT_ID_DMA_BUFFER_SETUP:
01182                 /* Reset the SG buffer setup */
01183                 retval =
01184                     cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff);
01185                 break;
01186 
01187         case FT_ID_DMA_CONCAT_SETUP:
01188                 /* Reset the Concatenation buffer setup */
01189                 retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff);
01190                 break;
01191 
01192         case FT_ID_DMA_BUFF_ALIGN:
01193                 /* Reset the Alignment buffer setup */
01194                 retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff);
01195                 break;
01196 
01197         case FT_ID_TX_FIFO_DEPTH:
01198                 retval =
01199                     cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1);
01200                 pcd->cfi->need_gadget_att = 0;
01201                 break;
01202 
01203         case FT_ID_RX_FIFO_DEPTH:
01204                 retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0);
01205                 pcd->cfi->need_gadget_att = 0;
01206                 break;
01207         default:
01208                 break;
01209         }
01210         return retval;
01211 }
01212 
01216 static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
01217 {
01218         uint8_t inaddr, outaddr;
01219         cfi_ep_t *epin, *epout;
01220         ddma_sg_buffer_setup_t *psgval;
01221         uint32_t desccount, size;
01222 
01223         CFI_INFO("%s\n", __func__);
01224 
01225         psgval = (ddma_sg_buffer_setup_t *) buf;
01226         desccount = (uint32_t) psgval->bCount;
01227         size = (uint32_t) psgval->wSize;
01228 
01229         /* Check the DMA descriptor count */
01230         if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) {
01231                 CFI_INFO
01232                     ("%s: The count of DMA Descriptors should be between 1 and %d\n",
01233                      __func__, MAX_DMA_DESCS_PER_EP);
01234                 return -DWC_E_INVALID;
01235         }
01236 
01237         /* Check the DMA descriptor count */
01238 
01239         if (size == 0) {
01240 
01241                 CFI_INFO("%s: The transfer size should be at least 1 byte\n",
01242                          __func__);
01243 
01244                 return -DWC_E_INVALID;
01245 
01246         }
01247 
01248         inaddr = psgval->bInEndpointAddress;
01249         outaddr = psgval->bOutEndpointAddress;
01250 
01251         epin = get_cfi_ep_by_addr(pcd->cfi, inaddr);
01252         epout = get_cfi_ep_by_addr(pcd->cfi, outaddr);
01253 
01254         if (NULL == epin || NULL == epout) {
01255                 CFI_INFO
01256                     ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n",
01257                      __func__, inaddr, outaddr);
01258                 return -DWC_E_INVALID;
01259         }
01260 
01261         epin->ep->dwc_ep.buff_mode = BM_SG;
01262         dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
01263 
01264         epout->ep->dwc_ep.buff_mode = BM_SG;
01265         dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
01266 
01267         return 0;
01268 }
01269 
01273 static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
01274 {
01275         cfi_ep_t *ep;
01276         uint8_t addr;
01277         ddma_align_buffer_setup_t *palignval;
01278 
01279         palignval = (ddma_align_buffer_setup_t *) buf;
01280         addr = palignval->bEndpointAddress;
01281 
01282         ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01283 
01284         if (NULL == ep) {
01285                 CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
01286                          __func__, addr);
01287                 return -DWC_E_INVALID;
01288         }
01289 
01290         ep->ep->dwc_ep.buff_mode = BM_ALIGN;
01291         dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t));
01292 
01293         return 0;
01294 }
01295 
01299 static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
01300 {
01301         uint8_t addr;
01302         cfi_ep_t *ep;
01303         struct _ddma_concat_buffer_setup_hdr *pConcatValHdr;
01304         uint16_t *pVals;
01305         uint32_t desccount;
01306         int i;
01307         uint16_t mps;
01308 
01309         pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf;
01310         desccount = (uint32_t) pConcatValHdr->bDescCount;
01311         pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN);
01312 
01313         /* Check the DMA descriptor count */
01314         if (desccount > MAX_DMA_DESCS_PER_EP) {
01315                 CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n",
01316                          __func__, MAX_DMA_DESCS_PER_EP);
01317                 return -DWC_E_INVALID;
01318         }
01319 
01320         addr = pConcatValHdr->bEndpointAddress;
01321         ep = get_cfi_ep_by_addr(pcd->cfi, addr);
01322         if (NULL == ep) {
01323                 CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
01324                          __func__, addr);
01325                 return -DWC_E_INVALID;
01326         }
01327 
01328         mps = UGETW(ep->ep->desc->wMaxPacketSize);
01329 
01330 #if 0
01331         for (i = 0; i < desccount; i++) {
01332                 CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]);
01333         }
01334         CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps);
01335 #endif
01336 
01337         /* Check the wTxSizes to be less than or equal to the mps */
01338         for (i = 0; i < desccount; i++) {
01339                 if (pVals[i] > mps) {
01340                         CFI_INFO
01341                             ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n",
01342                              __func__, i, pVals[i]);
01343                         return -DWC_E_INVALID;
01344                 }
01345         }
01346 
01347         ep->ep->dwc_ep.buff_mode = BM_CONCAT;
01348         dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN);
01349 
01350         /* Free the previously allocated storage for the wTxBytes */
01351         if (ep->bm_concat->wTxBytes) {
01352                 dwc_free(ep->bm_concat->wTxBytes);
01353         }
01354 
01355         /* Allocate a new storage for the wTxBytes field */
01356         ep->bm_concat->wTxBytes =
01357             dwc_alloc(sizeof(uint16_t) * pConcatValHdr->bDescCount);
01358         if (NULL == ep->bm_concat->wTxBytes) {
01359                 CFI_INFO("%s: Unable to allocate memory\n", __func__);
01360                 return -DWC_E_NO_MEMORY;
01361         }
01362 
01363         /* Copy the new values into the wTxBytes filed */
01364         dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN,
01365                    sizeof(uint16_t) * pConcatValHdr->bDescCount);
01366 
01367         return 0;
01368 }
01369 
01378 static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if)
01379 {
01380         dwc_otg_core_params_t *params = core_if->core_params;
01381         uint16_t dfifo_total = 0;
01382         int i;
01383 
01384         /* The shared RxFIFO size */
01385         dfifo_total =
01386             params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
01387 
01388         /* Add up each TxFIFO size to the total */
01389         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01390                 dfifo_total += params->dev_tx_fifo_size[i];
01391         }
01392 
01393         return dfifo_total;
01394 }
01395 
01404 static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue)
01405 {
01406         switch (wValue >> 8) {
01407         case 0:
01408                 return (core_if->pwron_rxfsiz <
01409                         32768) ? core_if->pwron_rxfsiz : 32768;
01410                 break;
01411         case 1:
01412                 return core_if->core_params->dev_rx_fifo_size;
01413                 break;
01414         default:
01415                 return -DWC_E_INVALID;
01416                 break;
01417         }
01418 }
01419 
01428 static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue)
01429 {
01430         dwc_otg_pcd_ep_t *ep;
01431 
01432         ep = get_ep_by_addr(pcd, wValue & 0xff);
01433 
01434         if (NULL == ep) {
01435                 CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
01436                          __func__, wValue & 0xff);
01437                 return -DWC_E_INVALID;
01438         }
01439 
01440         if (!ep->dwc_ep.is_in) {
01441                 CFI_INFO
01442                     ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n",
01443                      __func__, wValue & 0xff);
01444                 return -DWC_E_INVALID;
01445         }
01446 
01447         switch (wValue >> 8) {
01448         case 0:
01449                 return (GET_CORE_IF(pcd)->
01450                         pwron_txfsiz[ep->dwc_ep.tx_fifo_num - 1] <
01451                         768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->dwc_ep.
01452                                                               tx_fifo_num -
01453                                                               1] : 32768;
01454                 break;
01455         case 1:
01456                 return GET_CORE_IF(pcd)->core_params->dev_tx_fifo_size[ep->
01457                                                                        dwc_ep.
01458                                                                        num - 1];
01459                 break;
01460         default:
01461                 return -DWC_E_INVALID;
01462                 break;
01463         }
01464 }
01465 
01475 static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if)
01476 {
01477         uint16_t dfifo_actual = 0;
01478         dwc_otg_core_params_t *params = core_if->core_params;
01479         uint16_t start_addr = 0;
01480         int i;
01481 
01482         dfifo_actual =
01483             params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
01484 
01485         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01486                 dfifo_actual += params->dev_tx_fifo_size[i];
01487         }
01488 
01489         if (dfifo_actual > core_if->total_fifo_size) {
01490                 return 0;
01491         }
01492 
01493         if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16)
01494                 return 0;
01495 
01496         if (params->dev_nperio_tx_fifo_size > 32768
01497             || params->dev_nperio_tx_fifo_size < 16)
01498                 return 0;
01499 
01500         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01501 
01502                 if (params->dev_tx_fifo_size[i] > 768
01503                     || params->dev_tx_fifo_size[i] < 4)
01504                         return 0;
01505         }
01506 
01507         if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz)
01508                 return 0;
01509         start_addr = params->dev_rx_fifo_size;
01510 
01511         if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz)
01512                 return 0;
01513         start_addr += params->dev_nperio_tx_fifo_size;
01514 
01515         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01516 
01517                 if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i])
01518                         return 0;
01519                 start_addr += params->dev_tx_fifo_size[i];
01520         }
01521 
01522         return 1;
01523 }
01524 
01533 static uint8_t resize_fifos(dwc_otg_core_if_t * core_if)
01534 {
01535         int i = 0;
01536         dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
01537         dwc_otg_core_params_t *params = core_if->core_params;
01538         uint32_t rx_fifo_size;
01539         fifosize_data_t nptxfifosize;
01540         fifosize_data_t txfifosize[15];
01541 
01542         uint32_t rx_fsz_bak;
01543         uint32_t nptxfsz_bak;
01544         uint32_t txfsz_bak[15];
01545 
01546         uint16_t start_address;
01547         uint8_t retval = 1;
01548 
01549         if (!check_fifo_sizes(core_if)) {
01550                 return 0;
01551         }
01552 
01553         /* Configure data FIFO sizes */
01554         if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
01555                 rx_fsz_bak = dwc_read_reg32(&global_regs->grxfsiz);
01556                 rx_fifo_size = params->dev_rx_fifo_size;
01557                 dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size);
01558 
01559                 /*
01560                  * Tx FIFOs These FIFOs are numbered from 1 to 15.
01561                  * Indexes of the FIFO size module parameters in the
01562                  * dev_tx_fifo_size array and the FIFO size registers in
01563                  * the dptxfsiz_dieptxf array run from 0 to 14.
01564                  */
01565 
01566                 /* Non-periodic Tx FIFO */
01567                 nptxfsz_bak = dwc_read_reg32(&global_regs->gnptxfsiz);
01568                 nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
01569                 start_address = params->dev_rx_fifo_size;
01570                 nptxfifosize.b.startaddr = start_address;
01571 
01572                 dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32);
01573 
01574                 start_address += nptxfifosize.b.depth;
01575 
01576                 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01577                         txfsz_bak[i] =
01578                             dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]);
01579 
01580                         txfifosize[i].b.depth = params->dev_tx_fifo_size[i];
01581                         txfifosize[i].b.startaddr = start_address;
01582                         dwc_write_reg32(&global_regs->dptxfsiz_dieptxf[i],
01583                                         txfifosize[i].d32);
01584 
01585                         start_address += txfifosize[i].b.depth;
01586                 }
01587 
01589                 if (rx_fifo_size != dwc_read_reg32(&global_regs->grxfsiz)) {
01590                         retval = 0;
01591                 }
01592 
01593                 if (nptxfifosize.d32 != dwc_read_reg32(&global_regs->gnptxfsiz)) {
01594                         retval = 0;
01595                 }
01596 
01597                 for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01598                         if (txfifosize[i].d32 !=
01599                             dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i])) {
01600                                 retval = 0;
01601                         }
01602                 }
01603 
01605                 if (retval == 0) {
01606                         dwc_write_reg32(&global_regs->grxfsiz, rx_fsz_bak);
01607 
01608                         /* Non-periodic Tx FIFO */
01609                         dwc_write_reg32(&global_regs->gnptxfsiz, nptxfsz_bak);
01610 
01611                         for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
01612                                 dwc_write_reg32(&global_regs->
01613                                                 dptxfsiz_dieptxf[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 Tue May 5 02:22:48 2009 for DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver by  doxygen 1.4.7