Changes in uspace/drv/bus/isa/i8237.c [3e6a98c5:3869c596] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/isa/i8237.c
r3e6a98c5 r3869c596 36 36 37 37 #include <assert.h> 38 #include < stdbool.h>38 #include <bool.h> 39 39 #include <errno.h> 40 #include <fibril_synch.h>41 40 #include <ddi.h> 42 41 #include <ddf/log.h> 42 #include <fibril_synch.h> 43 #include <libarch/ddi.h> 43 44 #include "i8237.h" 44 45 … … 198 199 .channels = { 199 200 /* 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, 231 232 }, 232 233 233 234 /* 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, 265 266 }, 266 267 }, … … 272 273 }; 273 274 274 /* Initialize I/O access to DMA controller I/O ports.275 /** Initialize I/O access to DMA controller I/O ports. 275 276 * 276 277 * @param controller DMA Controller structure to initialize. 277 278 * 278 279 * @return Error code. 279 *280 280 */ 281 281 static inline int dma_controller_init(dma_controller_t *controller) … … 304 304 305 305 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); 306 324 } 307 325 … … 320 338 * 321 339 * @return Error code. 322 * 323 */ 324 int dma_setup_channel(unsigned int channel, uint32_t pa, uint16_t size, 340 */ 341 int dma_channel_setup(unsigned int channel, uint32_t pa, uint16_t size, 325 342 uint8_t mode) 326 343 { 344 if (!is_dma8(channel) && !is_dma16(channel)) 345 return ENOENT; 346 327 347 if ((channel == 0) || (channel == 4)) 328 348 return ENOTSUP; 329 330 if (channel > 7)331 return ENOENT;332 349 333 350 /* DMA is limited to 24bit addresses. */ … … 336 353 337 354 /* 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)) 339 360 return EINVAL; 340 361 … … 349 370 } 350 371 372 ddf_msg(LVL_DEBUG, "Unspoiled address: %p and size: %zu.", pa, size); 373 351 374 /* 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)) { 355 376 /* Size must be aligned to 16 bits */ 356 377 if ((size & 1) != 0) { … … 358 379 return EINVAL; 359 380 } 360 381 /* Size is in 2byte words */ 361 382 size >>= 1; 362 363 383 /* Address is fun: lower 16 bits need to be shifted by 1 */ 364 384 pa = ((pa & 0xffff) >> 1) | (pa & 0xff0000); … … 367 387 const dma_channel_t dma_channel = controller_8237.channels[channel]; 368 388 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); 371 391 372 392 /* Mask DMA request */ … … 426 446 } 427 447 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 } 428 495 /** 429 496 * @}
Note:
See TracChangeset
for help on using the changeset viewer.