Ignore:
File:
1 edited

Legend:

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

    r3869c596 r3e6a98c5  
    3636
    3737#include <assert.h>
    38 #include <bool.h>
     38#include <stdbool.h>
    3939#include <errno.h>
     40#include <fibril_synch.h>
    4041#include <ddi.h>
    4142#include <ddf/log.h>
    42 #include <fibril_synch.h>
    43 #include <libarch/ddi.h>
    4443#include "i8237.h"
    4544
     
    199198        .channels = {
    200199                /* The first chip 8-bit */
    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,
     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,
    232231                },
    233232               
    234233                /* The second chip 16-bit */
    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,
     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,
    266265                },
    267266        },
     
    273272};
    274273
    275 /** Initialize I/O access to DMA controller I/O ports.
     274/* Initialize I/O access to DMA controller I/O ports.
    276275 *
    277276 * @param controller DMA Controller structure to initialize.
    278277 *
    279278 * @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  */
    312 static 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  */
    321 static inline bool is_dma8(unsigned channel)
    322 {
    323         return (channel < 4);
    324306}
    325307
     
    338320 *
    339321 * @return Error code.
    340  */
    341 int dma_channel_setup(unsigned int channel, uint32_t pa, uint16_t size,
     322 *
     323 */
     324int dma_setup_channel(unsigned int channel, uint32_t pa, uint16_t size,
    342325    uint8_t mode)
    343326{
    344         if (!is_dma8(channel) && !is_dma16(channel))
    345                 return ENOENT;
    346 
    347327        if ((channel == 0) || (channel == 4))
    348328                return ENOTSUP;
     329       
     330        if (channel > 7)
     331                return ENOENT;
    349332       
    350333        /* DMA is limited to 24bit addresses. */
     
    353336       
    354337        /* 8 bit channels use only 4 bits from the page register. */
    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))
     338        if ((channel > 0) && (channel < 4) && (pa >= (1 << 20)))
    360339                return EINVAL;
    361340       
     
    370349        }
    371350       
    372         ddf_msg(LVL_DEBUG, "Unspoiled address: %p and size: %zu.", pa, size);
    373        
    374351        /* 16 bit transfers are a bit special */
    375         if (is_dma16(channel)) {
     352        ddf_msg(LVL_DEBUG, "Unspoiled address %#" PRIx32 " (size %" PRIu16 ")",
     353            pa, size);
     354        if (channel > 4) {
    376355                /* Size must be aligned to 16 bits */
    377356                if ((size & 1) != 0) {
     
    379358                        return EINVAL;
    380359                }
    381                 /* Size is in 2byte words */
     360               
    382361                size >>= 1;
     362               
    383363                /* Address is fun: lower 16 bits need to be shifted by 1 */
    384364                pa = ((pa & 0xffff) >> 1) | (pa & 0xff0000);
     
    387367        const dma_channel_t dma_channel = controller_8237.channels[channel];
    388368       
    389         ddf_msg(LVL_DEBUG, "Setting channel %u, to address %p(%zu), mode %hhx.",
    390             channel, pa, size, mode);
     369        ddf_msg(LVL_DEBUG, "Setting channel %u to address %#" PRIx32 " "
     370            "(size %" PRIu16 "), mode %hhx.", channel, pa, size, mode);
    391371       
    392372        /* Mask DMA request */
     
    446426}
    447427
    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  */
    456 int 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 }
    495428/**
    496429 * @}
Note: See TracChangeset for help on using the changeset viewer.