Ejemplo n.º 1
0
/*!
 * \brief Initialize the RTC in LPC 17xx controller
 *
 * \return 0 on success or -1 in case of an error.
 *
 */
static int Lpc17xxRtcInit(NUTRTC *rtc)
{
    rtc->dcb = NutHeapAllocClear(sizeof(lpc17xx_rtc_dcb));
    if (rtc->dcb == NULL) {
        return -1;
    }

    if (NutRegisterIrqHandler(&sig_RTC, Lpc17xxRtcInterrupt, rtc) != 0) {
        NutHeapFree(rtc->dcb);
        return -1;
    }

    /* Set up clock and power for RTC module */
    SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCRTC);

    /* Clear all register to be default */
    LPC_RTC->ILR  = 0x03;
    LPC_RTC->CCR  = 0x00;
    LPC_RTC->CIIR = 0x00;
    LPC_RTC->AMR  = 0xFF;
    LPC_RTC->CALIBRATION = 0x00;

    /* enable RTC (run) */
    LPC_RTC->CCR |= RTC_CCR_CLKEN;

    ((lpc17xx_rtc_dcb *)rtc->dcb)->flags = 0x00000000;
    rtc->alarm = NULL;

    NutIrqEnable(&sig_RTC);

    return(0);
}
/*!
 * \brief Create a copy of an existing network buffer
 *        structure.
 *
 * \param nb Points to an existing network buffer
 *           structure, previously allocated by
 *           NutNetBufAlloc().
 *
 * \return Pointer to a newly allocated copy.
 */
NETBUF *NutNetBufClone(NETBUF * nb)
{
    NETBUF *clone;

    if ((clone = NutHeapAllocClear(sizeof(NETBUF))) == 0)
        return 0;

    if (nb->nb_dl.sz) {
        if (NutNetBufAllocData(&clone->nb_dl, nb->nb_dl.sz)) {
            NutNetBufFree(clone);
            return 0;
        }
        memcpy(clone->nb_dl.vp, nb->nb_dl.vp, nb->nb_dl.sz);
        clone->nb_flags |= NBAF_DATALINK;
    }
    if (nb->nb_nw.sz) {
        if (NutNetBufAllocData(&clone->nb_nw, nb->nb_nw.sz)) {
            NutNetBufFree(clone);
            return 0;
        }
        memcpy(clone->nb_nw.vp, nb->nb_nw.vp, nb->nb_nw.sz);
        clone->nb_flags |= NBAF_NETWORK;
    }
    if (nb->nb_tp.sz) {
        if (NutNetBufAllocData(&clone->nb_tp, nb->nb_tp.sz)) {
            NutNetBufFree(clone);
            return 0;
        }
        memcpy(clone->nb_tp.vp, nb->nb_tp.vp, nb->nb_tp.sz);
        clone->nb_flags |= NBAF_TRANSPORT;
    }
    if (nb->nb_ap.sz) {
        if (NutNetBufAllocData(&clone->nb_ap, nb->nb_ap.sz)) {
            NutNetBufFree(clone);
            return 0;
        }
        memcpy(clone->nb_ap.vp, nb->nb_ap.vp, nb->nb_ap.sz);
        clone->nb_flags |= NBAF_APPLICATION;
    }
    return clone;
}
/*!
 * \brief Allocate or re-allocate a network buffer part.
 *
 * \param nb   Points to an existing network buffer structure or NULL, 
 *             if a new structure should be created. An existing buffer
 *             must not be used any further if this function returns
 *             a null pointer.
 * \param type Part of the buffer to be allocated. This can be any of
 *             the following:
 *             - NBAF_DATALINK
 *             - NBAF_NETWORK
 *             - NBAF_TRANSPORT
 *             - NBAF_APPLICATION
 * \param size Size of the part to be allocated.
 *
 * \return Pointer to the allocated network buffer structure. A null
 *         pointer is returned if not enough memory is available and
 *         the whole structure is released.
 */
NETBUF *NutNetBufAlloc(NETBUF * nb, u_char type, u_short size)
{
    if (nb == 0) {
        nb = NutHeapAllocClear(sizeof(NETBUF));
    }

    if (nb && type) {
        if (size) {
            if (type & NBAF_DATALINK) {
                if (nb->nb_flags & NBAF_DATALINK) {
                    if (nb->nb_dl.sz < size) {
                        NutNetBufFreeData(&nb->nb_dl);
                        if (NutNetBufAllocData(&nb->nb_dl, size)) {
                            NutNetBufFree(nb);
                            return 0;
                        }
                    } else
                        nb->nb_dl.sz = size;
                } else if (NutNetBufAllocData(&nb->nb_dl, size)) {
                    NutNetBufFree(nb);
                    return 0;
                }
            }

            if (type & NBAF_NETWORK) {
                if (nb->nb_flags & NBAF_NETWORK) {
                    if (nb->nb_nw.sz < size) {
                        NutNetBufFreeData(&nb->nb_nw);
                        if (NutNetBufAllocData(&nb->nb_nw, size)) {
                            NutNetBufFree(nb);
                            return 0;
                        }
                    } else
                        nb->nb_nw.sz = size;
                } else if (NutNetBufAllocData(&nb->nb_nw, size)) {
                    NutNetBufFree(nb);
                    return 0;
                }
            }

            if (type & NBAF_TRANSPORT) {
                if (nb->nb_flags & NBAF_TRANSPORT) {
                    if (nb->nb_tp.sz < size) {
                        NutNetBufFreeData(&nb->nb_tp);
                        if (NutNetBufAllocData(&nb->nb_tp, size)) {
                            NutNetBufFree(nb);
                            return 0;
                        }
                    } else
                        nb->nb_tp.sz = size;
                } else if (NutNetBufAllocData(&nb->nb_tp, size)) {
                    NutNetBufFree(nb);
                    return 0;
                }
            }

            if (type & NBAF_APPLICATION) {
                if (nb->nb_flags & NBAF_APPLICATION) {
                    if (nb->nb_ap.sz < size) {
                        NutNetBufFreeData(&nb->nb_ap);
                        if (NutNetBufAllocData(&nb->nb_ap, size)) {
                            NutNetBufFree(nb);
                            return 0;
                        }
                    } else
                        nb->nb_ap.sz = size;
                } else if (NutNetBufAllocData(&nb->nb_ap, size)) {
                    NutNetBufFree(nb);
                    return 0;
                }
            }
            nb->nb_flags |= type;
        } else {
            type &= nb->nb_flags;
            if (type & NBAF_DATALINK)
                NutNetBufFreeData(&nb->nb_dl);
            if (type & NBAF_NETWORK)
                NutNetBufFreeData(&nb->nb_nw);
            if (type & NBAF_TRANSPORT)
                NutNetBufFreeData(&nb->nb_tp);
            if (type & NBAF_APPLICATION)
                NutNetBufFreeData(&nb->nb_ap);
            nb->nb_flags &= ~type;
        }
    }
    return nb;
}
/*!
 * \brief Mount a partition.
 *
 * Nut/OS doesn't provide specific routines for mounting. Instead routines
 * for opening files are used.
 *
 * Applications should not directly call this function, but use the high
 * level stdio routines for opening a file.
 *
 * \param dev  Pointer to the MMC device.
 * \param name Partition number followed by a slash followed by a name
 *             of the file system device. Both items are optional. If no 
 *             file system driver name is given, the first file system
 *             driver found in the list of registered devices will be 
 *             used. If no partition number is specified or if partition
 *             zero is given, the first active primary partition will be 
 *             used.
 * \param mode Opening mode. Currently ignored, but 
 *             \code _O_RDWR | _O_BINARY \endcode should be used for
 *             compatibility with future enhancements.
 * \param acc  File attributes, ignored.
 *
 * \return Pointer to a newly created file pointer to the mounted
 *         partition or NUTFILE_EOF in case of any error.
 */
static NUTFILE *At91MciMount(NUTDEVICE * dev, CONST char *name, int mode, int acc)
{
    int partno = 0;
    int i;
    NUTDEVICE *fsdev;
    NUTFILE *nfp;
    MCIFCB *fcb;
    DOSPART *part;
    MCIFC *ifc = (MCIFC *) dev->dev_icb;
    FSCP_VOL_MOUNT mparm;

    if (At91MciDiscover(ifc)) {
        errno = ENODEV;
        return NUTFILE_EOF;
    }

    /* Parse the name for a partition number and a file system driver. */
    if (*name) {
        partno = atoi(name);
        do {
            name++;
        } while (*name && *name != '/');
        if (*name == '/') {
            name++;
        }
    }
#ifdef NUTDEBUG
    printf("['%s'-PART%d]", name, partno);
#endif

    /*
     * Check the list of registered devices for the given name of the
     * files system driver. If none has been specified, get the first
     * file system driver in the list. Hopefully the application
     * registered one only.
     */
    for (fsdev = nutDeviceList; fsdev; fsdev = fsdev->dev_next) {
        if (*name == 0) {
            if (fsdev->dev_type == IFTYP_FS) {
                break;
            }
        } else if (strcmp(fsdev->dev_name, name) == 0) {
            break;
        }
    }

    if (fsdev == 0) {
#ifdef NUTDEBUG
        printf("[No FSDriver]");
#endif
        errno = ENODEV;
        return NUTFILE_EOF;
    }

    if ((fcb = NutHeapAllocClear(sizeof(MCIFCB))) == 0) {
        errno = ENOMEM;
        return NUTFILE_EOF;
    }
    fcb->fcb_fsdev = fsdev;

    /* Initialize MMC access mutex semaphore. */
    NutEventPost(&mutex);

    /* Read MBR. */
    if (At91MciReadSingle(ifc, 0, fcb->fcb_blkbuf)) {
        NutHeapFree(fcb);
        return NUTFILE_EOF;
    }

    /* Read partition table. */
    part = (DOSPART *) & fcb->fcb_blkbuf[DOSPART_SECTORPOS];
    for (i = 1; i <= 4; i++) {
        if (partno) {
            if (i == partno) {
                /* Found specified partition number. */
                fcb->fcb_part = *part;
                break;
            }
        } else if (part->part_state & 0x80) {
            /* Located first active partition. */
            fcb->fcb_part = *part;
            break;
        }
        part++;
    }

    if (fcb->fcb_part.part_type == PTYPE_EMPTY) {
        NutHeapFree(fcb);
        return NUTFILE_EOF;
    }

    if ((nfp = NutHeapAlloc(sizeof(NUTFILE))) == 0) {
        NutHeapFree(fcb);
        errno = ENOMEM;
        return NUTFILE_EOF;
    }
    nfp->nf_next = 0;
    nfp->nf_dev = dev;
    nfp->nf_fcb = fcb;

    /*
     * Mount the file system volume.
     */
    mparm.fscp_bmnt = nfp;
    mparm.fscp_part_type = fcb->fcb_part.part_type;
    if (fsdev->dev_ioctl(fsdev, FS_VOL_MOUNT, &mparm)) {
        At91MciUnmount(nfp);
        return NUTFILE_EOF;
    }
    return nfp;
}