Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/isa/i8237.c

    r3e6a98c5 r3869c596  
    3636
    3737#include <assert.h>
    38 #include <stdbool.h>
     38#include <bool.h>
    3939#include <errno.h>
    40 #include <fibril_synch.h>
    4140#include <ddi.h>
    4241#include <ddf/log.h>
     42#include <fibril_synch.h>
     43#include <libarch/ddi.h>
    4344#include "i8237.h"
    4445
     
    198199        .channels = {
    199200                /* The first chip 8-bit */
    200                 {
    201                         (uint8_t *) 0x00,
    202                         (uint8_t *) 0x01,
    203                         (uint8_t *) 0x87,
    204                         (uint8_t *) 0x0a,
    205                         (uint8_t *) 0x0b,
    206                         (uint8_t *) 0x0c,
    207                 },
    208                 {
    209                         (uint8_t *) 0x02,
    210                         (uint8_t *) 0x03,
    211                         (uint8_t *) 0x83,
    212                         (uint8_t *) 0x0a,
    213                         (uint8_t *) 0x0b,
    214                         (uint8_t *) 0x0c,
    215                 },
    216                 {
    217                         (uint8_t *) 0x04,
    218                         (uint8_t *) 0x05,
    219                         (uint8_t *) 0x81,
    220                         (uint8_t *) 0x0a,
    221                         (uint8_t *) 0x0b,
    222                         (uint8_t *) 0x0c,
    223                 },
    224                 {
    225                         (uint8_t *) 0x06,
    226                         (uint8_t *) 0x07,
    227                         (uint8_t *) 0x82,
    228                         (uint8_t *) 0x0a,
    229                         (uint8_t *) 0x0b,
    230                         (uint8_t *) 0x0c,
     201                { /* Channel 0 - Unusable*/
     202                        .offset_reg_address = (uint8_t *) 0x00,
     203                        .size_reg_address = (uint8_t *) 0x01,
     204                        .page_reg_address = (uint8_t *) 0x87,
     205                        .single_mask_address = (uint8_t *) 0x0a,
     206                        .mode_address = (uint8_t *) 0x0b,
     207                        .flip_flop_address = (uint8_t *) 0x0c,
     208                },
     209                { /* Channel 1 */
     210                        .offset_reg_address = (uint8_t *) 0x02,
     211                        .size_reg_address = (uint8_t *) 0x03,
     212                        .page_reg_address = (uint8_t *) 0x83,
     213                        .single_mask_address = (uint8_t *) 0x0a,
     214                        .mode_address = (uint8_t *) 0x0b,
     215                        .flip_flop_address = (uint8_t *) 0x0c,
     216                },
     217                { /* Channel 2 */
     218                        .offset_reg_address = (uint8_t *) 0x04,
     219                        .size_reg_address = (uint8_t *) 0x05,
     220                        .page_reg_address = (uint8_t *) 0x81,
     221                        .single_mask_address = (uint8_t *) 0x0a,
     222                        .mode_address = (uint8_t *) 0x0b,
     223                        .flip_flop_address = (uint8_t *) 0x0c,
     224                },
     225                { /* Channel 3 */
     226                        .offset_reg_address = (uint8_t *) 0x06,
     227                        .size_reg_address = (uint8_t *) 0x07,
     228                        .page_reg_address = (uint8_t *) 0x82,
     229                        .single_mask_address = (uint8_t *) 0x0a,
     230                        .mode_address = (uint8_t *) 0x0b,
     231                        .flip_flop_address = (uint8_t *) 0x0c,
    231232                },
    232233               
    233234                /* The second chip 16-bit */
    234                 {
    235                         (uint8_t *) 0xc0,
    236                         (uint8_t *) 0xc2,
    237                         (uint8_t *) 0x8f,
    238                         (uint8_t *) 0xd4,
    239                         (uint8_t *) 0xd6,
    240                         (uint8_t *) 0xd8,
    241                 },
    242                 {
    243                         (uint8_t *) 0xc4,
    244                         (uint8_t *) 0xc6,
    245                         (uint8_t *) 0x8b,
    246                         (uint8_t *) 0xd4,
    247                         (uint8_t *) 0xd6,
    248                         (uint8_t *) 0xd8,
    249                 },
    250                 {
    251                         (uint8_t *) 0xc8,
    252                         (uint8_t *) 0xca,
    253                         (uint8_t *) 0x89,
    254                         (uint8_t *) 0xd4,
    255                         (uint8_t *) 0xd6,
    256                         (uint8_t *) 0xd8,
    257                 },
    258                 {
    259                         (uint8_t *) 0xcc,
    260                         (uint8_t *) 0xce,
    261                         (uint8_t *) 0x8a,
    262                         (uint8_t *) 0xd4,
    263                         (uint8_t *) 0xd6,
    264                         (uint8_t *) 0xd8,
     235                { /* Channel 4 - Unusable */
     236                        .offset_reg_address = (uint8_t *) 0xc0,
     237                        .size_reg_address = (uint8_t *) 0xc2,
     238                        .page_reg_address = (uint8_t *) 0x8f,
     239                        .single_mask_address = (uint8_t *) 0xd4,
     240                        .mode_address = (uint8_t *) 0xd6,
     241                        .flip_flop_address = (uint8_t *) 0xd8,
     242                },
     243                { /* Channel 5 */
     244                        .offset_reg_address = (uint8_t *) 0xc4,
     245                        .size_reg_address = (uint8_t *) 0xc6,
     246                        .page_reg_address = (uint8_t *) 0x8b,
     247                        .single_mask_address = (uint8_t *) 0xd4,
     248                        .mode_address = (uint8_t *) 0xd6,
     249                        .flip_flop_address = (uint8_t *) 0xd8,
     250                },
     251                { /* Channel 6 */
     252                        .offset_reg_address = (uint8_t *) 0xc8,
     253                        .size_reg_address = (uint8_t *) 0xca,
     254                        .page_reg_address = (uint8_t *) 0x89,
     255                        .single_mask_address = (uint8_t *) 0xd4,
     256                        .mode_address = (uint8_t *) 0xd6,
     257                        .flip_flop_address = (uint8_t *) 0xd8,
     258                },
     259                { /* Channel 7 */
     260                        .offset_reg_address = (uint8_t *) 0xcc,
     261                        .size_reg_address = (uint8_t *) 0xce,
     262                        .page_reg_address = (uint8_t *) 0x8a,
     263                        .single_mask_address = (uint8_t *) 0xd4,
     264                        .mode_address = (uint8_t *) 0xd6,
     265                        .flip_flop_address = (uint8_t *) 0xd8,
    265266                },
    266267        },
     
    272273};
    273274
    274 /* Initialize I/O access to DMA controller I/O ports.
     275/** Initialize I/O access to DMA controller I/O ports.
    275276 *
    276277 * @param controller DMA Controller structure to initialize.
    277278 *
    278279 * @return Error code.
    279  *
    280280 */
    281281static inline int dma_controller_init(dma_controller_t *controller)
     
    304304       
    305305        return EOK;
     306}
     307
     308/** Helper function. Channels 4,5,6, and 7 are 8 bit DMA.
     309 * @pram channel DMA channel.
     310 * @reutrn True, if channel is 4,5,6, or 7, false otherwise.
     311 */
     312static inline bool is_dma16(unsigned channel)
     313{
     314        return (channel >= 4) && (channel < 8);
     315}
     316
     317/** Helper function. Channels 0,1,2, and 3 are 8 bit DMA.
     318 * @pram channel DMA channel.
     319 * @reutrn True, if channel is 0,1,2, or 3, false otherwise.
     320 */
     321static inline bool is_dma8(unsigned channel)
     322{
     323        return (channel < 4);
    306324}
    307325
     
    320338 *
    321339 * @return Error code.
    322  *
    323  */
    324 int dma_setup_channel(unsigned int channel, uint32_t pa, uint16_t size,
     340 */
     341int dma_channel_setup(unsigned int channel, uint32_t pa, uint16_t size,
    325342    uint8_t mode)
    326343{
     344        if (!is_dma8(channel) && !is_dma16(channel))
     345                return ENOENT;
     346
    327347        if ((channel == 0) || (channel == 4))
    328348                return ENOTSUP;
    329        
    330         if (channel > 7)
    331                 return ENOENT;
    332349       
    333350        /* DMA is limited to 24bit addresses. */
     
    336353       
    337354        /* 8 bit channels use only 4 bits from the page register. */
    338         if ((channel > 0) && (channel < 4) && (pa >= (1 << 20)))
     355        if (is_dma8(channel) && (pa >= (1 << 20)))
     356                return EINVAL;
     357
     358        /* Buffers cannot cross 64K page boundaries */
     359        if ((pa & 0xffff0000) !=  ((pa + size) & 0xffff0000))
    339360                return EINVAL;
    340361       
     
    349370        }
    350371       
     372        ddf_msg(LVL_DEBUG, "Unspoiled address: %p and size: %zu.", pa, size);
     373       
    351374        /* 16 bit transfers are a bit special */
    352         ddf_msg(LVL_DEBUG, "Unspoiled address %#" PRIx32 " (size %" PRIu16 ")",
    353             pa, size);
    354         if (channel > 4) {
     375        if (is_dma16(channel)) {
    355376                /* Size must be aligned to 16 bits */
    356377                if ((size & 1) != 0) {
     
    358379                        return EINVAL;
    359380                }
    360                
     381                /* Size is in 2byte words */
    361382                size >>= 1;
    362                
    363383                /* Address is fun: lower 16 bits need to be shifted by 1 */
    364384                pa = ((pa & 0xffff) >> 1) | (pa & 0xff0000);
     
    367387        const dma_channel_t dma_channel = controller_8237.channels[channel];
    368388       
    369         ddf_msg(LVL_DEBUG, "Setting channel %u to address %#" PRIx32 " "
    370             "(size %" PRIu16 "), mode %hhx.", channel, pa, size, mode);
     389        ddf_msg(LVL_DEBUG, "Setting channel %u, to address %p(%zu), mode %hhx.",
     390            channel, pa, size, mode);
    371391       
    372392        /* Mask DMA request */
     
    426446}
    427447
     448/** Query remaining buffer size.
     449 *
     450 * @param channel DMA Channel 1, 2, 3 for 8 bit transfers,
     451 *                    5, 6, 7 for 16 bit.
     452 * @param size    Place to store number of bytes pending in the assigned buffer.
     453 *
     454 * @return Error code.
     455 */
     456int dma_channel_remain(unsigned channel, size_t *size)
     457{
     458        assert(size);
     459        if (!is_dma8(channel) && !is_dma16(channel))
     460                return ENOENT;
     461       
     462        if ((channel == 0) || (channel == 4))
     463                return ENOTSUP;
     464       
     465        fibril_mutex_lock(&guard);
     466        if (!controller_8237.initialized) {
     467                fibril_mutex_unlock(&guard);
     468                return EIO;
     469        }
     470
     471        const dma_channel_t dma_channel = controller_8237.channels[channel];
     472        /* Get size - reset flip-flop */
     473        pio_write_8(dma_channel.flip_flop_address, 0);
     474       
     475        /* Low byte */
     476        const uint8_t value_low = pio_read_8(dma_channel.size_reg_address);
     477        ddf_msg(LVL_DEBUG2, "Read size low byte: %p:%zx.",
     478            dma_channel.size_reg_address, value_low);
     479       
     480        /* High byte */
     481        const uint8_t value_high = pio_read_8(dma_channel.size_reg_address);
     482        ddf_msg(LVL_DEBUG2, "Read size high byte: %p:%zx.",
     483            dma_channel.size_reg_address, value_high);
     484        fibril_mutex_unlock(&guard);
     485
     486        uint16_t remain = (value_high << 8 | value_low) ;
     487        /* 16 bit DMA size is in words,
     488         * the upper bits are bogus for 16bit transfers so we need to get
     489         * rid of them. Using limited type works well.*/
     490        if (is_dma16(channel))
     491                remain <<= 1;
     492        *size =  is_dma16(channel) ? remain + 2: remain + 1;
     493        return EOK;
     494}
    428495/**
    429496 * @}
Note: See TracChangeset for help on using the changeset viewer.