comparison packages/devs/eth/cl/cs8900a/current/src/if_cs8900a.c @ 941:01d8c3c977d9

* src/if_cs8900a.c (cs8900a_send): Allow for data not being 16-bit aligned. Thanks to Laurent Gonzalez <laurent.gonzalez@ri.silicomp.fr> for reporting this and his initial patch. * src/if_cs8900a.c: * include/cs8900a.h: Changes to support both little and big endian targets
author jlarmour
date Sat, 12 Apr 2003 03:50:18 +0000
parents ae8511176102
children 9c818dd5d9fa
comparison
equal deleted inserted replaced
940:26aa16c08c2e 941:01d8c3c977d9
73 #include <pkgconf/io_eth_drivers.h> 73 #include <pkgconf/io_eth_drivers.h>
74 74
75 #include <cyg/infra/cyg_type.h> 75 #include <cyg/infra/cyg_type.h>
76 #include <cyg/hal/hal_arch.h> 76 #include <cyg/hal/hal_arch.h>
77 #include <cyg/hal/hal_intr.h> 77 #include <cyg/hal/hal_intr.h>
78 #include <cyg/hal/hal_endian.h>
78 #include <cyg/infra/diag.h> 79 #include <cyg/infra/diag.h>
79 #include <cyg/hal/drv_api.h> 80 #include <cyg/hal/drv_api.h>
80 #undef __ECOS 81 #undef __ECOS
81 #define __ECOS 82 #define __ECOS
82 #include <cyg/io/eth/eth_drv.h> 83 #include <cyg/io/eth/eth_drv.h>
166 { 167 {
167 struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance; 168 struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
168 cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private; 169 cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
169 cyg_addrword_t base = cpd->base; 170 cyg_addrword_t base = cpd->base;
170 cyg_uint16 chip_type, chip_rev, chip_status; 171 cyg_uint16 chip_type, chip_rev, chip_status;
171 int i; 172 cyg_uint16 i;
172 long timeout = 500000; 173 long timeout = 500000;
173 cyg_bool esa_configured = false; 174 cyg_bool esa_configured = false;
174 175
175 cpd->tab = tab; 176 cpd->tab = tab;
176 177
210 chip_type = get_reg(base, PP_ChipID); 211 chip_type = get_reg(base, PP_ChipID);
211 chip_rev = get_reg(base, PP_ChipRev); 212 chip_rev = get_reg(base, PP_ChipRev);
212 #if DEBUG & 8 213 #if DEBUG & 8
213 diag_printf("CS8900A[%p] - type: 0x%04x, rev: 0x%04x\n", base, chip_type, chip_rev); 214 diag_printf("CS8900A[%p] - type: 0x%04x, rev: 0x%04x\n", base, chip_type, chip_rev);
214 #endif 215 #endif
215 if (chip_type != 0x630e) { 216 if (chip_type != PP_ChipID_CL) {
216 #if DEBUG & 8 217 #if DEBUG & 8
217 diag_printf("CS8900 - invalid type (0x%04x), must be 0x630e\n", chip_type); 218 diag_printf("CS8900 - invalid type (0x%04x), must be 0x630e\n", chip_type);
218 #endif 219 #endif
219 return false; 220 return false;
220 } 221 }
261 } 262 }
262 if (!esa_configured && (chip_status & PP_SelfStat_EEPROM)) { 263 if (!esa_configured && (chip_status & PP_SelfStat_EEPROM)) {
263 // Get ESA from EEPROM - via the PP_IA registers 264 // Get ESA from EEPROM - via the PP_IA registers
264 cyg_uint16 esa_word; 265 cyg_uint16 esa_word;
265 for (i = 0; i < sizeof(cpd->esa); i += 2) { 266 for (i = 0; i < sizeof(cpd->esa); i += 2) {
267 #if(CYG_BYTEORDER == CYG_LSBFIRST)
266 esa_word = get_reg(base, PP_IA+i); 268 esa_word = get_reg(base, PP_IA+i);
267 cpd->esa[i] = (esa_word & 0xFF); 269 cpd->esa[i] = (esa_word & 0xFF);
268 cpd->esa[i+1] = (esa_word >> 8) & 0xFF; 270 cpd->esa[i+1] = (esa_word >> 8) & 0xFF;
271 #elif(CYG_BYTEORDER == CYG_MSBFIRST)
272 esa_word = get_reg(base, PP_IA+CYG_SWAP16(i));
273 cpd->esa[i+1] = (esa_word & 0xFF);
274 cpd->esa[i] = (esa_word >> 8) & 0xFF;
275 #else
276 # error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
277 #endif
269 } 278 }
270 esa_configured = true; 279 esa_configured = true;
271 } 280 }
272 if (!esa_configured) { 281 if (!esa_configured) {
273 # if DEBUG & 8 282 # if DEBUG & 8
276 return false; 285 return false;
277 } 286 }
278 287
279 // Tell the chip what ESA to use 288 // Tell the chip what ESA to use
280 for (i = 0; i < sizeof(cpd->esa); i += 2) { 289 for (i = 0; i < sizeof(cpd->esa); i += 2) {
290 #if(CYG_BYTEORDER == CYG_LSBFIRST)
281 put_reg(base, PP_IA+i, cpd->esa[i] | (cpd->esa[i+1] << 8)); 291 put_reg(base, PP_IA+i, cpd->esa[i] | (cpd->esa[i+1] << 8));
292 #elif(CYG_BYTEORDER == CYG_MSBFIRST)
293 put_reg(base, PP_IA+CYG_SWAP16(i), cpd->esa[i+1] | (cpd->esa[i] << 8));
294 #endif
282 } 295 }
283 // Set logical address mask 296 // Set logical address mask
284 for (i = 0; i < 8; i += 2) { 297 for (i = 0; i < 8; i += 2) {
298 #if(CYG_BYTEORDER == CYG_LSBFIRST)
285 put_reg(base, PP_LAF+i, 0xFFFF); 299 put_reg(base, PP_LAF+i, 0xFFFF);
300 #elif(CYG_BYTEORDER == CYG_MSBFIRST)
301 put_reg(base, PP_LAF+CYG_SWAP16(i), 0xFFFF);
302 #endif
286 } 303 }
287 # if DEBUG & 8 304 # if DEBUG & 8
288 diag_printf("ESA %02x:%02x:%02x:%02x:%02x:%02x\n", 305 diag_printf("ESA %02x:%02x:%02x:%02x:%02x:%02x\n",
289 cpd->esa[0], cpd->esa[1], cpd->esa[2], 306 cpd->esa[0], cpd->esa[1], cpd->esa[2],
290 cpd->esa[3], cpd->esa[4], cpd->esa[5]); 307 cpd->esa[3], cpd->esa[4], cpd->esa[5]);
417 cpd->txbusy = true; 434 cpd->txbusy = true;
418 cpd->txkey = key; 435 cpd->txkey = key;
419 #ifdef CYGPKG_KERNEL 436 #ifdef CYGPKG_KERNEL
420 cpd->txstart = cyg_current_time(); 437 cpd->txstart = cyg_current_time();
421 #endif 438 #endif
439
422 // Start the xmit sequence 440 // Start the xmit sequence
423 441 #if(CYG_BYTEORDER == CYG_MSBFIRST)
442 total_len = CYG_SWAP16(total_len);
443 #endif
444
424 // The hardware indicates that there are options as to when the actual 445 // The hardware indicates that there are options as to when the actual
425 // packet transmission will start wrt moving of data into the transmit 446 // packet transmission will start wrt moving of data into the transmit
426 // buffer. However, impirical results seem to indicate that if the 447 // buffer. However, impirical results seem to indicate that if the
427 // packet is large and transmission is allowed to start before the 448 // packet is large and transmission is allowed to start before the
428 // entire packet has been pushed into the buffer, the hardware gets 449 // entire packet has been pushed into the buffer, the hardware gets
449 len = sg_list[i].len; 470 len = sg_list[i].len;
450 471
451 if (len > 0) { 472 if (len > 0) {
452 /* Finish the last word. */ 473 /* Finish the last word. */
453 if (odd_byte) { 474 if (odd_byte) {
475 // Add data to the most significant byte
476 #if(CYG_BYTEORDER == CYG_LSBFIRST)
454 saved_data |= ((cyg_uint16)*data++) << 8; 477 saved_data |= ((cyg_uint16)*data++) << 8;
478 #elif(CYG_BYTEORDER == CYG_MSBFIRST)
479 saved_data = ((cyg_uint16)*data++) | (saved_data << 8);
480 #endif
455 HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data); 481 HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data);
456 len--; 482 len--;
457 odd_byte = false; 483 odd_byte = false;
458 } 484 }
459 /* Output contiguous words. */ 485 if ((CYG_ADDRESS)data & 0x1 == 0) {
460 sdata = (cyg_uint16 *)data; 486 /* Aligned on 16-bit boundary, so output contiguous words. */
461 while (len > 1) { 487 sdata = (cyg_uint16 *)data;
462 HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, *sdata++); 488 while (len > 1) {
463 len -= sizeof(cyg_uint16); 489 HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, *sdata++);
490 len -= sizeof(cyg_uint16);
491 }
492 data = (cyg_uint8 *)sdata;
493 } else {
494 /* Not 16-bit aligned, so byte copy */
495 while (len > 1) {
496 saved_data = (cyg_uint16)*data++; // reuse saved_data
497 #if CYG_BYTEORDER == CYG_MSBFIRST
498 saved_data = ((cyg_uint16)*data++) | (saved_data << 8);
499 #else
500 saved_data |= ((cyg_uint16)*data++) << 8;
501 #endif
502 HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data);
503 len -= sizeof(cyg_uint16);
504 }
464 } 505 }
465 /* Save last byte, if necessary. */ 506 /* Save last byte, if necessary. */
466 if (len == 1) { 507 if (len == 1) {
467 data = (cyg_uint8 *)sdata;
468 saved_data = (cyg_uint16)*data; 508 saved_data = (cyg_uint16)*data;
469 odd_byte = true; 509 odd_byte = true;
470 } 510 }
471 } 511 }
472 } 512 }
487 cyg_addrword_t base = cpd->base; 527 cyg_addrword_t base = cpd->base;
488 cyg_uint16 stat, len; 528 cyg_uint16 stat, len;
489 529
490 HAL_READ_UINT16(base+CS8900A_RTDATA, stat); 530 HAL_READ_UINT16(base+CS8900A_RTDATA, stat);
491 HAL_READ_UINT16(base+CS8900A_RTDATA, len); 531 HAL_READ_UINT16(base+CS8900A_RTDATA, len);
532
533 #if(CYG_BYTEORDER == CYG_MSBFIRST)
534 len = CYG_SWAP16(len);
535 #endif
536
492 #ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG 537 #ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
493 if (cyg_io_eth_net_debug) { 538 if (cyg_io_eth_net_debug) {
494 diag_printf("RxEvent - stat: %x, len: %d\n", stat, len); 539 diag_printf("RxEvent - stat: %x, len: %d\n", stat, len);
495 } 540 }
496 #endif 541 #endif
520 *data++ = val; 565 *data++ = val;
521 } 566 }
522 mlen -= sizeof(*data); 567 mlen -= sizeof(*data);
523 } 568 }
524 if (mlen) { 569 if (mlen) {
525 // Fetch last odd byte 570 HAL_READ_UINT16(base+CS8900A_RTDATA, val);
526 HAL_READ_UINT16(base+CS8900A_RTDATA, cval); 571 #if(CYG_BYTEORDER == CYG_LSBFIRST)
527 cval &= 0xFF; 572 // last odd byte will be in the LSB
573 cval = (cyg_uint8)(val);
574 #elif(CYG_BYTEORDER == CYG_MSBFIRST)
575 // last odd byte will be in the MSB
576 cval = (cyg_uint8)(val >> 8);
577 #endif
578 cval &= 0xff;
528 if ((cp = (cyg_uint8 *)data) != 0) { 579 if ((cp = (cyg_uint8 *)data) != 0) {
529 *cp = cval; 580 *cp = cval;
530 } 581 }
531 } 582 }
532 } 583 }