/[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 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2006  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.15 2006/10/07 00:36:29 debug Exp $
29   *   *
30   *  Basic "ethernet" network device. This is a simple test device which can   *  Basic "ethernet" network device. This is a simple test device which can
31   *  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 37 
37    
38  #include "cpu.h"  #include "cpu.h"
39  #include "device.h"  #include "device.h"
 #include "devices.h"  
40  #include "emul.h"  #include "emul.h"
41  #include "machine.h"  #include "machine.h"
42  #include "memory.h"  #include "memory.h"
43  #include "misc.h"  #include "misc.h"
44  #include "net.h"  #include "net.h"
45    
46    #include "testmachine/dev_ether.h"
47    
 #define DEV_ETHER_MAXBUFLEN     16384  
 #define DEV_ETHER_TICK_SHIFT    14  
48    
49  #define STATUS_RECEIVED         0x01  #define DEV_ETHER_TICK_SHIFT    14
 #define STATUS_MORE_AVAIL       0x02  
50    
51  struct ether_data {  struct ether_data {
52          unsigned char   buf[DEV_ETHER_MAXBUFLEN];          unsigned char   buf[DEV_ETHER_BUFFER_SIZE];
53          unsigned char   mac[6];          unsigned char   mac[6];
54    
55          int             status;          int             status;
# Line 62  struct ether_data { Line 59  struct ether_data {
59  };  };
60    
61    
62  /*  DEVICE_TICK(ether)
  *  dev_ether_tick():  
  */  
 void dev_ether_tick(struct cpu *cpu, void *extra)  
63  {    {  
64          struct ether_data *d = (struct ether_data *) extra;          struct ether_data *d = (struct ether_data *) extra;
65          int r = 0;          int r = 0;
66    
67          d->status &= ~STATUS_MORE_AVAIL;          d->status &= ~DEV_ETHER_STATUS_MORE_PACKETS_AVAILABLE;
68          if (cpu->machine->emul->net != NULL)          if (cpu->machine->emul->net != NULL)
69                  r = net_ethernet_rx_avail(cpu->machine->emul->net, d);                  r = net_ethernet_rx_avail(cpu->machine->emul->net, d);
70          if (r)          if (r)
71                  d->status |= STATUS_MORE_AVAIL;                  d->status |= DEV_ETHER_STATUS_MORE_PACKETS_AVAILABLE;
72    
73          if (d->status)          if (d->status)
74                  cpu_interrupt(cpu, d->irq_nr);                  cpu_interrupt(cpu, d->irq_nr);
# Line 83  void dev_ether_tick(struct cpu *cpu, voi Line 77  void dev_ether_tick(struct cpu *cpu, voi
77  }  }
78    
79    
80  /*  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)  
81  {  {
82          struct ether_data *d = (struct ether_data *) extra;          struct ether_data *d = (struct ether_data *) extra;
83    
# Line 100  int dev_ether_buf_access(struct cpu *cpu Line 89  int dev_ether_buf_access(struct cpu *cpu
89  }  }
90    
91    
92  /*  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)  
93  {  {
94          struct ether_data *d = (struct ether_data *) extra;          struct ether_data *d = (struct ether_data *) extra;
95          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
# Line 115  int dev_ether_access(struct cpu *cpu, st Line 99  int dev_ether_access(struct cpu *cpu, st
99          if (writeflag == MEM_WRITE)          if (writeflag == MEM_WRITE)
100                  idata = memory_readmax64(cpu, data, len);                  idata = memory_readmax64(cpu, data, len);
101    
102          switch (relative_addr) {          /*  Note: relative_addr + DEV_ETHER_BUFFER_SIZE to get the same
103          case 0x0000:              offsets as in the header file:  */
104    
105            switch (relative_addr + DEV_ETHER_BUFFER_SIZE) {
106    
107            case DEV_ETHER_STATUS:
108                  if (writeflag == MEM_READ) {                  if (writeflag == MEM_READ) {
109                          odata = d->status;                          odata = d->status;
110                          d->status = 0;                          d->status = 0;
# Line 124  int dev_ether_access(struct cpu *cpu, st Line 112  int dev_ether_access(struct cpu *cpu, st
112                  } else                  } else
113                          fatal("[ ether: WARNING: write to status ]\n");                          fatal("[ ether: WARNING: write to status ]\n");
114                  break;                  break;
115          case 0x0010:  
116            case DEV_ETHER_PACKETLENGTH:
117                  if (writeflag == MEM_READ)                  if (writeflag == MEM_READ)
118                          odata = d->packet_len;                          odata = d->packet_len;
119                  else {                  else {
# Line 133  int dev_ether_access(struct cpu *cpu, st Line 122  int dev_ether_access(struct cpu *cpu, st
122                                      " short (%i bytes) ]\n", (int)idata);                                      " short (%i bytes) ]\n", (int)idata);
123                                  idata = -1;                                  idata = -1;
124                          }                          }
125                          if (idata > DEV_ETHER_MAXBUFLEN) {                          if (idata > DEV_ETHER_BUFFER_SIZE) {
126                                  fatal("[ ether: ERROR: packet len too"                                  fatal("[ ether: ERROR: packet len too"
127                                      " large (%i bytes) ]\n", (int)idata);                                      " large (%i bytes) ]\n", (int)idata);
128                                  idata = DEV_ETHER_MAXBUFLEN;                                  idata = DEV_ETHER_BUFFER_SIZE;
129                          }                          }
130                          d->packet_len = idata;                          d->packet_len = idata;
131                  }                  }
132                  break;                  break;
133          case 0x0020:  
134                  if (writeflag == MEM_READ)          case DEV_ETHER_COMMAND:
135                    if (writeflag == MEM_READ) {
136                          fatal("[ ether: WARNING: read from command ]\n");                          fatal("[ ether: WARNING: read from command ]\n");
137                  else {                          break;
138                          switch (idata) {                  }
139                          case 0x00:              /*  Receive:  */  
140                                  if (cpu->machine->emul->net == NULL)                  /*  Write:  */
141                                          fatal("[ ether: RECEIVE but no "                  switch (idata) {
142                                              "net? ]\n");  
143                                  else {                  case DEV_ETHER_COMMAND_RX:      /*  Receive:  */
144                                          d->status &= ~STATUS_RECEIVED;                          if (cpu->machine->emul->net == NULL)
145                                          net_ethernet_rx(cpu->machine->emul->net,                                  fatal("[ ether: RECEIVE but no net? ]\n");
146                                              d, &incoming_ptr, &incoming_len);                          else {
147                                          if (incoming_ptr != NULL) {                                  d->status &= ~DEV_ETHER_STATUS_PACKET_RECEIVED;
148                                                  d->status |= STATUS_RECEIVED;                                  net_ethernet_rx(cpu->machine->emul->net,
149                                                  if (incoming_len >                                      d, &incoming_ptr, &incoming_len);
150                                                      DEV_ETHER_MAXBUFLEN)                                  if (incoming_ptr != NULL) {
151                                                          incoming_len =                                          d->status |=
152                                                              DEV_ETHER_MAXBUFLEN;                                              DEV_ETHER_STATUS_PACKET_RECEIVED;
153                                                  memcpy(d->buf, incoming_ptr,                                          if (incoming_len>DEV_ETHER_BUFFER_SIZE)
154                                                      incoming_len);                                                  incoming_len =
155                                                  free(incoming_ptr);                                                      DEV_ETHER_BUFFER_SIZE;
156                                                  d->packet_len = incoming_len;                                          memcpy(d->buf, incoming_ptr,
157                                          }                                              incoming_len);
158                                            free(incoming_ptr);
159                                            d->packet_len = incoming_len;
160                                  }                                  }
                                 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;  
161                          }                          }
162                            dev_ether_tick(cpu, d);
163                            break;
164    
165                    case DEV_ETHER_COMMAND_TX:      /*  Send  */
166                            if (cpu->machine->emul->net == NULL)
167                                    fatal("[ ether: SEND but no net? ]\n");
168                            else
169                                    net_ethernet_tx(cpu->machine->emul->net,
170                                        d, d->buf, d->packet_len);
171                            d->status &= ~DEV_ETHER_STATUS_PACKET_RECEIVED;
172                            dev_ether_tick(cpu, d);
173                            break;
174    
175                    default:fatal("[ ether: UNIMPLEMENTED command 0x"
176                                "%02x ]\n", idata);
177                            cpu->running = 0;
178                  }                  }
179                  break;                  break;
180    
181          default:if (writeflag == MEM_WRITE) {          default:if (writeflag == MEM_WRITE) {
182                          fatal("[ ether: unimplemented write to "                          fatal("[ ether: unimplemented write to "
183                              "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 195  int dev_ether_access(struct cpu *cpu, st
195  }  }
196    
197    
198  /*  DEVINIT(ether)
  *  devinit_ether():  
  */  
 int devinit_ether(struct devinit *devinit)  
199  {  {
200          struct ether_data *d = malloc(sizeof(struct ether_data));          struct ether_data *d = malloc(sizeof(struct ether_data));
201          size_t nlen;          size_t nlen;
# Line 228  int devinit_ether(struct devinit *devini Line 220  int devinit_ether(struct devinit *devini
220          snprintf(n1, nlen, "%s [%s]", devinit->name, tmp);          snprintf(n1, nlen, "%s [%s]", devinit->name, tmp);
221          snprintf(n2, nlen, "%s [%s, control]", devinit->name, tmp);          snprintf(n2, nlen, "%s [%s, control]", devinit->name, tmp);
222    
223          memory_device_register(devinit->machine->memory, n1,          memory_device_register(devinit->machine->memory, n1, devinit->addr,
224              devinit->addr, DEV_ETHER_MAXBUFLEN, dev_ether_buf_access, (void *)d,              DEV_ETHER_BUFFER_SIZE, dev_ether_buf_access, (void *)d,
225              DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK |              DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK |
226              DM_READS_HAVE_NO_SIDE_EFFECTS, d->buf);              DM_READS_HAVE_NO_SIDE_EFFECTS, d->buf);
227          memory_device_register(devinit->machine->memory, n2,          memory_device_register(devinit->machine->memory, n2,
228              devinit->addr + DEV_ETHER_MAXBUFLEN,              devinit->addr + DEV_ETHER_BUFFER_SIZE,
229              DEV_ETHER_LENGTH-DEV_ETHER_MAXBUFLEN, dev_ether_access, (void *)d,              DEV_ETHER_LENGTH-DEV_ETHER_BUFFER_SIZE, dev_ether_access, (void *)d,
230              DM_DEFAULT, NULL);              DM_DEFAULT, NULL);
231    
232          net_add_nic(devinit->machine->emul->net, d, d->mac);          net_add_nic(devinit->machine->emul->net, d, d->mac);
233    
234          machine_add_tickfunction(devinit->machine,          machine_add_tickfunction(devinit->machine,
235              dev_ether_tick, d, DEV_ETHER_TICK_SHIFT);              dev_ether_tick, d, DEV_ETHER_TICK_SHIFT, 0.0);
236    
237          return 1;          return 1;
238  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26