uboot/drivers/usb/musb/musb_hcd.c
<<
>>
Prefs
   1/*
   2 * Mentor USB OTG Core host controller driver.
   3 *
   4 * Copyright (c) 2008 Texas Instruments
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation; either version 2 of
   9 * the License, or (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  19 * MA 02111-1307 USA
  20 *
  21 * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
  22 */
  23
  24#include <common.h>
  25#include <usb.h>
  26#include "musb_hcd.h"
  27
  28/* MSC control transfers */
  29#define USB_MSC_BBB_RESET       0xFF
  30#define USB_MSC_BBB_GET_MAX_LUN 0xFE
  31
  32/* Endpoint configuration information */
  33static const struct musb_epinfo epinfo[3] = {
  34        {MUSB_BULK_EP, 1, 512}, /* EP1 - Bluk Out - 512 Bytes */
  35        {MUSB_BULK_EP, 0, 512}, /* EP1 - Bluk In  - 512 Bytes */
  36        {MUSB_INTR_EP, 0, 64}   /* EP2 - Interrupt IN - 64 Bytes */
  37};
  38
  39/* --- Virtual Root Hub ---------------------------------------------------- */
  40#ifdef MUSB_NO_MULTIPOINT
  41static int rh_devnum;
  42static u32 port_status;
  43
  44/* Device descriptor */
  45static const u8 root_hub_dev_des[] = {
  46        0x12,                   /*  __u8  bLength; */
  47        0x01,                   /*  __u8  bDescriptorType; Device */
  48        0x00,                   /*  __u16 bcdUSB; v1.1 */
  49        0x02,
  50        0x09,                   /*  __u8  bDeviceClass; HUB_CLASSCODE */
  51        0x00,                   /*  __u8  bDeviceSubClass; */
  52        0x00,                   /*  __u8  bDeviceProtocol; */
  53        0x08,                   /*  __u8  bMaxPacketSize0; 8 Bytes */
  54        0x00,                   /*  __u16 idVendor; */
  55        0x00,
  56        0x00,                   /*  __u16 idProduct; */
  57        0x00,
  58        0x00,                   /*  __u16 bcdDevice; */
  59        0x00,
  60        0x00,                   /*  __u8  iManufacturer; */
  61        0x01,                   /*  __u8  iProduct; */
  62        0x00,                   /*  __u8  iSerialNumber; */
  63        0x01                    /*  __u8  bNumConfigurations; */
  64};
  65
  66/* Configuration descriptor */
  67static const u8 root_hub_config_des[] = {
  68        0x09,                   /*  __u8  bLength; */
  69        0x02,                   /*  __u8  bDescriptorType; Configuration */
  70        0x19,                   /*  __u16 wTotalLength; */
  71        0x00,
  72        0x01,                   /*  __u8  bNumInterfaces; */
  73        0x01,                   /*  __u8  bConfigurationValue; */
  74        0x00,                   /*  __u8  iConfiguration; */
  75        0x40,                   /*  __u8  bmAttributes;
  76                                   Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
  77        0x00,                   /*  __u8  MaxPower; */
  78
  79        /* interface */
  80        0x09,                   /*  __u8  if_bLength; */
  81        0x04,                   /*  __u8  if_bDescriptorType; Interface */
  82        0x00,                   /*  __u8  if_bInterfaceNumber; */
  83        0x00,                   /*  __u8  if_bAlternateSetting; */
  84        0x01,                   /*  __u8  if_bNumEndpoints; */
  85        0x09,                   /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
  86        0x00,                   /*  __u8  if_bInterfaceSubClass; */
  87        0x00,                   /*  __u8  if_bInterfaceProtocol; */
  88        0x00,                   /*  __u8  if_iInterface; */
  89
  90        /* endpoint */
  91        0x07,                   /*  __u8  ep_bLength; */
  92        0x05,                   /*  __u8  ep_bDescriptorType; Endpoint */
  93        0x81,                   /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
  94        0x03,                   /*  __u8  ep_bmAttributes; Interrupt */
  95        0x00,                   /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
  96        0x02,
  97        0xff                    /*  __u8  ep_bInterval; 255 ms */
  98};
  99
 100static const unsigned char root_hub_str_index0[] = {
 101        0x04,                   /*  __u8  bLength; */
 102        0x03,                   /*  __u8  bDescriptorType; String-descriptor */
 103        0x09,                   /*  __u8  lang ID */
 104        0x04,                   /*  __u8  lang ID */
 105};
 106
 107static const unsigned char root_hub_str_index1[] = {
 108        0x1c,                   /*  __u8  bLength; */
 109        0x03,                   /*  __u8  bDescriptorType; String-descriptor */
 110        'M',                    /*  __u8  Unicode */
 111        0,                      /*  __u8  Unicode */
 112        'U',                    /*  __u8  Unicode */
 113        0,                      /*  __u8  Unicode */
 114        'S',                    /*  __u8  Unicode */
 115        0,                      /*  __u8  Unicode */
 116        'B',                    /*  __u8  Unicode */
 117        0,                      /*  __u8  Unicode */
 118        ' ',                    /*  __u8  Unicode */
 119        0,                      /*  __u8  Unicode */
 120        'R',                    /*  __u8  Unicode */
 121        0,                      /*  __u8  Unicode */
 122        'o',                    /*  __u8  Unicode */
 123        0,                      /*  __u8  Unicode */
 124        'o',                    /*  __u8  Unicode */
 125        0,                      /*  __u8  Unicode */
 126        't',                    /*  __u8  Unicode */
 127        0,                      /*  __u8  Unicode */
 128        ' ',                    /*  __u8  Unicode */
 129        0,                      /*  __u8  Unicode */
 130        'H',                    /*  __u8  Unicode */
 131        0,                      /*  __u8  Unicode */
 132        'u',                    /*  __u8  Unicode */
 133        0,                      /*  __u8  Unicode */
 134        'b',                    /*  __u8  Unicode */
 135        0,                      /*  __u8  Unicode */
 136};
 137#endif
 138
 139/*
 140 * This function writes the data toggle value.
 141 */
 142static void write_toggle(struct usb_device *dev, u8 ep, u8 dir_out)
 143{
 144        u16 toggle = usb_gettoggle(dev, ep, dir_out);
 145        u16 csr;
 146
 147        if (dir_out) {
 148                csr = readw(&musbr->txcsr);
 149                if (!toggle) {
 150                        if (csr & MUSB_TXCSR_MODE)
 151                                csr = MUSB_TXCSR_CLRDATATOG;
 152                        else
 153                                csr = 0;
 154                        writew(csr, &musbr->txcsr);
 155                } else {
 156                        csr |= MUSB_TXCSR_H_WR_DATATOGGLE;
 157                        writew(csr, &musbr->txcsr);
 158                        csr |= (toggle << MUSB_TXCSR_H_DATATOGGLE_SHIFT);
 159                        writew(csr, &musbr->txcsr);
 160                }
 161        } else {
 162                if (!toggle) {
 163                        csr = readw(&musbr->txcsr);
 164                        if (csr & MUSB_TXCSR_MODE)
 165                                csr = MUSB_RXCSR_CLRDATATOG;
 166                        else
 167                                csr = 0;
 168                        writew(csr, &musbr->rxcsr);
 169                } else {
 170                        csr = readw(&musbr->rxcsr);
 171                        csr |= MUSB_RXCSR_H_WR_DATATOGGLE;
 172                        writew(csr, &musbr->rxcsr);
 173                        csr |= (toggle << MUSB_S_RXCSR_H_DATATOGGLE);
 174                        writew(csr, &musbr->rxcsr);
 175                }
 176        }
 177}
 178
 179/*
 180 * This function checks if RxStall has occured on the endpoint. If a RxStall
 181 * has occured, the RxStall is cleared and 1 is returned. If RxStall has
 182 * not occured, 0 is returned.
 183 */
 184static u8 check_stall(u8 ep, u8 dir_out)
 185{
 186        u16 csr;
 187
 188        /* For endpoint 0 */
 189        if (!ep) {
 190                csr = readw(&musbr->txcsr);
 191                if (csr & MUSB_CSR0_H_RXSTALL) {
 192                        csr &= ~MUSB_CSR0_H_RXSTALL;
 193                        writew(csr, &musbr->txcsr);
 194                        return 1;
 195                }
 196        } else { /* For non-ep0 */
 197                if (dir_out) { /* is it tx ep */
 198                        csr = readw(&musbr->txcsr);
 199                        if (csr & MUSB_TXCSR_H_RXSTALL) {
 200                                csr &= ~MUSB_TXCSR_H_RXSTALL;
 201                                writew(csr, &musbr->txcsr);
 202                                return 1;
 203                        }
 204                } else { /* is it rx ep */
 205                        csr = readw(&musbr->rxcsr);
 206                        if (csr & MUSB_RXCSR_H_RXSTALL) {
 207                                csr &= ~MUSB_RXCSR_H_RXSTALL;
 208                                writew(csr, &musbr->rxcsr);
 209                                return 1;
 210                        }
 211                }
 212        }
 213        return 0;
 214}
 215
 216/*
 217 * waits until ep0 is ready. Returns 0 if ep is ready, -1 for timeout
 218 * error and -2 for stall.
 219 */
 220static int wait_until_ep0_ready(struct usb_device *dev, u32 bit_mask)
 221{
 222        u16 csr;
 223        int result = 1;
 224        int timeout = CONFIG_MUSB_TIMEOUT;
 225
 226        while (result > 0) {
 227                csr = readw(&musbr->txcsr);
 228                if (csr & MUSB_CSR0_H_ERROR) {
 229                        csr &= ~MUSB_CSR0_H_ERROR;
 230                        writew(csr, &musbr->txcsr);
 231                        dev->status = USB_ST_CRC_ERR;
 232                        result = -1;
 233                        break;
 234                }
 235
 236                switch (bit_mask) {
 237                case MUSB_CSR0_TXPKTRDY:
 238                        if (!(csr & MUSB_CSR0_TXPKTRDY)) {
 239                                if (check_stall(MUSB_CONTROL_EP, 0)) {
 240                                        dev->status = USB_ST_STALLED;
 241                                        result = -2;
 242                                } else
 243                                        result = 0;
 244                        }
 245                        break;
 246
 247                case MUSB_CSR0_RXPKTRDY:
 248                        if (check_stall(MUSB_CONTROL_EP, 0)) {
 249                                dev->status = USB_ST_STALLED;
 250                                result = -2;
 251                        } else
 252                                if (csr & MUSB_CSR0_RXPKTRDY)
 253                                        result = 0;
 254                        break;
 255
 256                case MUSB_CSR0_H_REQPKT:
 257                        if (!(csr & MUSB_CSR0_H_REQPKT)) {
 258                                if (check_stall(MUSB_CONTROL_EP, 0)) {
 259                                        dev->status = USB_ST_STALLED;
 260                                        result = -2;
 261                                } else
 262                                        result = 0;
 263                        }
 264                        break;
 265                }
 266
 267                /* Check the timeout */
 268                if (--timeout)
 269                        udelay(1);
 270                else {
 271                        dev->status = USB_ST_CRC_ERR;
 272                        result = -1;
 273                        break;
 274                }
 275        }
 276
 277        return result;
 278}
 279
 280/*
 281 * waits until tx ep is ready. Returns 1 when ep is ready and 0 on error.
 282 */
 283static u8 wait_until_txep_ready(struct usb_device *dev, u8 ep)
 284{
 285        u16 csr;
 286        int timeout = CONFIG_MUSB_TIMEOUT;
 287
 288        do {
 289                if (check_stall(ep, 1)) {
 290                        dev->status = USB_ST_STALLED;
 291                        return 0;
 292                }
 293
 294                csr = readw(&musbr->txcsr);
 295                if (csr & MUSB_TXCSR_H_ERROR) {
 296                        dev->status = USB_ST_CRC_ERR;
 297                        return 0;
 298                }
 299
 300                /* Check the timeout */
 301                if (--timeout)
 302                        udelay(1);
 303                else {
 304                        dev->status = USB_ST_CRC_ERR;
 305                        return -1;
 306                }
 307
 308        } while (csr & MUSB_TXCSR_TXPKTRDY);
 309        return 1;
 310}
 311
 312/*
 313 * waits until rx ep is ready. Returns 1 when ep is ready and 0 on error.
 314 */
 315static u8 wait_until_rxep_ready(struct usb_device *dev, u8 ep)
 316{
 317        u16 csr;
 318        int timeout = CONFIG_MUSB_TIMEOUT;
 319
 320        do {
 321                if (check_stall(ep, 0)) {
 322                        dev->status = USB_ST_STALLED;
 323                        return 0;
 324                }
 325
 326                csr = readw(&musbr->rxcsr);
 327                if (csr & MUSB_RXCSR_H_ERROR) {
 328                        dev->status = USB_ST_CRC_ERR;
 329                        return 0;
 330                }
 331
 332                /* Check the timeout */
 333                if (--timeout)
 334                        udelay(1);
 335                else {
 336                        dev->status = USB_ST_CRC_ERR;
 337                        return -1;
 338                }
 339
 340        } while (!(csr & MUSB_RXCSR_RXPKTRDY));
 341        return 1;
 342}
 343
 344/*
 345 * This function performs the setup phase of the control transfer
 346 */
 347static int ctrlreq_setup_phase(struct usb_device *dev, struct devrequest *setup)
 348{
 349        int result;
 350        u16 csr;
 351
 352        /* write the control request to ep0 fifo */
 353        write_fifo(MUSB_CONTROL_EP, sizeof(struct devrequest), (void *)setup);
 354
 355        /* enable transfer of setup packet */
 356        csr = readw(&musbr->txcsr);
 357        csr |= (MUSB_CSR0_TXPKTRDY|MUSB_CSR0_H_SETUPPKT);
 358        writew(csr, &musbr->txcsr);
 359
 360        /* wait until the setup packet is transmitted */
 361        result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
 362        dev->act_len = 0;
 363        return result;
 364}
 365
 366/*
 367 * This function handles the control transfer in data phase
 368 */
 369static int ctrlreq_in_data_phase(struct usb_device *dev, u32 len, void *buffer)
 370{
 371        u16 csr;
 372        u32 rxlen = 0;
 373        u32 nextlen = 0;
 374        u8  maxpktsize = (1 << dev->maxpacketsize) * 8;
 375        u8  *rxbuff = (u8 *)buffer;
 376        u8  rxedlength;
 377        int result;
 378
 379        while (rxlen < len) {
 380                /* Determine the next read length */
 381                nextlen = ((len-rxlen) > maxpktsize) ? maxpktsize : (len-rxlen);
 382
 383                /* Set the ReqPkt bit */
 384                csr = readw(&musbr->txcsr);
 385                writew(csr | MUSB_CSR0_H_REQPKT, &musbr->txcsr);
 386                result = wait_until_ep0_ready(dev, MUSB_CSR0_RXPKTRDY);
 387                if (result < 0)
 388                        return result;
 389
 390                /* Actual number of bytes received by usb */
 391                rxedlength = readb(&musbr->rxcount);
 392
 393                /* Read the data from the RxFIFO */
 394                read_fifo(MUSB_CONTROL_EP, rxedlength, &rxbuff[rxlen]);
 395
 396                /* Clear the RxPktRdy Bit */
 397                csr = readw(&musbr->txcsr);
 398                csr &= ~MUSB_CSR0_RXPKTRDY;
 399                writew(csr, &musbr->txcsr);
 400
 401                /* short packet? */
 402                if (rxedlength != nextlen) {
 403                        dev->act_len += rxedlength;
 404                        break;
 405                }
 406                rxlen += nextlen;
 407                dev->act_len = rxlen;
 408        }
 409        return 0;
 410}
 411
 412/*
 413 * This function handles the control transfer out data phase
 414 */
 415static int ctrlreq_out_data_phase(struct usb_device *dev, u32 len, void *buffer)
 416{
 417        u16 csr;
 418        u32 txlen = 0;
 419        u32 nextlen = 0;
 420        u8  maxpktsize = (1 << dev->maxpacketsize) * 8;
 421        u8  *txbuff = (u8 *)buffer;
 422        int result = 0;
 423
 424        while (txlen < len) {
 425                /* Determine the next write length */
 426                nextlen = ((len-txlen) > maxpktsize) ? maxpktsize : (len-txlen);
 427
 428                /* Load the data to send in FIFO */
 429                write_fifo(MUSB_CONTROL_EP, txlen, &txbuff[txlen]);
 430
 431                /* Set TXPKTRDY bit */
 432                csr = readw(&musbr->txcsr);
 433                writew(csr | MUSB_CSR0_H_DIS_PING | MUSB_CSR0_TXPKTRDY,
 434                                        &musbr->txcsr);
 435                result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
 436                if (result < 0)
 437                        break;
 438
 439                txlen += nextlen;
 440                dev->act_len = txlen;
 441        }
 442        return result;
 443}
 444
 445/*
 446 * This function handles the control transfer out status phase
 447 */
 448static int ctrlreq_out_status_phase(struct usb_device *dev)
 449{
 450        u16 csr;
 451        int result;
 452
 453        /* Set the StatusPkt bit */
 454        csr = readw(&musbr->txcsr);
 455        csr |= (MUSB_CSR0_H_DIS_PING | MUSB_CSR0_TXPKTRDY |
 456                        MUSB_CSR0_H_STATUSPKT);
 457        writew(csr, &musbr->txcsr);
 458
 459        /* Wait until TXPKTRDY bit is cleared */
 460        result = wait_until_ep0_ready(dev, MUSB_CSR0_TXPKTRDY);
 461        return result;
 462}
 463
 464/*
 465 * This function handles the control transfer in status phase
 466 */
 467static int ctrlreq_in_status_phase(struct usb_device *dev)
 468{
 469        u16 csr;
 470        int result;
 471
 472        /* Set the StatusPkt bit and ReqPkt bit */
 473        csr = MUSB_CSR0_H_DIS_PING | MUSB_CSR0_H_REQPKT | MUSB_CSR0_H_STATUSPKT;
 474        writew(csr, &musbr->txcsr);
 475        result = wait_until_ep0_ready(dev, MUSB_CSR0_H_REQPKT);
 476
 477        /* clear StatusPkt bit and RxPktRdy bit */
 478        csr = readw(&musbr->txcsr);
 479        csr &= ~(MUSB_CSR0_RXPKTRDY | MUSB_CSR0_H_STATUSPKT);
 480        writew(csr, &musbr->txcsr);
 481        return result;
 482}
 483
 484/*
 485 * determines the speed of the device (High/Full/Slow)
 486 */
 487static u8 get_dev_speed(struct usb_device *dev)
 488{
 489        return (dev->speed == USB_SPEED_HIGH) ? MUSB_TYPE_SPEED_HIGH :
 490                ((dev->speed == USB_SPEED_LOW) ? MUSB_TYPE_SPEED_LOW :
 491                                                MUSB_TYPE_SPEED_FULL);
 492}
 493
 494/*
 495 * configure the hub address and the port address.
 496 */
 497static void config_hub_port(struct usb_device *dev, u8 ep)
 498{
 499        u8 chid;
 500        u8 hub;
 501
 502        /* Find out the nearest parent which is high speed */
 503        while (dev->parent->parent != NULL)
 504                if (get_dev_speed(dev->parent) !=  MUSB_TYPE_SPEED_HIGH)
 505                        dev = dev->parent;
 506                else
 507                        break;
 508
 509        /* determine the port address at that hub */
 510        hub = dev->parent->devnum;
 511        for (chid = 0; chid < USB_MAXCHILDREN; chid++)
 512                if (dev->parent->children[chid] == dev)
 513                        break;
 514
 515#ifndef MUSB_NO_MULTIPOINT
 516        /* configure the hub address and the port address */
 517        writeb(hub, &musbr->tar[ep].txhubaddr);
 518        writeb((chid + 1), &musbr->tar[ep].txhubport);
 519        writeb(hub, &musbr->tar[ep].rxhubaddr);
 520        writeb((chid + 1), &musbr->tar[ep].rxhubport);
 521#endif
 522}
 523
 524#ifdef MUSB_NO_MULTIPOINT
 525
 526static void musb_port_reset(int do_reset)
 527{
 528        u8 power = readb(&musbr->power);
 529
 530        if (do_reset) {
 531                power &= 0xf0;
 532                writeb(power | MUSB_POWER_RESET, &musbr->power);
 533                port_status |= USB_PORT_STAT_RESET;
 534                port_status &= ~USB_PORT_STAT_ENABLE;
 535                udelay(30000);
 536        } else {
 537                writeb(power & ~MUSB_POWER_RESET, &musbr->power);
 538
 539                power = readb(&musbr->power);
 540                if (power & MUSB_POWER_HSMODE)
 541                        port_status |= USB_PORT_STAT_HIGH_SPEED;
 542
 543                port_status &= ~(USB_PORT_STAT_RESET | (USB_PORT_STAT_C_CONNECTION << 16));
 544                port_status |= USB_PORT_STAT_ENABLE
 545                        | (USB_PORT_STAT_C_RESET << 16)
 546                        | (USB_PORT_STAT_C_ENABLE << 16);
 547        }
 548}
 549
 550/*
 551 * root hub control
 552 */
 553static int musb_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
 554                              void *buffer, int transfer_len,
 555                              struct devrequest *cmd)
 556{
 557        int leni = transfer_len;
 558        int len = 0;
 559        int stat = 0;
 560        u32 datab[4];
 561        const u8 *data_buf = (u8 *) datab;
 562        u16 bmRType_bReq;
 563        u16 wValue;
 564        u16 wIndex;
 565        u16 wLength;
 566        u16 int_usb;
 567
 568        if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) {
 569                debug("Root-Hub submit IRQ: NOT implemented\n");
 570                return 0;
 571        }
 572
 573        bmRType_bReq = cmd->requesttype | (cmd->request << 8);
 574        wValue = swap_16(cmd->value);
 575        wIndex = swap_16(cmd->index);
 576        wLength = swap_16(cmd->length);
 577
 578        debug("--- HUB ----------------------------------------\n");
 579        debug("submit rh urb, req=%x val=%#x index=%#x len=%d\n",
 580            bmRType_bReq, wValue, wIndex, wLength);
 581        debug("------------------------------------------------\n");
 582
 583        switch (bmRType_bReq) {
 584        case RH_GET_STATUS:
 585                debug("RH_GET_STATUS\n");
 586
 587                *(__u16 *) data_buf = swap_16(1);
 588                len = 2;
 589                break;
 590
 591        case RH_GET_STATUS | RH_INTERFACE:
 592                debug("RH_GET_STATUS | RH_INTERFACE\n");
 593
 594                *(__u16 *) data_buf = swap_16(0);
 595                len = 2;
 596                break;
 597
 598        case RH_GET_STATUS | RH_ENDPOINT:
 599                debug("RH_GET_STATUS | RH_ENDPOINT\n");
 600
 601                *(__u16 *) data_buf = swap_16(0);
 602                len = 2;
 603                break;
 604
 605        case RH_GET_STATUS | RH_CLASS:
 606                debug("RH_GET_STATUS | RH_CLASS\n");
 607
 608                *(__u32 *) data_buf = swap_32(0);
 609                len = 4;
 610                break;
 611
 612        case RH_GET_STATUS | RH_OTHER | RH_CLASS:
 613                debug("RH_GET_STATUS | RH_OTHER | RH_CLASS\n");
 614
 615                int_usb = readw(&musbr->intrusb);
 616                if (int_usb & MUSB_INTR_CONNECT) {
 617                        port_status |= USB_PORT_STAT_CONNECTION
 618                                | (USB_PORT_STAT_C_CONNECTION << 16);
 619                        port_status |= USB_PORT_STAT_HIGH_SPEED
 620                                | USB_PORT_STAT_ENABLE;
 621                }
 622
 623                if (port_status & USB_PORT_STAT_RESET)
 624                        musb_port_reset(0);
 625
 626                *(__u32 *) data_buf = swap_32(port_status);
 627                len = 4;
 628                break;
 629
 630        case RH_CLEAR_FEATURE | RH_ENDPOINT:
 631                debug("RH_CLEAR_FEATURE | RH_ENDPOINT\n");
 632
 633                switch (wValue) {
 634                case RH_ENDPOINT_STALL:
 635                        debug("C_HUB_ENDPOINT_STALL\n");
 636                        len = 0;
 637                        break;
 638                }
 639                port_status &= ~(1 << wValue);
 640                break;
 641
 642        case RH_CLEAR_FEATURE | RH_CLASS:
 643                debug("RH_CLEAR_FEATURE | RH_CLASS\n");
 644
 645                switch (wValue) {
 646                case RH_C_HUB_LOCAL_POWER:
 647                        debug("C_HUB_LOCAL_POWER\n");
 648                        len = 0;
 649                        break;
 650
 651                case RH_C_HUB_OVER_CURRENT:
 652                        debug("C_HUB_OVER_CURRENT\n");
 653                        len = 0;
 654                        break;
 655                }
 656                port_status &= ~(1 << wValue);
 657                break;
 658
 659        case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
 660                debug("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS\n");
 661
 662                switch (wValue) {
 663                case RH_PORT_ENABLE:
 664                        len = 0;
 665                        break;
 666
 667                case RH_PORT_SUSPEND:
 668                        len = 0;
 669                        break;
 670
 671                case RH_PORT_POWER:
 672                        len = 0;
 673                        break;
 674
 675                case RH_C_PORT_CONNECTION:
 676                        len = 0;
 677                        break;
 678
 679                case RH_C_PORT_ENABLE:
 680                        len = 0;
 681                        break;
 682
 683                case RH_C_PORT_SUSPEND:
 684                        len = 0;
 685                        break;
 686
 687                case RH_C_PORT_OVER_CURRENT:
 688                        len = 0;
 689                        break;
 690
 691                case RH_C_PORT_RESET:
 692                        len = 0;
 693                        break;
 694
 695                default:
 696                        debug("invalid wValue\n");
 697                        stat = USB_ST_STALLED;
 698                }
 699
 700                port_status &= ~(1 << wValue);
 701                break;
 702
 703        case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
 704                debug("RH_SET_FEATURE | RH_OTHER | RH_CLASS\n");
 705
 706                switch (wValue) {
 707                case RH_PORT_SUSPEND:
 708                        len = 0;
 709                        break;
 710
 711                case RH_PORT_RESET:
 712                        musb_port_reset(1);
 713                        len = 0;
 714                        break;
 715
 716                case RH_PORT_POWER:
 717                        len = 0;
 718                        break;
 719
 720                case RH_PORT_ENABLE:
 721                        len = 0;
 722                        break;
 723
 724                default:
 725                        debug("invalid wValue\n");
 726                        stat = USB_ST_STALLED;
 727                }
 728
 729                port_status |= 1 << wValue;
 730                break;
 731
 732        case RH_SET_ADDRESS:
 733                debug("RH_SET_ADDRESS\n");
 734
 735                rh_devnum = wValue;
 736                len = 0;
 737                break;
 738
 739        case RH_GET_DESCRIPTOR:
 740                debug("RH_GET_DESCRIPTOR: %x, %d\n", wValue, wLength);
 741
 742                switch (wValue) {
 743                case (USB_DT_DEVICE << 8):      /* device descriptor */
 744                        len = min_t(unsigned int,
 745                                    leni, min_t(unsigned int,
 746                                                sizeof(root_hub_dev_des),
 747                                                wLength));
 748                        data_buf = root_hub_dev_des;
 749                        break;
 750
 751                case (USB_DT_CONFIG << 8):      /* configuration descriptor */
 752                        len = min_t(unsigned int,
 753                                    leni, min_t(unsigned int,
 754                                                sizeof(root_hub_config_des),
 755                                                wLength));
 756                        data_buf = root_hub_config_des;
 757                        break;
 758
 759                case ((USB_DT_STRING << 8) | 0x00):     /* string 0 descriptors */
 760                        len = min_t(unsigned int,
 761                                    leni, min_t(unsigned int,
 762                                                sizeof(root_hub_str_index0),
 763                                                wLength));
 764                        data_buf = root_hub_str_index0;
 765                        break;
 766
 767                case ((USB_DT_STRING << 8) | 0x01):     /* string 1 descriptors */
 768                        len = min_t(unsigned int,
 769                                    leni, min_t(unsigned int,
 770                                                sizeof(root_hub_str_index1),
 771                                                wLength));
 772                        data_buf = root_hub_str_index1;
 773                        break;
 774
 775                default:
 776                        debug("invalid wValue\n");
 777                        stat = USB_ST_STALLED;
 778                }
 779
 780                break;
 781
 782        case RH_GET_DESCRIPTOR | RH_CLASS: {
 783                u8 *_data_buf = (u8 *) datab;
 784                debug("RH_GET_DESCRIPTOR | RH_CLASS\n");
 785
 786                _data_buf[0] = 0x09;    /* min length; */
 787                _data_buf[1] = 0x29;
 788                _data_buf[2] = 0x1;     /* 1 port */
 789                _data_buf[3] = 0x01;    /* per-port power switching */
 790                _data_buf[3] |= 0x10;   /* no overcurrent reporting */
 791
 792                /* Corresponds to data_buf[4-7] */
 793                _data_buf[4] = 0;
 794                _data_buf[5] = 5;
 795                _data_buf[6] = 0;
 796                _data_buf[7] = 0x02;
 797                _data_buf[8] = 0xff;
 798
 799                len = min_t(unsigned int, leni,
 800                            min_t(unsigned int, data_buf[0], wLength));
 801                break;
 802        }
 803
 804        case RH_GET_CONFIGURATION:
 805                debug("RH_GET_CONFIGURATION\n");
 806
 807                *(__u8 *) data_buf = 0x01;
 808                len = 1;
 809                break;
 810
 811        case RH_SET_CONFIGURATION:
 812                debug("RH_SET_CONFIGURATION\n");
 813
 814                len = 0;
 815                break;
 816
 817        default:
 818                debug("*** *** *** unsupported root hub command *** *** ***\n");
 819                stat = USB_ST_STALLED;
 820        }
 821
 822        len = min_t(int, len, leni);
 823        if (buffer != data_buf)
 824                memcpy(buffer, data_buf, len);
 825
 826        dev->act_len = len;
 827        dev->status = stat;
 828        debug("dev act_len %d, status %lu\n", dev->act_len, dev->status);
 829
 830        return stat;
 831}
 832
 833static void musb_rh_init(void)
 834{
 835        rh_devnum = 0;
 836        port_status = 0;
 837}
 838
 839#else
 840
 841static void musb_rh_init(void) {}
 842
 843#endif
 844
 845/*
 846 * do a control transfer
 847 */
 848int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 849                        int len, struct devrequest *setup)
 850{
 851        int devnum = usb_pipedevice(pipe);
 852        u8  devspeed;
 853
 854#ifdef MUSB_NO_MULTIPOINT
 855        /* Control message is for the HUB? */
 856        if (devnum == rh_devnum) {
 857                int stat = musb_submit_rh_msg(dev, pipe, buffer, len, setup);
 858                if (stat)
 859                        return stat;
 860        }
 861#endif
 862
 863        /* select control endpoint */
 864        writeb(MUSB_CONTROL_EP, &musbr->index);
 865        readw(&musbr->txcsr);
 866
 867#ifndef MUSB_NO_MULTIPOINT
 868        /* target addr and (for multipoint) hub addr/port */
 869        writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].txfuncaddr);
 870        writeb(devnum, &musbr->tar[MUSB_CONTROL_EP].rxfuncaddr);
 871#endif
 872
 873        /* configure the hub address and the port number as required */
 874        devspeed = get_dev_speed(dev);
 875        if ((musb_ishighspeed()) && (dev->parent != NULL) &&
 876                (devspeed != MUSB_TYPE_SPEED_HIGH)) {
 877                config_hub_port(dev, MUSB_CONTROL_EP);
 878                writeb(devspeed << 6, &musbr->txtype);
 879        } else {
 880                writeb(musb_cfg.musb_speed << 6, &musbr->txtype);
 881#ifndef MUSB_NO_MULTIPOINT
 882                writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubaddr);
 883                writeb(0, &musbr->tar[MUSB_CONTROL_EP].txhubport);
 884                writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubaddr);
 885                writeb(0, &musbr->tar[MUSB_CONTROL_EP].rxhubport);
 886#endif
 887        }
 888
 889        /* Control transfer setup phase */
 890        if (ctrlreq_setup_phase(dev, setup) < 0)
 891                return 0;
 892
 893        switch (setup->request) {
 894        case USB_REQ_GET_DESCRIPTOR:
 895        case USB_REQ_GET_CONFIGURATION:
 896        case USB_REQ_GET_INTERFACE:
 897        case USB_REQ_GET_STATUS:
 898        case USB_MSC_BBB_GET_MAX_LUN:
 899                /* control transfer in-data-phase */
 900                if (ctrlreq_in_data_phase(dev, len, buffer) < 0)
 901                        return 0;
 902                /* control transfer out-status-phase */
 903                if (ctrlreq_out_status_phase(dev) < 0)
 904                        return 0;
 905                break;
 906
 907        case USB_REQ_SET_ADDRESS:
 908        case USB_REQ_SET_CONFIGURATION:
 909        case USB_REQ_SET_FEATURE:
 910        case USB_REQ_SET_INTERFACE:
 911        case USB_REQ_CLEAR_FEATURE:
 912        case USB_MSC_BBB_RESET:
 913                /* control transfer in status phase */
 914                if (ctrlreq_in_status_phase(dev) < 0)
 915                        return 0;
 916                break;
 917
 918        case USB_REQ_SET_DESCRIPTOR:
 919                /* control transfer out data phase */
 920                if (ctrlreq_out_data_phase(dev, len, buffer) < 0)
 921                        return 0;
 922                /* control transfer in status phase */
 923                if (ctrlreq_in_status_phase(dev) < 0)
 924                        return 0;
 925                break;
 926
 927        default:
 928                /* unhandled control transfer */
 929                return -1;
 930        }
 931
 932        dev->status = 0;
 933        dev->act_len = len;
 934
 935#ifdef MUSB_NO_MULTIPOINT
 936        /* Set device address to USB_FADDR register */
 937        if (setup->request == USB_REQ_SET_ADDRESS)
 938                writeb(dev->devnum, &musbr->faddr);
 939#endif
 940
 941        return len;
 942}
 943
 944/*
 945 * do a bulk transfer
 946 */
 947int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
 948                                        void *buffer, int len)
 949{
 950        int dir_out = usb_pipeout(pipe);
 951        int ep = usb_pipeendpoint(pipe);
 952#ifndef MUSB_NO_MULTIPOINT
 953        int devnum = usb_pipedevice(pipe);
 954#endif
 955        u8  type;
 956        u16 csr;
 957        u32 txlen = 0;
 958        u32 nextlen = 0;
 959        u8  devspeed;
 960
 961        /* select bulk endpoint */
 962        writeb(MUSB_BULK_EP, &musbr->index);
 963
 964#ifndef MUSB_NO_MULTIPOINT
 965        /* write the address of the device */
 966        if (dir_out)
 967                writeb(devnum, &musbr->tar[MUSB_BULK_EP].txfuncaddr);
 968        else
 969                writeb(devnum, &musbr->tar[MUSB_BULK_EP].rxfuncaddr);
 970#endif
 971
 972        /* configure the hub address and the port number as required */
 973        devspeed = get_dev_speed(dev);
 974        if ((musb_ishighspeed()) && (dev->parent != NULL) &&
 975                (devspeed != MUSB_TYPE_SPEED_HIGH)) {
 976                /*
 977                 * MUSB is in high speed and the destination device is full
 978                 * speed device. So configure the hub address and port
 979                 * address registers.
 980                 */
 981                config_hub_port(dev, MUSB_BULK_EP);
 982        } else {
 983#ifndef MUSB_NO_MULTIPOINT
 984                if (dir_out) {
 985                        writeb(0, &musbr->tar[MUSB_BULK_EP].txhubaddr);
 986                        writeb(0, &musbr->tar[MUSB_BULK_EP].txhubport);
 987                } else {
 988                        writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubaddr);
 989                        writeb(0, &musbr->tar[MUSB_BULK_EP].rxhubport);
 990                }
 991#endif
 992                devspeed = musb_cfg.musb_speed;
 993        }
 994
 995        /* Write the saved toggle bit value */
 996        write_toggle(dev, ep, dir_out);
 997
 998        if (dir_out) { /* bulk-out transfer */
 999                /* Program the TxType register */
1000                type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
1001                           (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) |
1002                           (ep & MUSB_TYPE_REMOTE_END);
1003                writeb(type, &musbr->txtype);
1004
1005                /* Write maximum packet size to the TxMaxp register */
1006                writew(dev->epmaxpacketout[ep], &musbr->txmaxp);
1007                while (txlen < len) {
1008                        nextlen = ((len-txlen) < dev->epmaxpacketout[ep]) ?
1009                                        (len-txlen) : dev->epmaxpacketout[ep];
1010
1011#ifdef CONFIG_USB_BLACKFIN
1012                        /* Set the transfer data size */
1013                        writew(nextlen, &musbr->txcount);
1014#endif
1015
1016                        /* Write the data to the FIFO */
1017                        write_fifo(MUSB_BULK_EP, nextlen,
1018                                        (void *)(((u8 *)buffer) + txlen));
1019
1020                        /* Set the TxPktRdy bit */
1021                        csr = readw(&musbr->txcsr);
1022                        writew(csr | MUSB_TXCSR_TXPKTRDY, &musbr->txcsr);
1023
1024                        /* Wait until the TxPktRdy bit is cleared */
1025                        if (!wait_until_txep_ready(dev, MUSB_BULK_EP)) {
1026                                readw(&musbr->txcsr);
1027                                usb_settoggle(dev, ep, dir_out,
1028                                (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1);
1029                                dev->act_len = txlen;
1030                                return 0;
1031                        }
1032                        txlen += nextlen;
1033                }
1034
1035                /* Keep a copy of the data toggle bit */
1036                csr = readw(&musbr->txcsr);
1037                usb_settoggle(dev, ep, dir_out,
1038                                (csr >> MUSB_TXCSR_H_DATATOGGLE_SHIFT) & 1);
1039        } else { /* bulk-in transfer */
1040                /* Write the saved toggle bit value */
1041                write_toggle(dev, ep, dir_out);
1042
1043                /* Program the RxType register */
1044                type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
1045                           (MUSB_TYPE_PROTO_BULK << MUSB_TYPE_PROTO_SHIFT) |
1046                           (ep & MUSB_TYPE_REMOTE_END);
1047                writeb(type, &musbr->rxtype);
1048
1049                /* Write the maximum packet size to the RxMaxp register */
1050                writew(dev->epmaxpacketin[ep], &musbr->rxmaxp);
1051                while (txlen < len) {
1052                        nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ?
1053                                        (len-txlen) : dev->epmaxpacketin[ep];
1054
1055                        /* Set the ReqPkt bit */
1056                        csr = readw(&musbr->rxcsr);
1057                        writew(csr | MUSB_RXCSR_H_REQPKT, &musbr->rxcsr);
1058
1059                        /* Wait until the RxPktRdy bit is set */
1060                        if (!wait_until_rxep_ready(dev, MUSB_BULK_EP)) {
1061                                csr = readw(&musbr->rxcsr);
1062                                usb_settoggle(dev, ep, dir_out,
1063                                (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
1064                                csr &= ~MUSB_RXCSR_RXPKTRDY;
1065                                writew(csr, &musbr->rxcsr);
1066                                dev->act_len = txlen;
1067                                return 0;
1068                        }
1069
1070                        /* Read the data from the FIFO */
1071                        read_fifo(MUSB_BULK_EP, nextlen,
1072                                        (void *)(((u8 *)buffer) + txlen));
1073
1074                        /* Clear the RxPktRdy bit */
1075                        csr =  readw(&musbr->rxcsr);
1076                        csr &= ~MUSB_RXCSR_RXPKTRDY;
1077                        writew(csr, &musbr->rxcsr);
1078                        txlen += nextlen;
1079                }
1080
1081                /* Keep a copy of the data toggle bit */
1082                csr = readw(&musbr->rxcsr);
1083                usb_settoggle(dev, ep, dir_out,
1084                                (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
1085        }
1086
1087        /* bulk transfer is complete */
1088        dev->status = 0;
1089        dev->act_len = len;
1090        return 0;
1091}
1092
1093/*
1094 * This function initializes the usb controller module.
1095 */
1096int usb_lowlevel_init(int index, void **controller)
1097{
1098        u8  power;
1099        u32 timeout;
1100
1101        musb_rh_init();
1102
1103        if (musb_platform_init() == -1)
1104                return -1;
1105
1106        /* Configure all the endpoint FIFO's and start usb controller */
1107        musbr = musb_cfg.regs;
1108        musb_configure_ep(&epinfo[0], ARRAY_SIZE(epinfo));
1109        musb_start();
1110
1111        /*
1112         * Wait until musb is enabled in host mode with a timeout. There
1113         * should be a usb device connected.
1114         */
1115        timeout = musb_cfg.timeout;
1116        while (--timeout)
1117                if (readb(&musbr->devctl) & MUSB_DEVCTL_HM)
1118                        break;
1119
1120        /* if musb core is not in host mode, then return */
1121        if (!timeout)
1122                return -1;
1123
1124        /* start usb bus reset */
1125        power = readb(&musbr->power);
1126        writeb(power | MUSB_POWER_RESET, &musbr->power);
1127
1128        /* After initiating a usb reset, wait for about 20ms to 30ms */
1129        udelay(30000);
1130
1131        /* stop usb bus reset */
1132        power = readb(&musbr->power);
1133        power &= ~MUSB_POWER_RESET;
1134        writeb(power, &musbr->power);
1135
1136        /* Determine if the connected device is a high/full/low speed device */
1137        musb_cfg.musb_speed = (readb(&musbr->power) & MUSB_POWER_HSMODE) ?
1138                        MUSB_TYPE_SPEED_HIGH :
1139                        ((readb(&musbr->devctl) & MUSB_DEVCTL_FSDEV) ?
1140                        MUSB_TYPE_SPEED_FULL : MUSB_TYPE_SPEED_LOW);
1141        return 0;
1142}
1143
1144/*
1145 * This function stops the operation of the davinci usb module.
1146 */
1147int usb_lowlevel_stop(int index)
1148{
1149        /* Reset the USB module */
1150        musb_platform_deinit();
1151        writeb(0, &musbr->devctl);
1152        return 0;
1153}
1154
1155/*
1156 * This function supports usb interrupt transfers. Currently, usb interrupt
1157 * transfers are not supported.
1158 */
1159int submit_int_msg(struct usb_device *dev, unsigned long pipe,
1160                                void *buffer, int len, int interval)
1161{
1162        int dir_out = usb_pipeout(pipe);
1163        int ep = usb_pipeendpoint(pipe);
1164#ifndef MUSB_NO_MULTIPOINT
1165        int devnum = usb_pipedevice(pipe);
1166#endif
1167        u8  type;
1168        u16 csr;
1169        u32 txlen = 0;
1170        u32 nextlen = 0;
1171        u8  devspeed;
1172
1173        /* select interrupt endpoint */
1174        writeb(MUSB_INTR_EP, &musbr->index);
1175
1176#ifndef MUSB_NO_MULTIPOINT
1177        /* write the address of the device */
1178        if (dir_out)
1179                writeb(devnum, &musbr->tar[MUSB_INTR_EP].txfuncaddr);
1180        else
1181                writeb(devnum, &musbr->tar[MUSB_INTR_EP].rxfuncaddr);
1182#endif
1183
1184        /* configure the hub address and the port number as required */
1185        devspeed = get_dev_speed(dev);
1186        if ((musb_ishighspeed()) && (dev->parent != NULL) &&
1187                (devspeed != MUSB_TYPE_SPEED_HIGH)) {
1188                /*
1189                 * MUSB is in high speed and the destination device is full
1190                 * speed device. So configure the hub address and port
1191                 * address registers.
1192                 */
1193                config_hub_port(dev, MUSB_INTR_EP);
1194        } else {
1195#ifndef MUSB_NO_MULTIPOINT
1196                if (dir_out) {
1197                        writeb(0, &musbr->tar[MUSB_INTR_EP].txhubaddr);
1198                        writeb(0, &musbr->tar[MUSB_INTR_EP].txhubport);
1199                } else {
1200                        writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubaddr);
1201                        writeb(0, &musbr->tar[MUSB_INTR_EP].rxhubport);
1202                }
1203#endif
1204                devspeed = musb_cfg.musb_speed;
1205        }
1206
1207        /* Write the saved toggle bit value */
1208        write_toggle(dev, ep, dir_out);
1209
1210        if (!dir_out) { /* intrrupt-in transfer */
1211                /* Write the saved toggle bit value */
1212                write_toggle(dev, ep, dir_out);
1213                writeb(interval, &musbr->rxinterval);
1214
1215                /* Program the RxType register */
1216                type = (devspeed << MUSB_TYPE_SPEED_SHIFT) |
1217                           (MUSB_TYPE_PROTO_INTR << MUSB_TYPE_PROTO_SHIFT) |
1218                           (ep & MUSB_TYPE_REMOTE_END);
1219                writeb(type, &musbr->rxtype);
1220
1221                /* Write the maximum packet size to the RxMaxp register */
1222                writew(dev->epmaxpacketin[ep], &musbr->rxmaxp);
1223
1224                while (txlen < len) {
1225                        nextlen = ((len-txlen) < dev->epmaxpacketin[ep]) ?
1226                                        (len-txlen) : dev->epmaxpacketin[ep];
1227
1228                        /* Set the ReqPkt bit */
1229                        csr = readw(&musbr->rxcsr);
1230                        writew(csr | MUSB_RXCSR_H_REQPKT, &musbr->rxcsr);
1231
1232                        /* Wait until the RxPktRdy bit is set */
1233                        if (!wait_until_rxep_ready(dev, MUSB_INTR_EP)) {
1234                                csr = readw(&musbr->rxcsr);
1235                                usb_settoggle(dev, ep, dir_out,
1236                                (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
1237                                csr &= ~MUSB_RXCSR_RXPKTRDY;
1238                                writew(csr, &musbr->rxcsr);
1239                                dev->act_len = txlen;
1240                                return 0;
1241                        }
1242
1243                        /* Read the data from the FIFO */
1244                        read_fifo(MUSB_INTR_EP, nextlen,
1245                                        (void *)(((u8 *)buffer) + txlen));
1246
1247                        /* Clear the RxPktRdy bit */
1248                        csr =  readw(&musbr->rxcsr);
1249                        csr &= ~MUSB_RXCSR_RXPKTRDY;
1250                        writew(csr, &musbr->rxcsr);
1251                        txlen += nextlen;
1252                }
1253
1254                /* Keep a copy of the data toggle bit */
1255                csr = readw(&musbr->rxcsr);
1256                usb_settoggle(dev, ep, dir_out,
1257                                (csr >> MUSB_S_RXCSR_H_DATATOGGLE) & 1);
1258        }
1259
1260        /* interrupt transfer is complete */
1261        dev->irq_status = 0;
1262        dev->irq_act_len = len;
1263        dev->irq_handle(dev);
1264        dev->status = 0;
1265        dev->act_len = len;
1266        return 0;
1267}
1268