00001 /* 00002 * Copyright (C) 2002-2003 by Call Direct Cellular Solutions Pty. Ltd. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. All advertising materials mentioning features or use of this 00014 * software must display the following acknowledgement: 00015 * 00016 * This product includes software developed by Call Direct Cellular Solutions Pty. Ltd. 00017 * and its contributors. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY CALL DIRECT CELLULAR SOLUTIONS AND CONTRIBUTORS 00020 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00021 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00022 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CALL DIRECT 00023 * CELLULAR SOLUTIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00024 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00025 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00026 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00027 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00028 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00029 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00030 * SUCH DAMAGE. 00031 * 00032 * For additional information see http://www.calldirect.com.au/ 00033 * 00034 * - 00035 * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved. 00036 * 00037 * Redistribution and use in source and binary forms, with or without 00038 * modification, are permitted provided that the following conditions 00039 * are met: 00040 * 00041 * 1. Redistributions of source code must retain the above copyright 00042 * notice, this list of conditions and the following disclaimer. 00043 * 2. Redistributions in binary form must reproduce the above copyright 00044 * notice, this list of conditions and the following disclaimer in the 00045 * documentation and/or other materials provided with the distribution. 00046 * 3. All advertising materials mentioning features or use of this 00047 * software must display the following acknowledgement: 00048 * 00049 * This product includes software developed by egnite Software GmbH 00050 * and its contributors. 00051 * 00052 * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS 00053 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00054 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00055 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE 00056 * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00057 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00058 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00059 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00060 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00061 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00062 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00063 * SUCH DAMAGE. 00064 * 00065 * For additional information see http://www.ethernut.de/ 00066 * 00067 * - 00068 * Portions Copyright (C) 2000 David J. Hudson <dave@humbug.demon.co.uk> 00069 * 00070 * This file is distributed in the hope that it will be useful, but WITHOUT 00071 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00072 * FITNESS FOR A PARTICULAR PURPOSE. 00073 * 00074 * You can redistribute this file and/or modify it under the terms of the GNU 00075 * General Public License (GPL) as published by the Free Software Foundation; 00076 * either version 2 of the License, or (at your discretion) any later version. 00077 * See the accompanying file "copying-gpl.txt" for more details. 00078 * 00079 * As a special exception to the GPL, permission is granted for additional 00080 * uses of the text contained in this file. See the accompanying file 00081 * "copying-liquorice.txt" for details. 00082 * - 00083 * Portions Copyright (c) 1983, 1993 by 00084 * The Regents of the University of California. All rights reserved. 00085 * 00086 * Redistribution and use in source and binary forms, with or without 00087 * modification, are permitted provided that the following conditions 00088 * are met: 00089 * 1. Redistributions of source code must retain the above copyright 00090 * notice, this list of conditions and the following disclaimer. 00091 * 2. Redistributions in binary form must reproduce the above copyright 00092 * notice, this list of conditions and the following disclaimer in the 00093 * documentation and/or other materials provided with the distribution. 00094 * 3. All advertising materials mentioning features or use of this software 00095 * must display the following acknowledgement: 00096 * This product includes software developed by the University of 00097 * California, Berkeley and its contributors. 00098 * 4. Neither the name of the University nor the names of its contributors 00099 * may be used to endorse or promote products derived from this software 00100 * without specific prior written permission. 00101 * 00102 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00103 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00104 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00105 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00106 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00107 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00108 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00109 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00110 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00111 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00112 * SUCH DAMAGE. 00113 * - 00114 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 00115 * 00116 * Permission to use, copy, modify, and distribute this software for any 00117 * purpose with or without fee is hereby granted, provided that the above 00118 * copyright notice and this permission notice appear in all copies, and that 00119 * the name of Digital Equipment Corporation not be used in advertising or 00120 * publicity pertaining to distribution of the document or software without 00121 * specific, written prior permission. 00122 * 00123 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 00124 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 00125 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 00126 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 00127 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 00128 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 00129 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 00130 * SOFTWARE. 00131 */ 00132 00133 /* 00134 * $Log: cs8900.c,v $ 00135 * Revision 1.2 2006/10/08 16:48:07 haraldkipp 00136 * Documentation fixed 00137 * 00138 * Revision 1.1 2005/07/26 18:02:27 haraldkipp 00139 * Moved from dev. 00140 * 00141 * Revision 1.9 2005/04/30 16:42:41 chaac 00142 * Fixed bug in handling of NUTDEBUG. Added include for cfg/os.h. If NUTDEBUG 00143 * is defined in NutConf, it will make effect where it is used. 00144 * 00145 * Revision 1.8 2004/05/26 09:40:30 olereinhardt 00146 * Changed reading of packet length / receive status to be compatible with 00147 * newer AVRGCC versions. (Need to read high byte first!) 00148 * 00149 * Added software reset / wakeup routine to init code. (only avalilable in new code) 00150 * 00151 * Revision 1.7 2004/05/25 11:39:47 olereinhardt 00152 * Define NUT_CS8900_OLD to get the old functionality back again 00153 * 00154 * Revision 1.6 2004/05/24 17:09:17 olereinhardt 00155 * Changed base address handling in cs8900.c and moved cs8900.h to /include/dev 00156 * Base address can now be passed to the nic driver by NutRegisterDevice. 00157 * Removed some Assembler code in cs8900.c 00158 * 00159 * Added some databus waitstate settings for the upper half of the address space in os/arch/avr_nutinit.c. Now three waitstates are default for 0x8000-0xFFFF 00160 * 00161 * Added terminal device driver for hd44780 compatible LCD displays directly 00162 * connected to the memory bus (memory mapped). See hd44780.c for more information. 00163 * Therefore some minor changed in include/dev/term.h and dev/term.c are needet to 00164 * pass a base address to the lcd driver. 00165 * 00166 * Revision 1.5 2004/03/18 14:06:52 haraldkipp 00167 * Deprecated header file replaced 00168 * 00169 * Revision 1.4 2003/10/13 10:13:49 haraldkipp 00170 * First release 00171 * 00172 * Revision 1.3 2003/08/05 20:11:30 haraldkipp 00173 * Removed from ICCAVR compilation 00174 * 00175 * Revision 1.2 2003/07/20 20:07:38 haraldkipp 00176 * Conflicting Ethernet driver routine names solved. 00177 * 00178 * Revision 1.1 2003/07/20 16:37:21 haraldkipp 00179 * CrystalTek 8900A driver added. 00180 * 00181 * 00182 * Revision 1.0 2002/03/28 MJC CDCS 00183 * Created 00184 * 00185 * Revision 1.1 2003/03/25 MJC CDCS 00186 * Modified behaviour when transmit buffer space unavailable 00187 * 00188 */ 00189 00190 /* Not ported. */ 00191 #ifdef __GNUC__ 00192 00193 #include <cfg/os.h> 00194 #include <string.h> 00195 #include <avr/interrupt.h> 00196 00197 #include <sys/heap.h> 00198 #include <sys/thread.h> 00199 #include <sys/event.h> 00200 #include <sys/timer.h> 00201 #include <sys/confnet.h> 00202 00203 #include <dev/nicrtl.h> 00204 #include <netinet/if_ether.h> 00205 #include <net/ether.h> 00206 #include <net/if_var.h> 00207 #include <netinet/ip.h> 00208 00209 #include <dev/irqreg.h> 00210 #include "cs8900.h" 00211 00212 #ifdef NUTDEBUG 00213 #include <sys/osdebug.h> 00214 #include <net/netdebug.h> 00215 #endif 00216 00221 00222 00223 // Ethernet flags byte 00224 // Bit 0 = transmit byte flag 00225 u_char cs_flags; 00226 volatile u_short cs_base = 0x0000; 00227 00228 00229 void CSWrite16(u_short addr, u_short data) 00230 { 00231 u_short *p; 00232 00233 p = (u_short *) addr; 00234 cli(); 00235 *p = data; 00236 sei(); 00237 } 00238 00239 void CSWritePP16(u_short addr, u_short data) 00240 { 00241 u_short *p; 00242 00243 cli(); 00244 p = (u_short *) CS_PP_PTR; 00245 *p = addr; 00246 00247 CSWrite16(CS_PP_DATA0, data); 00248 00249 return; 00250 } 00251 00252 u_short CSRead16(u_short addr) 00253 { 00254 u_short *p; 00255 u_short d; 00256 00257 cli(); 00258 p = (u_short *) addr; 00259 d = *p; 00260 sei(); 00261 00262 return d; 00263 } 00264 00265 u_short CSReadPP16(u_short addr) 00266 { 00267 u_short *p; 00268 00269 cli(); 00270 p = (u_short *) CS_PP_PTR; 00271 *p = addr; 00272 00273 return CSRead16(CS_PP_DATA0); 00274 } 00275 00276 u_long CSReadPP32(u_int addr) 00277 { 00278 u_long l; 00279 u_long *p; 00280 00281 cli(); 00282 p = (u_long *) CS_PP_PTR; 00283 *p = addr; 00284 p = (u_long *) CS_PP_DATA0; 00285 l = *p; 00286 sei(); 00287 00288 return l; 00289 } 00290 00291 00292 00293 void CSBeginFrame(void) 00294 { 00295 cs_flags &= ~1; 00296 } 00297 00298 void CSEndFrame(void) 00299 { 00300 u_char *p; 00301 00302 cli(); 00303 p = (u_char *) CS_DATA_P0 + 1; 00304 sei(); 00305 00306 // If odd number of bytes in packet pad it out 00307 if (cs_flags & 1) 00308 p = 0; 00309 } 00310 00311 void CSWriteFrameByte(u_char data) 00312 { 00313 u_char *p; 00314 00315 if (cs_flags & 1) 00316 p = (u_char *) CS_DATA_P0 + 1; 00317 else 00318 p = (u_char *) CS_DATA_P0; 00319 00320 *p = data; 00321 cs_flags ^= 1; 00322 } 00323 00324 static int CSEthPutPacket(NUTDEVICE * dev, NETBUF * nb) 00325 { 00326 u_short i; 00327 u_short sz; 00328 u_char *p; 00329 NICINFO *ni; 00330 00331 ni = (NICINFO *) dev->dev_dcb; 00332 00333 // 00334 // Calculate the number of bytes to be send. Do not 00335 // send packets larger than 1536 bytes. 00336 // 00337 sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz; 00338 if (sz >= 0x600) { 00339 NutNetBufFree(nb); 00340 return -1; 00341 } 00342 #if 0 00343 if (tcp_trace) { 00344 NutPrintFormat_P(dev_debug, PSTR("[ETHTX-%u]\r\n"), sz); 00345 NutPrintFlush(dev_debug); 00346 } 00347 #endif 00348 00349 // Start transmission after entire frame is loaded into CS8900 00350 CSWrite16(CS_TX_CMD_I, 0xC0); 00351 // Set frame size 00352 CSWrite16(CS_TX_LEN_I, sz); 00353 00354 // Wait for buffer space, but only for a while (200ms) 00355 // If the cable is disconnected this will never become true 00356 // If we don't get the go ahead within 200ms return 0 (Sucess) 00357 // And let the upper layers deal with re-transmission 00358 // If we return failure TCP sockets will close straight away which probably 00359 // isn't the correct behaviour 00360 i = 0; 00361 while ((CSReadPP16(CS_BUS_STAT) & 0x0100) == 0) { 00362 i++; 00363 if (i > 20) 00364 return 0; 00365 NutSleep(10); 00366 } 00367 00368 // 00369 // Transfer ethernet physical header. 00370 // 00371 CSBeginFrame(); 00372 00373 p = nb->nb_dl.vp; 00374 for (i = 0; i < nb->nb_dl.sz; i++) { 00375 CSWriteFrameByte(*p++); 00376 } 00377 00378 00379 p = nb->nb_nw.vp; 00380 for (i = 0; i < nb->nb_nw.sz; i++) { 00381 CSWriteFrameByte(*p++); 00382 } 00383 00384 p = nb->nb_tp.vp; 00385 for (i = 0; i < nb->nb_tp.sz; i++) { 00386 CSWriteFrameByte(*p++); 00387 } 00388 00389 p = nb->nb_ap.vp; 00390 for (i = 0; i < nb->nb_ap.sz; i++) { 00391 CSWriteFrameByte(*p++); 00392 } 00393 00394 CSEndFrame(); 00395 00396 return 0; 00397 } 00398 00413 int CSNicOutput(NUTDEVICE * dev, NETBUF * nb) 00414 { 00415 int rc = -1; 00416 NICINFO *ni; 00417 00418 ni = (NICINFO *) dev->dev_dcb; 00419 00420 #if 0 00421 if (tcp_trace) { 00422 NutPrintFormat_P(dev_debug, PSTR("Enter EthOutput\r\n")); 00423 NutPrintFlush(dev_debug); 00424 } 00425 #endif 00426 00427 if ((rc = CSEthPutPacket(dev, nb)) == 0) 00428 ni->ni_tx_packets++; 00429 00430 return rc; 00431 } 00432 00433 00434 00435 00436 00444 THREAD(CSNICrx, arg) 00445 { 00446 NUTDEVICE *dev; 00447 IFNET *ifn; 00448 NICINFO *ni; 00449 NETBUF *nb; 00450 u_char *p; 00451 u_char *q; 00452 u_short i, m; 00453 volatile u_short l; 00454 00455 dev = arg; 00456 ifn = (IFNET *) dev->dev_icb; 00457 ni = (NICINFO *) dev->dev_dcb; 00458 00459 #if 0 00460 if (tcp_trace) { 00461 NutPrintFormat_P(dev_debug, PSTR("Enter ETHReceive\r\n")); 00462 NutPrintFlush(dev_debug); 00463 } 00464 #endif 00465 00466 l = 0; 00467 00468 NutThreadSetPriority(8); 00469 for (;;) { 00470 while ((CSReadPP16(CS_RX_EVENT) & 0x0100) == 0) { 00471 NutSleep(10); 00472 } 00473 00474 #ifdef NUT_CS8900_OLD 00475 // Get the RxStatus But don't let the compiler do any optomisation 00476 asm volatile ("lds __tmp_reg__, %3" "\n\t" 00477 "mov %B0, __tmp_reg__" "\n\t" "lds __tmp_reg__, %2" "\n\t" "mov %A0, __tmp_reg__" "\n\t":"=r" (l) 00478 :"0"(l), "n"((unsigned short) (CS_DATA_P0)), "n"((unsigned short) (CS_DATA_P0 + 1)) 00479 ); 00480 00481 // Get the Packet Length But don't let the compiler do any optomisation 00482 asm volatile ("lds __tmp_reg__, %3" "\n\t" 00483 "mov %B0, __tmp_reg__" "\n\t" "lds __tmp_reg__, %2" "\n\t" "mov %A0, __tmp_reg__" "\n\t":"=r" (l) 00484 :"0"(l), "n"((unsigned short) (CS_DATA_P0)), "n"((unsigned short) (CS_DATA_P0 + 1)) 00485 ); 00486 #else 00487 00488 l = *(u_char *) (CS_DATA_P0 + 1) << 8 | *(u_char *) (CS_DATA_P0); 00489 l = *(u_char *) (CS_DATA_P0 + 1) << 8 | *(u_char *) (CS_DATA_P0); 00490 #endif 00491 //NutPrintFormat_P(dev_debug,PSTR("RxLength = %x \r\n"), l); 00492 //NutPrintFlush(dev_debug); 00493 00494 // Account for odd length packets 00495 if (l & 1) 00496 m = l - 1; 00497 else 00498 m = l; 00499 00500 00501 nb = NutNetBufAlloc(0, NBAF_DATALINK, l); 00502 if (nb) { 00503 q = nb->nb_dl.vp; 00504 for (i = 0; i < m; i += 2) { 00505 p = (u_char *) CS_DATA_P0; 00506 *q++ = *p; 00507 p = (u_char *) CS_DATA_P0 + 1; 00508 *q++ = *p; 00509 } 00510 00511 // Odd length packets 00512 if (m != l) { 00513 p = (u_char *) CS_DATA_P0; 00514 *q++ = *p; 00515 00516 p = (u_char *) CS_DATA_P0 + 1; 00517 m = *p; 00518 } 00519 ni->ni_rx_packets++; 00520 (*ifn->if_recv) (dev, nb); 00521 } 00522 } 00523 } 00524 00525 void CSSoftwareWakeup(void) 00526 { 00527 volatile u_short *p; 00528 00529 p = (u_short *) CS_PP_PTR; 00530 *p = CS_SELF_CTRL; 00531 00532 NutDelay(10); 00533 } 00534 00535 00536 void CSSoftwareReset(void) 00537 { 00538 volatile u_short *p; 00539 00540 p = (u_short *) CS_PP_PTR; 00541 *p = CS_SELF_CTRL; 00542 p = (u_short *) CS_DATA_P0; 00543 *p = 0x0040; 00544 } 00545 00546 00557 int CSNicInit(NUTDEVICE * dev) 00558 { 00559 u_short i; 00560 u_short j; 00561 IFNET *ifn; 00562 NICINFO *ni; 00563 00564 #if 0 00565 if (tcp_trace) { 00566 NutPrintFormat_P(dev_debug, PSTR("Enter NicInit \r\n")); 00567 NutPrintFlush(dev_debug); 00568 } 00569 #endif 00570 cs_base = dev->dev_base; 00571 00572 if (confnet.cd_size == 0) 00573 NutNetLoadConfig(dev->dev_name); 00574 00575 ifn = dev->dev_icb; 00576 memcpy(ifn->if_mac, confnet.cdn_mac, 6); 00577 memset(dev->dev_dcb, 0, sizeof(NICINFO)); 00578 ni = (NICINFO *) dev->dev_dcb; 00579 00580 // Take CS8900 out of reset and wait for internal reset to complete 00581 #ifdef NUT_CS8900_OLD 00582 outp(inp(PORTD) & ~RESETE, PORTD); 00583 #else 00584 CSSoftwareWakeup(); 00585 CSSoftwareReset(); 00586 #endif 00587 00588 NutDelay(100); 00589 00590 // Check for presence 00591 if (CSReadPP16(CS_PROD_ID) != 0x630E) 00592 return -1; 00593 00594 // 00595 // Copy our MAC address to the NIC 00596 // 00597 for (i = 0; i < 6; i += 2) { 00598 j = ifn->if_mac[i] << 8; 00599 j |= ifn->if_mac[i + 1]; 00600 CSWritePP16(CS_IEEE_ADDR + i, j); 00601 j = CSReadPP16(CS_IEEE_ADDR + i); 00602 #if 0 00603 if (tcp_trace) { 00604 NutPrintFormat_P(dev_debug, PSTR("ADDR = %x\r\n"), j); 00605 NutPrintFlush(dev_debug); 00606 } 00607 #endif 00608 } 00609 00610 // 00611 // Enable the Transmitter and Receiver 00612 // 00613 CSWritePP16(CS_LINE_CTRL, 0x00C0); 00614 //i = CSReadPP16(CS_LINE_CTRL); 00615 //NutPrintFormat_P(dev_debug,PSTR("CS_LINE_CTRL = %x\r\n"), i); 00616 00617 CSWritePP16(CS_RX_CTL, 0x0F40); 00618 //i = CSReadPP16(CS_RX_CTL); 00619 //NutPrintFormat_P(dev_debug,PSTR("CS_RX_CTL = %x\r\n"), i); 00620 00621 // 00622 // Start receiver thread 00623 // 00624 NutThreadCreate("csnicrx", CSNICrx, dev, 500); 00625 00626 return 0; 00627 } 00628 00630 #else 00631 void keep_icc_happy(void) 00632 { 00633 } 00634 00635 #endif