6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 #include <exec/types.h>
23 #include <exec/resident.h>
25 #include <exec/ports.h>
26 #include <exec/errors.h>
30 #include <devices/sana2.h>
31 #include <devices/sana2specialstats.h>
32 #include <devices/newstyle.h>
33 #include <devices/timer.h>
35 #include <utility/utility.h>
36 #include <utility/tagitem.h>
37 #include <utility/hooks.h>
39 #include <proto/exec.h>
40 #include <proto/dos.h>
41 #include <proto/oop.h>
42 #include <proto/timer.h>
43 #include <proto/utility.h>
50 #include LC_LIBDEFS_FILE
53 * Report incoming events to all hyphotetical event receivers
55 VOID
ReportEvents(struct SiS900Base
*SiS900DeviceBase
, struct SiS900Unit
*unit
, ULONG events
)
57 struct IOSana2Req
*request
, *tail
, *next_request
;
60 list
= &unit
->sis900u_request_ports
[EVENT_QUEUE
]->mp_MsgList
;
61 next_request
= (APTR
)list
->lh_Head
;
62 tail
= (APTR
)&list
->lh_Tail
;
64 /* Go through list of event listeners. If send messages to receivers if event found */
66 while(next_request
!= tail
)
68 request
= next_request
;
69 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
71 if((request
->ios2_WireError
&events
) != 0)
73 request
->ios2_WireError
= events
;
74 Remove((APTR
)request
);
75 ReplyMsg((APTR
)request
);
83 struct TypeStats
*FindTypeStats(struct SiS900Base
*SiS900DeviceBase
, struct SiS900Unit
*unit
,
84 struct MinList
*list
, ULONG packet_type
)
86 struct TypeStats
*stats
, *tail
;
89 stats
= (APTR
)list
->mlh_Head
;
90 tail
= (APTR
)&list
->mlh_Tail
;
92 while(stats
!= tail
&& !found
)
94 if(stats
->packet_type
== packet_type
)
97 stats
= (APTR
)stats
->node
.mln_Succ
;
106 void FlushUnit(LIBBASETYPEPTR LIBBASE
, struct SiS900Unit
*unit
, UBYTE last_queue
, BYTE error
)
108 struct IORequest
*request
;
110 struct Opener
*opener
, *tail
;
112 D(bug("%s unit.FlushUnit\n", unit
->sis900u_name
));
114 /* Abort queued operations */
116 for (i
=0; i
<= last_queue
; i
++)
118 while ((request
= (APTR
)GetMsg(unit
->sis900u_request_ports
[i
])) != NULL
)
120 request
->io_Error
= IOERR_ABORTED
;
121 ReplyMsg((struct Message
*)request
);
125 opener
= (APTR
)unit
->sis900u_Openers
.mlh_Head
;
126 tail
= (APTR
)unit
->sis900u_Openers
.mlh_Tail
;
128 /* Flush every opener's read queue */
130 while(opener
!= tail
)
132 while ((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
134 request
->io_Error
= error
;
135 ReplyMsg((struct Message
*)request
);
137 opener
= (struct Opener
*)opener
->node
.mln_Succ
;
142 * Interrupt handler called whenever SiS900 NIC interface generates interrupt.
143 * It's duty is to iterate throgh RX queue searching for new packets.
145 * Please note, that allthough multicast support could be done on interface
146 * basis, it is done in this function as result of quick integration of both
147 * the forcedeth driver (IFF_ALLMULTI flag) and etherling3 driver (AddressMatch
150 static AROS_INTH1(SiS900_RX_IntF
, struct SiS900Unit
*, unit
)
154 struct SiS900Base
*SiS900DeviceBase
= unit
->sis900u_device
;
155 struct TypeStats
*tracker
;
157 struct Opener
*opener
, *opener_tail
;
158 struct IOSana2Req
*request
, *request_tail
;
159 BOOL accepted
, is_orphan
;
161 unsigned int entry
= unit
->cur_rx
% NUM_RX_DESC
;
162 ULONG rx_status
= unit
->rx_ring
[entry
].cmdsts
;
164 D(bug("[%s]: SiS900_RX_IntF() !!!!\n", unit
->sis900u_name
));
165 D(bug("[%s]: SiS900_RX_IntF: cur_rx:%4.4d, dirty_rx:%4.4d status:0x%8.8x\n", unit
->sis900u_name
, unit
->cur_rx
, unit
->dirty_rx
, rx_status
));
167 while (rx_status
& OWN
)
169 unsigned int rx_size
;
171 struct eth_frame
*frame
;
173 rx_size
= (rx_status
& DSIZE
) - CRC_SIZE
;
175 if (rx_status
& (ABORT
|OVERRUN
|TOOLONG
|RUNT
|RXISERR
|CRCERR
|FAERR
))
177 /* corrupted packet received */
178 D(bug("[%s]: SiS900_RX_IntF: Corrupted packet received, buffer status = 0x%8.8x.\n", unit
->sis900u_name
, rx_status
));
179 // unit->stats.rx_errors++;
180 if (rx_status
& OVERRUN
)
182 // unit->stats.rx_over_errors++;
184 if (rx_status
& (TOOLONG
|RUNT
))
186 // unit->stats.rx_length_errors++;
188 if (rx_status
& (RXISERR
| FAERR
))
190 // unit->stats.rx_frame_errors++;
192 if (rx_status
& CRCERR
)
194 // unit->stats.rx_crc_errors++;
196 /* reset buffer descriptor state */
197 unit
->rx_ring
[entry
].cmdsts
= RX_BUF_SIZE
;
201 /* got a valid packet - forward it to the network core */
202 frame
= unit
->rx_buffers
[entry
];
205 /* Dump contents of frame if DEBUG enabled */
209 for (j
=0; j
<64; j
++) {
211 D(bug("\n%03x:", j
));
212 D(bug(" %02x", ((unsigned char*)frame
)[j
]));
218 /* Check for address validity */
219 if(AddressFilter(LIBBASE
, unit
, frame
->eth_packet_dest
))
221 /* Packet is addressed to this driver */
222 packet_type
= AROS_BE2WORD(frame
->eth_packet_type
);
223 D(bug("[%s]: SiS900_RX_IntF: Packet IP accepted with type = %d\n", unit
->sis900u_name
, packet_type
));
225 opener
= (APTR
)unit
->sis900u_Openers
.mlh_Head
;
226 opener_tail
= (APTR
)&unit
->sis900u_Openers
.mlh_Tail
;
228 /* Offer packet to every opener */
229 while(opener
!= opener_tail
)
231 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
232 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
235 /* Offer packet to each request until it's accepted */
236 while((request
!= request_tail
) && !accepted
)
238 if((request
->ios2_PacketType
== packet_type
)
239 || ((request
->ios2_PacketType
<= ETH_MTU
)
240 && (packet_type
<= ETH_MTU
)))
242 D(bug("[%s]: SiS900_RX_IntF: copy packet for opener ..\n", unit
->sis900u_name
));
243 CopyPacket(LIBBASE
, unit
, request
, rx_size
, packet_type
, frame
);
247 (struct IOSana2Req
*)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
253 opener
= (APTR
)opener
->node
.mln_Succ
;
256 /* If packet was unwanted, give it to S2_READORPHAN request */
259 unit
->sis900u_stats
.UnknownTypesReceived
++;
261 if(!IsMsgPortEmpty(unit
->sis900u_request_ports
[ADOPT_QUEUE
]))
263 CopyPacket(LIBBASE
, unit
,
264 (APTR
)unit
->sis900u_request_ports
[ADOPT_QUEUE
]->
265 mp_MsgList
.lh_Head
, rx_size
, packet_type
, frame
);
266 D(bug("[%s]: SiS900_RX_IntF: packet copied to orphan queue\n", unit
->sis900u_name
));
270 /* Update remaining statistics */
273 FindTypeStats(LIBBASE
, unit
, &unit
->sis900u_type_trackers
, packet_type
);
277 tracker
->stats
.PacketsReceived
++;
278 tracker
->stats
.BytesReceived
+= rx_size
;
281 unit
->sis900u_stats
.PacketsReceived
++;
283 unit
->rx_ring
[entry
].cmdsts
= RX_BUF_SIZE
;
287 entry
= unit
->cur_rx
% NUM_RX_DESC
;
288 rx_status
= unit
->rx_ring
[entry
].cmdsts
;
297 * Interrupt generated by Cause() to push new packets into the NIC interface
299 static AROS_INTH1(SiS900_TX_IntF
, struct SiS900Unit
*,unit
)
303 struct SiS900Base
*SiS900DeviceBase
= unit
->sis900u_device
;
304 long ioaddr
= unit
->sis900u_BaseMem
;
305 BOOL proceed
= FALSE
; /* Fails by default */
308 unsigned int index_cur_tx
, index_dirty_tx
;
309 unsigned int count_dirty_tx
;
311 D(bug("[%s]: SiS900_TX_IntF()\n", unit
->sis900u_name
));
313 /* send packet only if there is free space on tx queue. Otherwise do nothing */
314 if (!netif_queue_stopped(unit
))
316 UWORD packet_size
, data_size
;
317 struct IOSana2Req
*request
;
318 struct Opener
*opener
;
322 struct MsgPort
*port
;
323 struct TypeStats
*tracker
;
325 proceed
= TRUE
; /* Success by default */
326 port
= unit
->sis900u_request_ports
[WRITE_QUEUE
];
328 /* Still no error and there are packets to be sent? */
329 while(proceed
&& (!IsMsgPortEmpty(port
)))
331 entry
= unit
->cur_tx
% NUM_TX_DESC
;
334 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
335 data_size
= packet_size
= request
->ios2_DataLength
;
337 opener
= (APTR
)request
->ios2_BufferManagement
;
339 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
341 packet_size
+= ETH_PACKET_DATA
;
342 CopyMem(request
->ios2_DstAddr
, &((struct eth_frame
*)unit
->tx_buffers
[entry
])->eth_packet_dest
, ETH_ADDRESSSIZE
);
343 CopyMem(unit
->sis900u_dev_addr
, &((struct eth_frame
*)unit
->tx_buffers
[entry
])->eth_packet_source
, ETH_ADDRESSSIZE
);
344 ((struct eth_frame
*)unit
->tx_buffers
[entry
])->eth_packet_type
= AROS_WORD2BE(request
->ios2_PacketType
);
346 buffer
= (UBYTE
*)&((struct eth_frame
*)(IPTR
)unit
->tx_buffers
[entry
])->eth_packet_data
;
349 buffer
= unit
->tx_buffers
[entry
];
351 if (!opener
->tx_function(buffer
, request
->ios2_Data
, data_size
))
353 error
= S2ERR_NO_RESOURCES
;
354 wire_error
= S2WERR_BUFF_ERROR
;
355 ReportEvents(LIBBASE
, unit
,
356 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
360 /* Now the packet is already in TX buffer, update flags for NIC */
364 D(bug("[%s]: SiS900_TX_IntF: packet %d @ %x [type = %d] queued for transmission.", unit
->sis900u_name
, entry
, unit
->tx_buffers
[entry
], ((struct eth_frame
*)unit
->tx_buffers
[entry
])->eth_packet_type
));
366 /* DEBUG? Dump frame if so */
370 for (j
=0; j
<64; j
++) {
372 D(bug("\n%03x:", j
));
373 D(bug(" %02x", ((unsigned char*)unit
->tx_buffers
[entry
])[j
]));
381 /* Set the ring details for the packet .. */
382 unit
->tx_ring
[entry
].cmdsts
= (OWN
| packet_size
);
383 LONGOUT(ioaddr
+ cr
, TxENA
| LONGIN(ioaddr
+ cr
));
386 index_cur_tx
= unit
->cur_tx
;
387 index_dirty_tx
= unit
->dirty_tx
;
389 for (count_dirty_tx
= 0; index_cur_tx
!= index_dirty_tx
; index_dirty_tx
++)
392 D(bug("[%s]: SiS900_TX_IntF: Packet Queued.\n", unit
->sis900u_name
));
397 request
->ios2_Req
.io_Error
= error
;
398 request
->ios2_WireError
= wire_error
;
400 Remove((APTR
)request
);
402 ReplyMsg((APTR
)request
);
404 /* Update statistics */
408 tracker
= FindTypeStats(LIBBASE
, unit
, &unit
->sis900u_type_trackers
,
409 request
->ios2_PacketType
);
412 tracker
->stats
.PacketsSent
++;
413 tracker
->stats
.BytesSent
+= packet_size
;
419 /* Was there success? Enable incomming of new packets */
421 unit
->sis900u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
423 unit
->sis900u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
431 * Handle timeouts and other strange cases
433 static AROS_INTH1(SiS900_TimeoutHandlerF
, struct SiS900Unit
*, unit
)
437 // struct timeval time;
438 // struct Device *TimerBase = unit->sis900u_TimerSlowReq->tr_node.io_Device;
440 // GetSysTime(&time);
441 //D(bug("[%s]: SiS900_TimeoutHandlerF()\n", unit->sis900u_name));
444 * If timeout timer is expected, and time elapsed - regenerate the
447 // if (unit->sis900u_toutNEED && (CmpTime(&time, &unit->sis900u_toutPOLL ) < 0))
449 // unit->sis900u_toutNEED = FALSE;
450 //Cause(&unit->sis900u_tx_end_int);
458 * The interrupt handler - schedules code execution to proper handlers
460 static AROS_INTH1(SiS900_IntHandlerF
, struct SiS900Unit
*, unit
)
464 long ioaddr
= unit
->sis900u_BaseMem
;
467 // int i, link_changed;
469 // struct Device *TimerBase = unit->sis900u_TimerSlowReq->tr_node.io_Device;
470 // struct timeval time;
472 D(bug("[%s]: SiS900_IntHandlerF()!!!!!!!\n", unit
->sis900u_name
));
475 status
= LONGIN(ioaddr
+ isr
);
477 if ((status
& (HIBERR
|TxURN
|TxERR
|TxIDLE
|RxORN
|RxERR
|RxOK
)) == 0)
479 /* nothing intresting happened */
480 D(bug("[%s]: SiS900_IntHandlerF: Nothing for us ..\n", unit
->sis900u_name
));
484 /* why dow't we break after Tx/Rx case ?? keyword: full-duplex */
485 if (status
& (RxORN
| RxERR
| RxOK
))
487 D(bug("[%s]: SiS900_IntHandlerF: Rx Detected!\n", unit
->sis900u_name
));
489 Cause(&unit
->sis900u_rx_int
);
492 if (status
& (TxURN
| TxERR
| TxIDLE
))
494 D(bug("[%s]: SiS900_IntHandlerF: End of Tx Detected\n", unit
->sis900u_name
));
496 for (; unit
->dirty_tx
!= unit
->cur_tx
; unit
->dirty_tx
++) {
500 entry
= unit
->dirty_tx
% NUM_TX_DESC
;
501 tx_status
= unit
->tx_ring
[entry
].cmdsts
;
503 if (tx_status
& OWN
) {
504 /* The packet is not transmitted yet (owned by hardware) !
505 * Note: the interrupt is generated only when Tx Machine
506 * is idle, so this is an almost impossible case */
510 if (tx_status
& (ABORT
| UNDERRUN
| OWCOLL
)) {
511 /* packet unsuccessfully transmitted */
512 D(bug("[%s]: SiS900_IntHandlerF: Transmit error, Tx status %8.8x.\n", unit
->sis900u_name
, tx_status
));
513 // unit->stats.tx_errors++;
514 if (tx_status
& UNDERRUN
)
516 // unit->stats.tx_fifo_errors++;
518 if (tx_status
& ABORT
)
520 // unit->stats.tx_aborted_errors++;
522 if (tx_status
& NOCARRIER
)
524 // unit->stats.tx_carrier_errors++;
526 if (tx_status
& OWCOLL
)
528 // unit->stats.tx_window_errors++;
531 /* packet successfully transmitted */
532 // sis_priv->stats.collisions += (tx_status & COLCNT) >> 16;
533 // sis_priv->stats.tx_bytes += tx_status & DSIZE;
534 unit
->sis900u_stats
.PacketsSent
++;
536 /* Mark the buffer as usable again ... */
537 unit
->tx_ring
[entry
].cmdsts
= 0;
541 /* something strange happened !!! */
542 if (status
& HIBERR
) {
543 D(bug("[%s]: SiS900_IntHandlerF: Abnormal interrupt, status %#8.8x\n", unit
->sis900u_name
, status
));
546 if (--boguscnt
< 0) {
547 D(bug("[%s]: SiS900_IntHandlerF: Too much work at interrupt, interrupt status = %#8.8x\n", unit
->sis900u_name
, status
));
552 D(bug("[%s]: SiS900_IntHandlerF: exiting interrupt, interrupt status = 0x%#8.8x\n", unit
->sis900u_name
, LONGIN(ioaddr
+ isr
)));
559 VOID
CopyPacket(struct SiS900Base
*SiS900DeviceBase
, struct SiS900Unit
*unit
,
560 struct IOSana2Req
*request
, UWORD packet_size
, UWORD packet_type
,
561 struct eth_frame
*buffer
)
563 struct Opener
*opener
;
564 BOOL filtered
= FALSE
;
566 const UBYTE broadcast
[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
568 D(bug("[%s]: CopyPacket(packet @ %x, len = %d)\n", unit
->sis900u_name
, buffer
, packet_size
));
570 /* Set multicast and broadcast flags */
572 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
573 if (memcmp(buffer
->eth_packet_dest
, broadcast
, 6) == 0)
575 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
576 D(bug("[%s]: CopyPacket: BROADCAST Flag set\n", unit
->sis900u_name
));
578 else if((buffer
->eth_packet_dest
[0] & 0x1) != 0)
580 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
581 D(bug("[%s]: CopyPacket: MULTICAST Flag set\n", unit
->sis900u_name
));
584 /* Set source and destination addresses and packet type */
585 CopyMem(buffer
->eth_packet_source
, request
->ios2_SrcAddr
, ETH_ADDRESSSIZE
);
586 CopyMem(buffer
->eth_packet_dest
, request
->ios2_DstAddr
, ETH_ADDRESSSIZE
);
587 request
->ios2_PacketType
= packet_type
;
589 /* Adjust for cooked packet request */
591 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
593 packet_size
-= ETH_PACKET_DATA
;
594 ptr
= (UBYTE
*)&buffer
->eth_packet_data
[0];
598 ptr
= (UBYTE
*)buffer
;
601 request
->ios2_DataLength
= packet_size
;
603 D(bug("[%s]: CopyPacket: packet @ %x (%d bytes)\n", unit
->sis900u_name
, ptr
, packet_size
));
607 opener
= request
->ios2_BufferManagement
;
608 if((request
->ios2_Req
.io_Command
== CMD_READ
) &&
609 (opener
->filter_hook
!= NULL
))
610 if(!CallHookPkt(opener
->filter_hook
, request
, ptr
))
612 D(bug("[%s]: CopyPacket: packet filtered\n", unit
->sis900u_name
));
618 /* Copy packet into opener's buffer and reply packet */
619 D(bug("[%s]: CopyPacket: opener recieve packet .. ", unit
->sis900u_name
));
620 if(!opener
->rx_function(request
->ios2_Data
, ptr
, packet_size
))
622 D(bug("ERROR occured!!\n"));
623 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
624 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
625 ReportEvents(LIBBASE
, unit
, S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
);
629 D(bug("SUCCESS!!\n"));
632 Remove((APTR
)request
);
634 ReplyMsg((APTR
)request
);
635 D(bug("[%s]: CopyPacket: opener notified.\n", unit
->sis900u_name
));
639 BOOL
AddressFilter(struct SiS900Base
*SiS900DeviceBase
, struct SiS900Unit
*unit
, UBYTE
*address
)
641 struct AddressRange
*range
, *tail
;
646 /* Check whether address is unicast/broadcast or multicast */
648 address_left
= AROS_BE2LONG(*((ULONG
*)address
));
649 address_right
= AROS_BE2WORD(*((UWORD
*)(address
+ 4)));
651 if((address_left
& 0x01000000) != 0 &&
652 !(address_left
== 0xffffffff && address_right
== 0xffff))
654 /* Check if this multicast address is wanted */
656 range
= (APTR
)unit
->sis900u_multicast_ranges
.mlh_Head
;
657 tail
= (APTR
)&unit
->sis900u_multicast_ranges
.mlh_Tail
;
660 while((range
!= tail
) && !accept
)
662 if((address_left
> range
->lower_bound_left
||
663 (address_left
== range
->lower_bound_left
&&
664 address_right
>= range
->lower_bound_right
)) &&
665 (address_left
< range
->upper_bound_left
||
666 (address_left
== range
->upper_bound_left
&&
667 address_right
<= range
->upper_bound_right
)))
669 range
= (APTR
)range
->node
.mln_Succ
;
673 unit
->sis900u_special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
681 AROS_UFH3(void, SiS900_Schedular
,
682 AROS_UFHA(STRPTR
, argPtr
, A0
),
683 AROS_UFHA(ULONG
, argSize
, D0
),
684 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
688 struct SiS900Startup
*sm_UD
= FindTask(NULL
)->tc_UserData
;
689 struct SiS900Unit
*unit
= sm_UD
->sis900sm_Unit
;
691 LIBBASETYPEPTR LIBBASE
= unit
->sis900u_device
;
692 struct MsgPort
*reply_port
, *input
;
694 D(bug("%s SiS900_Schedular()\n", unit
->sis900u_name
));
695 D(bug("%s SiS900_Schedular: Setting device up\n", unit
->sis900u_name
));
697 reply_port
= CreateMsgPort();
698 input
= CreateMsgPort();
700 unit
->sis900u_input_port
= input
;
702 unit
->sis900u_TimerSlowPort
= CreateMsgPort();
704 if (unit
->sis900u_TimerSlowPort
)
706 unit
->sis900u_TimerSlowReq
= (struct timerequest
*)
707 CreateIORequest((struct MsgPort
*)unit
->sis900u_TimerSlowPort
, sizeof(struct timerequest
));
709 if (unit
->sis900u_TimerSlowReq
)
711 if (!OpenDevice("timer.device", UNIT_VBLANK
,
712 (struct IORequest
*)unit
->sis900u_TimerSlowReq
, 0))
714 struct Message
*msg
= AllocVec(sizeof(struct Message
), MEMF_PUBLIC
|MEMF_CLEAR
);
717 D(bug("%s SiS900_Schedular: Got VBLANK unit of timer.device\n", unit
->sis900u_name
));
719 sis900func_initialize(unit
);
721 msg
->mn_ReplyPort
= reply_port
;
722 msg
->mn_Length
= sizeof(struct Message
);
724 D(bug("%s SiS900_Schedular: Setup complete. Sending handshake\n", unit
->sis900u_name
));
725 PutMsg(sm_UD
->sis900sm_SyncPort
, msg
);
726 WaitPort(reply_port
);
731 D(bug("%s SiS900_Schedular: entering forever loop ... \n", unit
->sis900u_name
));
733 unit
->sis900u_signal_0
= AllocSignal(-1);
734 unit
->sis900u_signal_1
= AllocSignal(-1);
735 unit
->sis900u_signal_2
= AllocSignal(-1);
736 unit
->sis900u_signal_3
= AllocSignal(-1);
738 sigset
= 1 << input
->mp_SigBit
|
739 1 << unit
->sis900u_signal_0
|
740 1 << unit
->sis900u_signal_1
|
741 1 << unit
->sis900u_signal_2
|
742 1 << unit
->sis900u_signal_3
;
745 ULONG recvd
= Wait(sigset
);
746 if (recvd
& unit
->sis900u_signal_0
)
749 * Shutdown process. Driver should close everything
750 * already and waits for our process to complete. Free
751 * memory allocared here and kindly return.
753 sis900func_deinitialize(unit
);
754 CloseDevice((struct IORequest
*)unit
->sis900u_TimerSlowReq
);
755 DeleteIORequest((struct IORequest
*)unit
->sis900u_TimerSlowReq
);
756 DeleteMsgPort(unit
->sis900u_TimerSlowPort
);
757 DeleteMsgPort(input
);
758 DeleteMsgPort(reply_port
);
760 D(bug("%s SiS900_Schedular: Process shutdown.\n", unit
->sis900u_name
));
763 else if (recvd
& (1 << input
->mp_SigBit
))
765 struct IOSana2Req
*io
;
767 /* Handle incoming transactions */
768 while ((io
= (struct IOSana2Req
*)GetMsg(input
))!= NULL
)
770 D(bug("%s SiS900_Schedular: Handle incomming transaction.\n", unit
->sis900u_name
));
771 ObtainSemaphore(&unit
->sis900u_unit_lock
);
772 handle_request(LIBBASE
, io
);
777 D(bug("%s SiS900_Schedular: Handle incomming signal.\n", unit
->sis900u_name
));
778 /* Handle incoming signals */
789 * Create new SiS900 ethernet device unit
791 struct SiS900Unit
*CreateUnit(struct SiS900Base
*SiS900DeviceBase
, OOP_Object
*pciDevice
, char * CardName
, char * CardChipset
)
793 struct SiS900Unit
*unit
= NULL
;
797 D(bug("[SiS900] CreateUnit()\n"));
799 if ((unit
= AllocMem(sizeof(struct SiS900Unit
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
801 IPTR DeviceID
= 0, RevisionID
= 0, HostRevisionID
= 0, base
= 0, len
;
802 OOP_Object
*driver
= NULL
;
804 D(bug("[SiS900] CreateUnit: Unit allocated @ %x\n", unit
));
806 unit
->sis900u_UnitNum
= SiS900DeviceBase
->sis900b_UnitCount
++;
808 unit
->sis900u_Sana2Info
.HardwareType
= S2WireType_Ethernet
;
809 unit
->sis900u_Sana2Info
.MTU
= ETH_MTU
;
810 unit
->sis900u_Sana2Info
.AddrFieldSize
= 8 * ETH_ADDRESSSIZE
;
812 if ((unit
->sis900u_name
= AllocVec(7 + (unit
->sis900u_UnitNum
/10) + 2, MEMF_PUBLIC
| MEMF_CLEAR
)) == NULL
)
814 FreeMem(unit
, sizeof(struct SiS900Unit
));
818 sprintf((char *)unit
->sis900u_name
, "sis900.%d", unit
->sis900u_UnitNum
);
820 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_ProductID
, &DeviceID
);
821 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_RevisionID
, &RevisionID
);
822 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Driver
, (APTR
)&driver
);
824 /* TODO: Get the host bridge revision!! */
825 /* // save our host bridge revision
826 dev = pci_get_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, NULL);
828 pci_read_config_byte(dev, PCI_CLASS_REVISION, &sis_priv->host_bridge_rev);
832 unit
->sis900u_rtl_cardname
= CardName
;
833 unit
->sis900u_rtl_chipname
= CardChipset
;
835 unit
->sis900u_PCIDevice
= pciDevice
;
836 unit
->sis900u_PCIDriver
= driver
;
838 unit
->sis900u_device
= SiS900DeviceBase
;
839 unit
->sis900u_DeviceID
= DeviceID
;
840 unit
->sis900u_RevisionID
= RevisionID
;
841 unit
->sis900u_HostRevisionID
= HostRevisionID
;
843 unit
->sis900u_mtu
= unit
->sis900u_Sana2Info
.MTU
;
845 InitSemaphore(&unit
->sis900u_unit_lock
);
846 NEWLIST(&unit
->sis900u_Openers
);
847 NEWLIST(&unit
->sis900u_multicast_ranges
);
848 NEWLIST(&unit
->sis900u_type_trackers
);
850 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_INTLine
, &unit
->sis900u_IRQ
);
851 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base1
, &unit
->sis900u_BaseIO
);
852 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base0
, &base
);
853 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Size0
, &len
);
855 D(bug("%s CreateUnit: INT:%d, base1:%x, base0:%x, size0:%d\n", unit
->sis900u_name
,
856 unit
->sis900u_IRQ
, unit
->sis900u_BaseIO
,
859 unit
->sis900u_BaseMem
= (IPTR
)HIDD_PCIDriver_MapPCI(driver
, (APTR
)base
, len
);
860 unit
->sis900u_SizeMem
= len
;
862 if (unit
->sis900u_BaseMem
)
864 struct TagItem attrs
[] = {
865 { aHidd_PCIDevice_isIO
, TRUE
},
866 { aHidd_PCIDevice_isMEM
, TRUE
},
867 { aHidd_PCIDevice_isMaster
, TRUE
},
870 OOP_SetAttrs(pciDevice
, (struct TagItem
*)&attrs
);
872 D(bug("%s CreateUnit: PCI_BaseMem @ %x\n", unit
->sis900u_name
, unit
->sis900u_BaseMem
));
873 if ((unit
->tx_ring
= AllocMem(TX_TOTAL_SIZE
, MEMF_PUBLIC
|MEMF_CLEAR
)) != NULL
)
876 if ((unit
->tx_ring_dma
= HIDD_PCIDriver_CPUtoPCI(unit
->sis900u_PCIDriver
, unit
->tx_ring
)) == NULL
)
878 D(bug("[%s]: CreateUnit: Failed to Map Tx Ring Buffer Descriptors DMA \n", unit
->sis900u_name
));
884 D(bug("[%s]: CreateUnit: Failed to Allocate Tx Ring Buffer Descriptors\n", unit
->sis900u_name
));
887 D(bug("[%s]: CreateUnit: Tx Ring Buffer Descriptors @ %p [DMA @ %p]\n", unit
->sis900u_name
, unit
->tx_ring
, unit
->tx_ring_dma
));
889 if ((unit
->rx_ring
= AllocMem(RX_TOTAL_SIZE
, MEMF_PUBLIC
|MEMF_CLEAR
)) != NULL
)
892 if ((unit
->rx_ring_dma
= HIDD_PCIDriver_CPUtoPCI(unit
->sis900u_PCIDriver
, unit
->rx_ring
)) == NULL
)
894 D(bug("[%s]: CreateUnit: Failed to Map Rx Ring Buffer Descriptors DMA\n", unit
->sis900u_name
));
900 D(bug("[%s]: CreateUnit: Failed to Allocate Rx Ring Buffer Descriptors DMA\n", unit
->sis900u_name
));
903 D(bug("[%s]: CreateUnit: Rx Ring Buffer Descriptors @ %p [DMA @ %p]\n", unit
->sis900u_name
, unit
->rx_ring
, unit
->rx_ring_dma
));
908 unit
->sis900u_irqhandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
909 unit
->sis900u_irqhandler
.is_Node
.ln_Pri
= 100;
910 unit
->sis900u_irqhandler
.is_Node
.ln_Name
= LIBBASE
->sis900b_Device
.dd_Library
.lib_Node
.ln_Name
;
911 unit
->sis900u_irqhandler
.is_Code
= (VOID_FUNC
)SiS900_IntHandlerF
;
912 unit
->sis900u_irqhandler
.is_Data
= unit
;
914 unit
->sis900u_touthandler
.is_Node
.ln_Type
= NT_INTERRUPT
;
915 unit
->sis900u_touthandler
.is_Node
.ln_Pri
= 100;
916 unit
->sis900u_touthandler
.is_Node
.ln_Name
= LIBBASE
->sis900b_Device
.dd_Library
.lib_Node
.ln_Name
;
917 unit
->sis900u_touthandler
.is_Code
= (VOID_FUNC
)SiS900_TimeoutHandlerF
;
918 unit
->sis900u_touthandler
.is_Data
= unit
;
920 unit
->sis900u_rx_int
.is_Node
.ln_Type
= NT_INTERRUPT
;
921 unit
->sis900u_rx_int
.is_Node
.ln_Name
= unit
->sis900u_name
;
922 unit
->sis900u_rx_int
.is_Code
= (VOID_FUNC
)SiS900_RX_IntF
;
923 unit
->sis900u_rx_int
.is_Data
= unit
;
925 unit
->sis900u_tx_int
.is_Node
.ln_Type
= NT_INTERRUPT
;
926 unit
->sis900u_tx_int
.is_Node
.ln_Name
= unit
->sis900u_name
;
927 unit
->sis900u_tx_int
.is_Code
= (VOID_FUNC
)SiS900_TX_IntF
;
928 unit
->sis900u_tx_int
.is_Data
= unit
;
930 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
932 struct MsgPort
*port
;
934 if ((port
= AllocMem(sizeof(struct MsgPort
), MEMF_PUBLIC
| MEMF_CLEAR
)) == NULL
) success
= FALSE
;
938 unit
->sis900u_request_ports
[i
] = port
;
939 NEWLIST(&port
->mp_MsgList
);
940 port
->mp_Flags
= PA_IGNORE
;
941 port
->mp_SigTask
= &unit
->sis900u_tx_int
;
945 unit
->sis900u_request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
949 struct SiS900Startup
*sm_UD
;
952 if ((sm_UD
= AllocMem(sizeof(struct SiS900Startup
), MEMF_PUBLIC
| MEMF_CLEAR
)) != NULL
)
954 sprintf((char *)tmpbuff
, SiS900_TASK_NAME
, unit
->sis900u_name
);
956 sm_UD
->sis900sm_SyncPort
= CreateMsgPort();
957 sm_UD
->sis900sm_Unit
= unit
;
959 unit
->sis900u_Process
= CreateNewProcTags(
960 NP_Entry
, (IPTR
)SiS900_Schedular
,
962 NP_Synchronous
, FALSE
,
964 NP_UserData
, (IPTR
)sm_UD
,
965 NP_StackSize
, 140960,
968 WaitPort(sm_UD
->sis900sm_SyncPort
);
969 msg
= GetMsg(sm_UD
->sis900sm_SyncPort
);
971 DeleteMsgPort(sm_UD
->sis900sm_SyncPort
);
972 FreeMem(sm_UD
, sizeof(struct SiS900Startup
));
974 D(bug("[%s] CreateUnit: Device Initialised. Unit %d @ %p\n", unit
->sis900u_name
, unit
->sis900u_UnitNum
, unit
));
980 D(bug("[%s]: ERRORS occured during Device setup - ABORTING\n", unit
->sis900u_name
));
986 D(bug("[SiS900] PANIC! Couldn't get MMIO area. Aborting\n"));
989 DeleteUnit(SiS900DeviceBase
, unit
);
994 * DeleteUnit - removes selected unit. Frees all resources and structures.
996 * The caller should be sure, that given unit is really ready to be freed.
999 void DeleteUnit(struct SiS900Base
*SiS900DeviceBase
, struct SiS900Unit
*Unit
)
1003 D(bug("[SiS900] DeleteUnit()\n"));
1007 if (Unit
->sis900u_Process
)
1009 Signal(&Unit
->sis900u_Process
->pr_Task
, Unit
->sis900u_signal_0
);
1012 for (i
=0; i
< REQUEST_QUEUE_COUNT
; i
++)
1014 if (Unit
->sis900u_request_ports
[i
] != NULL
)
1015 FreeMem(Unit
->sis900u_request_ports
[i
], sizeof(struct MsgPort
));
1017 Unit
->sis900u_request_ports
[i
] = NULL
;
1020 if (Unit
->sis900u_BaseMem
)
1022 HIDD_PCIDriver_UnmapPCI(Unit
->sis900u_PCIDriver
,
1023 (APTR
)Unit
->sis900u_BaseMem
,
1024 Unit
->sis900u_SizeMem
);
1027 FreeMem(Unit
, sizeof(struct SiS900Unit
));
1031 static struct AddressRange
*FindMulticastRange(LIBBASETYPEPTR LIBBASE
, struct SiS900Unit
*unit
,
1032 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
, UWORD upper_bound_right
)
1034 struct AddressRange
*range
, *tail
;
1037 range
= (APTR
)unit
->sis900u_multicast_ranges
.mlh_Head
;
1038 tail
= (APTR
)&unit
->sis900u_multicast_ranges
.mlh_Tail
;
1040 while((range
!= tail
) && !found
)
1042 if((lower_bound_left
== range
->lower_bound_left
) &&
1043 (lower_bound_right
== range
->lower_bound_right
) &&
1044 (upper_bound_left
== range
->upper_bound_left
) &&
1045 (upper_bound_right
== range
->upper_bound_right
))
1048 range
= (APTR
)range
->node
.mln_Succ
;
1057 BOOL
AddMulticastRange(LIBBASETYPEPTR LIBBASE
, struct SiS900Unit
*unit
, const UBYTE
*lower_bound
,
1058 const UBYTE
*upper_bound
)
1060 struct AddressRange
*range
;
1061 ULONG lower_bound_left
, upper_bound_left
;
1062 UWORD lower_bound_right
, upper_bound_right
;
1064 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
1065 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
1066 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
1067 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
1069 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
1070 upper_bound_left
, upper_bound_right
);
1076 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
1079 range
->lower_bound_left
= lower_bound_left
;
1080 range
->lower_bound_right
= lower_bound_right
;
1081 range
->upper_bound_left
= upper_bound_left
;
1082 range
->upper_bound_right
= upper_bound_right
;
1083 range
->add_count
= 1;
1086 AddTail((APTR
)&unit
->sis900u_multicast_ranges
, (APTR
)range
);
1089 if (unit
->sis900u_range_count
++ == 0)
1091 unit
->sis900u_ifflags
|= IFF_ALLMULTI
;
1092 sis900func_set_multicast(unit
);
1097 return range
!= NULL
;
1100 BOOL
RemMulticastRange(LIBBASETYPEPTR LIBBASE
, struct SiS900Unit
*unit
, const UBYTE
*lower_bound
, const UBYTE
*upper_bound
)
1102 struct AddressRange
*range
;
1103 ULONG lower_bound_left
, upper_bound_left
;
1104 UWORD lower_bound_right
, upper_bound_right
;
1106 lower_bound_left
= AROS_BE2LONG(*((ULONG
*)lower_bound
));
1107 lower_bound_right
= AROS_BE2WORD(*((UWORD
*)(lower_bound
+ 4)));
1108 upper_bound_left
= AROS_BE2LONG(*((ULONG
*)upper_bound
));
1109 upper_bound_right
= AROS_BE2WORD(*((UWORD
*)(upper_bound
+ 4)));
1111 range
= FindMulticastRange(LIBBASE
, unit
, lower_bound_left
, lower_bound_right
,
1112 upper_bound_left
, upper_bound_right
);
1116 if(--range
->add_count
== 0)
1119 Remove((APTR
)range
);
1121 FreeMem(range
, sizeof(struct AddressRange
));
1123 if (--unit
->sis900u_range_count
== 0)
1125 unit
->sis900u_ifflags
&= ~IFF_ALLMULTI
;
1126 sis900func_set_multicast(unit
);
1130 return range
!= NULL
;