/[gxemul]/trunk/src/devices/dev_ether.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/devices/dev_ether.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_ether.c,v 1.9 2005/11/13 00:14:08 debug Exp $   *  $Id: dev_ether.c,v 1.19 2007/06/15 19:11:15 debug Exp $
29     *
30     *  COMMENT: A simple ethernet controller, for the test machines
31   *   *
32   *  Basic "ethernet" network device. This is a simple test device which can   *  Basic "ethernet" network device. This is a simple test device which can
33   *  be used to send and receive packets to/from a simulated ethernet network.   *  be used to send and receive packets to/from a simulated ethernet network.
# Line 37  Line 39 
39    
40  #include "cpu.h"  #include "cpu.h"
41  #include "device.h"  #include "device.h"
 #include "devices.h"  
42  #include "emul.h"  #include "emul.h"
43  #include "machine.h"  #include "machine.h"
44  #include "memory.h"  #include "memory.h"
45  #include "misc.h"  #include "misc.h"
46  #include "net.h"  #include "net.h"
47    
48    #include "testmachine/dev_ether.h"
49    
 #define DEV_ETHER_MAXBUFLEN     16384  
 #define DEV_ETHER_TICK_SHIFT    14  
50    
51  #define STATUS_RECEIVED         0x01  #define DEV_ETHER_TICK_SHIFT    14
 #define STATUS_MORE_AVAIL       0x02  
52    
53  struct ether_data {  struct ether_data {
54          unsigned char   buf[DEV_ETHER_MAXBUFLEN];          unsigned char           buf[DEV_ETHER_BUFFER_SIZE];
55          unsigned char   mac[6];          unsigned char           mac[6];
56    
57          int             status;          int                     status;
58          int             packet_len;          int                     packet_len;
59    
60          int             irq_nr;          struct interrupt        irq;
61  };  };
62    
63    
64  /*  DEVICE_TICK(ether)
  *  dev_ether_tick():  
  */  
 void dev_ether_tick(struct cpu *cpu, void *extra)  
65  {    {  
66          struct ether_data *d = (struct ether_data *) extra;          struct ether_data *d = extra;
67          int r = 0;          int r = 0;
68    
69          d->status &= ~STATUS_MORE_AVAIL;          d->status &= ~DEV_ETHER_STATUS_MORE_PACKETS_AVAILABLE;
70          if (cpu->machine->emul->net != NULL)          if (cpu->machine->emul->net != NULL)
71                  r = net_ethernet_rx_avail(cpu->machine->emul->net, d);                  r = net_ethernet_rx_avail(cpu->machine->emul->net, d);
72          if (r)          if (r)
73                  d->status |= STATUS_MORE_AVAIL;                  d->status |= DEV_ETHER_STATUS_MORE_PACKETS_AVAILABLE;
74    
75          if (d->status)          if (d->status)
76                  cpu_interrupt(cpu, d->irq_nr);                  INTERRUPT_ASSERT(d->irq);
77          else          else
78                  cpu_interrupt_ack(cpu, d->irq_nr);                  INTERRUPT_DEASSERT(d->irq);
79  }  }
80    
81    
82  /*  DEVICE_ACCESS(ether_buf)
  *  dev_ether_buf_access():  
  */  
 int dev_ether_buf_access(struct cpu *cpu, struct memory *mem,  
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
83  {  {
84          struct ether_data *d = (struct ether_data *) extra;          struct ether_data *d = extra;
85    
86          if (writeflag == MEM_WRITE)          if (writeflag == MEM_WRITE)
87                  memcpy(d->buf + relative_addr, data, len);                  memcpy(d->buf + relative_addr, data, len);
88          else          else
89                  memcpy(data, d->buf + relative_addr, len);                  memcpy(data, d->buf + relative_addr, len);
90    
91          return 1;          return 1;
92  }  }
93    
94    
95  /*  DEVICE_ACCESS(ether)
  *  dev_ether_access():  
  */  
 int dev_ether_access(struct cpu *cpu, struct memory *mem,  
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
96  {  {
97          struct ether_data *d = (struct ether_data *) extra;          struct ether_data *d = extra;
98          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
99          unsigned char *incoming_ptr;          unsigned char *incoming_ptr;
100          int incoming_len;          int incoming_len;
# Line 115  int dev_ether_access(struct cpu *cpu, st Line 102  int dev_ether_access(struct cpu *cpu, st
102          if (writeflag == MEM_WRITE)          if (writeflag == MEM_WRITE)
103                  idata = memory_readmax64(cpu, data, len);                  idata = memory_readmax64(cpu, data, len);
104    
105          switch (relative_addr) {          /*  Note: relative_addr + DEV_ETHER_BUFFER_SIZE to get the same
106          case 0x0000:              offsets as in the header file:  */
107    
108            switch (relative_addr + DEV_ETHER_BUFFER_SIZE) {
109    
110            case DEV_ETHER_STATUS:
111                  if (writeflag == MEM_READ) {                  if (writeflag == MEM_READ) {
112                          odata = d->status;                          odata = d->status;
113                          d->status = 0;                          d->status = 0;
114                          cpu_interrupt_ack(cpu, d->irq_nr);                          INTERRUPT_DEASSERT(d->irq);
115                  } else                  } else
116                          fatal("[ ether: WARNING: write to status ]\n");                          fatal("[ ether: WARNING: write to status ]\n");
117                  break;                  break;
118          case 0x0010:  
119            case DEV_ETHER_PACKETLENGTH:
120                  if (writeflag == MEM_READ)                  if (writeflag == MEM_READ)
121                          odata = d->packet_len;                          odata = d->packet_len;
122                  else {                  else {
# Line 133  int dev_ether_access(struct cpu *cpu, st Line 125  int dev_ether_access(struct cpu *cpu, st
125                                      " short (%i bytes) ]\n", (int)idata);                                      " short (%i bytes) ]\n", (int)idata);
126                                  idata = -1;                                  idata = -1;
127                          }                          }
128                          if (idata > DEV_ETHER_MAXBUFLEN) {                          if (idata > DEV_ETHER_BUFFER_SIZE) {
129                                  fatal("[ ether: ERROR: packet len too"                                  fatal("[ ether: ERROR: packet len too"
130                                      " large (%i bytes) ]\n", (int)idata);                                      " large (%i bytes) ]\n", (int)idata);
131                                  idata = DEV_ETHER_MAXBUFLEN;                                  idata = DEV_ETHER_BUFFER_SIZE;
132                          }                          }
133                          d->packet_len = idata;                          d->packet_len = idata;
134                  }                  }
135                  break;                  break;
136          case 0x0020:  
137                  if (writeflag == MEM_READ)          case DEV_ETHER_COMMAND:
138                    if (writeflag == MEM_READ) {
139                          fatal("[ ether: WARNING: read from command ]\n");                          fatal("[ ether: WARNING: read from command ]\n");
140                  else {                          break;
141                          switch (idata) {                  }
142                          case 0x00:              /*  Receive:  */  
143                                  if (cpu->machine->emul->net == NULL)                  /*  Write:  */
144                                          fatal("[ ether: RECEIVE but no "                  switch (idata) {
145                                              "net? ]\n");  
146                                  else {                  case DEV_ETHER_COMMAND_RX:      /*  Receive:  */
147                                          d->status &= ~STATUS_RECEIVED;                          if (cpu->machine->emul->net == NULL)
148                                          net_ethernet_rx(cpu->machine->emul->net,                                  fatal("[ ether: RECEIVE but no net? ]\n");
149                                              d, &incoming_ptr, &incoming_len);                          else {
150                                          if (incoming_ptr != NULL) {                                  d->status &= ~DEV_ETHER_STATUS_PACKET_RECEIVED;
151                                                  d->status |= STATUS_RECEIVED;                                  net_ethernet_rx(cpu->machine->emul->net,
152                                                  if (incoming_len >                                      d, &incoming_ptr, &incoming_len);
153                                                      DEV_ETHER_MAXBUFLEN)                                  if (incoming_ptr != NULL) {
154                                                          incoming_len =                                          d->status |=
155                                                              DEV_ETHER_MAXBUFLEN;                                              DEV_ETHER_STATUS_PACKET_RECEIVED;
156                                                  memcpy(d->buf, incoming_ptr,                                          if (incoming_len>DEV_ETHER_BUFFER_SIZE)
157                                                      incoming_len);                                                  incoming_len =
158                                                  free(incoming_ptr);                                                      DEV_ETHER_BUFFER_SIZE;
159                                                  d->packet_len = incoming_len;                                          memcpy(d->buf, incoming_ptr,
160                                          }                                              incoming_len);
161                                            free(incoming_ptr);
162                                            d->packet_len = incoming_len;
163                                  }                                  }
                                 dev_ether_tick(cpu, d);  
                                 break;  
                         case 0x01:              /*  Send  */  
                                 if (cpu->machine->emul->net == NULL)  
                                         fatal("[ ether: SEND but no net? ]\n");  
                                 else  
                                         net_ethernet_tx(cpu->machine->emul->net,  
                                             d, d->buf, d->packet_len);  
                                 d->status &= ~STATUS_RECEIVED;  
                                 dev_ether_tick(cpu, d);  
                                 break;  
                         default:fatal("[ ether: UNIMPLEMENTED command 0x"  
                                     "%02x ]\n", idata);  
                                 cpu->running = 0;  
164                          }                          }
165                            dev_ether_tick(cpu, d);
166                            break;
167    
168                    case DEV_ETHER_COMMAND_TX:      /*  Send  */
169                            if (cpu->machine->emul->net == NULL)
170                                    fatal("[ ether: SEND but no net? ]\n");
171                            else
172                                    net_ethernet_tx(cpu->machine->emul->net,
173                                        d, d->buf, d->packet_len);
174                            d->status &= ~DEV_ETHER_STATUS_PACKET_RECEIVED;
175                            dev_ether_tick(cpu, d);
176                            break;
177    
178                    default:fatal("[ ether: UNIMPLEMENTED command 0x"
179                                "%02x ]\n", idata);
180                            cpu->running = 0;
181                  }                  }
182                  break;                  break;
183    
184          default:if (writeflag == MEM_WRITE) {          default:if (writeflag == MEM_WRITE) {
185                          fatal("[ ether: unimplemented write to "                          fatal("[ ether: unimplemented write to "
186                              "offset 0x%x: data=0x%x ]\n", (int)                              "offset 0x%x: data=0x%x ]\n", (int)
# Line 200  int dev_ether_access(struct cpu *cpu, st Line 198  int dev_ether_access(struct cpu *cpu, st
198  }  }
199    
200    
201  /*  DEVINIT(ether)
  *  devinit_ether():  
  */  
 int devinit_ether(struct devinit *devinit)  
202  {  {
203          struct ether_data *d = malloc(sizeof(struct ether_data));          struct ether_data *d;
204          size_t nlen;          size_t nlen;
205          char *n1, *n2;          char *n1, *n2;
206          char tmp[50];          char tmp[50];
207    
208            CHECK_ALLOCATION(d = malloc(sizeof(struct ether_data)));
209            memset(d, 0, sizeof(struct ether_data));
210    
211          nlen = strlen(devinit->name) + 80;          nlen = strlen(devinit->name) + 80;
212          n1 = malloc(nlen);          CHECK_ALLOCATION(n1 = malloc(nlen));
213          n2 = malloc(nlen);          CHECK_ALLOCATION(n2 = malloc(nlen));
214    
215          if (d == NULL || n1 == NULL || n2 == NULL) {          INTERRUPT_CONNECT(devinit->interrupt_path, d->irq);
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
         memset(d, 0, sizeof(struct ether_data));  
         d->irq_nr = devinit->irq_nr;  
216    
217          net_generate_unique_mac(devinit->machine, d->mac);          net_generate_unique_mac(devinit->machine, d->mac);
218          snprintf(tmp, sizeof(tmp), "%02x:%02x:%02x:%02x:%02x:%02x",          snprintf(tmp, sizeof(tmp), "%02x:%02x:%02x:%02x:%02x:%02x",
# Line 228  int devinit_ether(struct devinit *devini Line 221  int devinit_ether(struct devinit *devini
221          snprintf(n1, nlen, "%s [%s]", devinit->name, tmp);          snprintf(n1, nlen, "%s [%s]", devinit->name, tmp);
222          snprintf(n2, nlen, "%s [%s, control]", devinit->name, tmp);          snprintf(n2, nlen, "%s [%s, control]", devinit->name, tmp);
223    
224          memory_device_register(devinit->machine->memory, n1,          memory_device_register(devinit->machine->memory, n1, devinit->addr,
225              devinit->addr, DEV_ETHER_MAXBUFLEN, dev_ether_buf_access, (void *)d,              DEV_ETHER_BUFFER_SIZE, dev_ether_buf_access, (void *)d,
226              DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK |              DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK |
227              DM_READS_HAVE_NO_SIDE_EFFECTS, d->buf);              DM_READS_HAVE_NO_SIDE_EFFECTS, d->buf);
228          memory_device_register(devinit->machine->memory, n2,          memory_device_register(devinit->machine->memory, n2,
229              devinit->addr + DEV_ETHER_MAXBUFLEN,              devinit->addr + DEV_ETHER_BUFFER_SIZE,
230              DEV_ETHER_LENGTH-DEV_ETHER_MAXBUFLEN, dev_ether_access, (void *)d,              DEV_ETHER_LENGTH-DEV_ETHER_BUFFER_SIZE, dev_ether_access, (void *)d,
231              DM_DEFAULT, NULL);              DM_DEFAULT, NULL);
232    
233          net_add_nic(devinit->machine->emul->net, d, d->mac);          net_add_nic(devinit->machine->emul->net, d, d->mac);

Legend:
Removed from v.20  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26