|
|
1.1 root 1: /*
2: * Copyright (c) 1993 NeXT Computer, Inc.
3: *
4: * Driver class for SMC EtherCard Plus Elite16 adaptors.
5: *
6: * HISTORY
7: *
8: * 19 Apr 1993
9: * Added multicast & promiscuous mode support.
10: *
11: * 26 Jan 1993
12: * Created.
13: */
14:
15: #define MACH_USER_API 1
16:
17: #import <driverkit/generalFuncs.h>
18: #import <driverkit/IONetbufQueue.h>
19:
20: #import "SMC16.h"
21: #import "SMC16IOInline.h"
22: #import "SMC16Private.h"
23:
24: #import <kernserv/kern_server_types.h>
25: #import <kernserv/prototypes.h>
26: #import <kernserv/i386/spl.h>
27:
28: @implementation SMC16
29:
30: /*
31: * Private Instance Methods
32: */
33:
34: /*
35: * _memAvail
36: * Returns the amount of onboard memory not currently in use.
37: * Never returns less than zero.
38: */
39: - (SMC16_len_t)_memAvail
40: {
41: int available;
42:
43: available = (memtotal - memused);
44:
45: return ((SMC16_len_t) ((available < 0)? 0: available));
46: }
47:
48: /*
49: * _memRegion
50: * Returns the next available NIC_PAGE_SIZE chunk of onboard memory.
51: */
52: - (SMC16_off_t)_memRegion:(SMC16_len_t)length
53: {
54: if ([self _memAvail] < length)
55: IOPanic("SMC16: onboard memory exhausted");
56:
57: return ((SMC16_off_t) (memused / NIC_PAGE_SIZE));
58: }
59:
60: /*
61: * _memAlloc
62: * Allocates onboard memory in chunks of NIC_PAGE_SIZE
63: */
64: - (SMC16_off_t)_memAlloc:(SMC16_len_t)length
65: {
66: SMC16_off_t region;
67:
68: /*
69: * Round up to the next multiple of NIC_PAGE_SIZE
70: */
71: length = ((length + NIC_PAGE_SIZE - 1) & ~(NIC_PAGE_SIZE - 1));
72:
73: region = [self _memRegion:length];
74:
75: memused += length;
76:
77: return (region);
78: }
79:
80: /*
81: * _initializeHardware
82: * Resets the SMC adaptor. Disables interrupts, resets the NIC, and
83: * configures the onboard memory.
84: */
85: - (void)_initializeHardware
86: {
87: setIRQ(irq, YES, base);
88:
89: resetNIC(base);
90:
91: memtotal = setupRAM(membase, memsize, base);
92: memused = 0;
93: }
94:
95: /*
96: * _receiveInitialize
97: * Prepares the card for receive operations. Allocates as many NIC_PAGE_SIZE
98: * buffers from the available onboard memory.
99: */
100: - (void)_receiveInitialize
101: {
102: SMC16_len_t avail = [self _memAvail];
103:
104: rstart = [self _memAlloc:avail];
105: rstop = rstart + (avail / NIC_PAGE_SIZE);
106:
107: /*
108: * Setup the receive ring
109: */
110: put_rstart_reg(rstart, base); put_rstop_reg(rstop, base);
111:
112: /*
113: * Reset the boundary buffer pointer
114: */
115: put_bound_reg(rstart, base);
116:
117: rnext = rstart + 1;
118:
119: /*
120: * Reset the current buffer pointer
121: */
122: (void)sel_reg_page(REG_PAGE1, base);
123: put_curr_reg(rnext, base);
124: (void)sel_reg_page(REG_PAGE0, base);
125: }
126:
127: /*
128: * _transmitInitialize
129: * Prepares for transmit operations. We use 1 transmit buffer of maximum
130: * size.
131: */
132: - (void)_transmitInitialize
133: {
134: tstart = [self _memAlloc:ETHERMAXPACKET];
135: }
136:
137: /*
138: * _initializeSoftware
139: * Prepare the adaptor for network operations and start them.
140: */
141: - (void)_initializeSoftware
142: {
143: setStationAddress(&myAddress, base);
144:
145: [self _transmitInitialize];
146: [self _receiveInitialize];
147:
148: startNIC(base, rconsave);
149: }
150:
151: /*
152: * _receiveInterruptOccurred
153: * This method handles the process of moving received frames from
154: * onboard adaptor memory to netbufs and handing them up to the network
155: * object.
156: */
157: - (void)_receiveInterruptOccurred
158: {
159: nic_recv_hdr_t *rhdr;
160: netbuf_t pkt;
161: int pkt_len, pre_wrap_len;
162: void *pkt_data = NULL;
163:
164: #ifdef DEBUG
165:
166: /*
167: * Change this to 1 to be inundated with messages.
168: */
169: boolean_t SMC16_recvTrace = 0;
170:
171: #endif DEBUG
172:
173:
174: /*
175: * Grab buffers until we point to the next available one.
176: */
177: while (rnext != getCurrentBuffer(base)) {
178:
179: /*
180: * Point to the receive header in this buffer.
181: */
182: rhdr = (nic_recv_hdr_t *)nic_page_addr(rnext,membase);
183:
184: #ifdef DEBUG
185: if (SMC16_recvTrace) {
186: IOLog("[rstat %02x next %02x len %03x rnext "
187: "%02x bound %02x curr %02x]\n",
188: *(unsigned char *)&rhdr->rstat,
189: rhdr->next, rhdr->len, rnext,
190: get_bound_reg(base), getCurrentBuffer(base));
191: }
192: #endif DEBUG
193:
194:
195: /*
196: * Display a somewhat cryptic message if the prx bit is set.
197: */
198: if (!rhdr->rstat.prx) {
199: IOLog("rhdr1 rstat %02x next %02x len %x\n",
200: *(unsigned char *)&rhdr->rstat, rhdr->next, rhdr->len);
201: [network incrementInputErrors];
202: rnext = rhdr->next;
203: continue;
204: }
205:
206: /*
207: * Display a slightly different, equally cryptic message
208: * if the pointer to the next buffer in this header is outside
209: * the range configured buffers. If this is the case, force a
210: * reset by invoking -timeoutOccurred.
211: */
212: if (rhdr->next >= rstop || rhdr->next < rstart) {
213: IOLog("rhdr2 rstat %02x next %02x len %x\n",
214: *(unsigned char *)&rhdr->rstat, rhdr->next, rhdr->len);
215: [network incrementInputErrors];
216: [self timeoutOccurred];
217: return;
218: }
219:
220: /*
221: * Get the overall packet length and the length between
222: * the start of the packet and the end of onboard memory.
223: * Any packet data beyond that will wrap back to the start
224: * of onboard memory.
225: */
226: pkt_len = rhdr->len - ETHERCRC;
227: pre_wrap_len = nic_page_addr(rstop,membase) -
228: nic_page_addr(rnext,membase) -
229: sizeof (*rhdr);
230:
231: /*
232: * If the packet length looks reasonable, allocate a net buffer
233: * for it and establish a pointer to the data in that net buffer.
234: */
235: if (pkt_len >= (ETHERMINPACKET - ETHERCRC) &&
236: pkt_len <= ETHERMAXPACKET) {
237: pkt = nb_alloc(pkt_len);
238: if (pkt)
239: pkt_data = nb_map(pkt);
240: }
241: else {
242: [network incrementInputErrors];
243: pkt = 0;
244: }
245:
246: /*
247: * If none of the packet wraps around the ring, just
248: * copy it into the netbuf.
249: */
250: if (pkt_len <= pre_wrap_len) {
251: if (pkt)
252: IOCopyMemory(
253: (void *)nic_page_addr(rnext,membase) + sizeof (*rhdr),
254: pkt_data,
255: pkt_len,
256: sizeof(short));
257: /*
258: * Otherwise, copy up to the end of memory, then copy the remaining
259: * portion from the start of memory.
260: */
261: }
262: else {
263: if (pkt) {
264: IOCopyMemory(
265: (void *)nic_page_addr(rnext,membase) + sizeof (*rhdr),
266: pkt_data,
267: pre_wrap_len,
268: sizeof(short));
269: IOCopyMemory(
270: (void *)nic_page_addr(rstart,membase),
271: pkt_data + pre_wrap_len,
272: pkt_len - pre_wrap_len,
273: sizeof(short));
274: }
275: }
276:
277: /*
278: * Increment the ring buffer pointers.
279: */
280: rnext = rhdr->next;
281: if ((rnext - 1) >= rstart)
282: put_bound_reg(rnext - 1, base);
283: else
284: put_bound_reg(rstop - 1, base);
285:
286: /*
287: * We only pass packets upward if they pass thru multicast filter.
288: */
289: if(pkt) {
290: if(rconsave.prom == 0 && [super
291: isUnwantedMulticastPacket:(ether_header_t *)nb_map(pkt)]) {
292: nb_free(pkt);
293: }
294: else {
295:
296: [network handleInputPacket:pkt extra:0];
297:
298: }
299: }
300: }
301:
302: }
303:
304: /*
305: * _receiveOverwriteOccurred
306: * Called when the adaptor tells us that we haven't fetched frames from
307: * onboard memory fast enough, so it's overwritten an old frame with a new
308: * one. Oh well...
309: */
310: - (void)_receiveOverwriteOccurred
311: {
312: #ifdef DEBUG
313: IOLog("overwrite bound %02x curr %02x rnext %02x\n", get_bound_reg(base), getCurrentBuffer(base), rnext);
314: [network incrementInputErrors];
315: #endif DEBUG
316: }
317:
318: /*
319: * _transmitInterruptOccurred
320: * Called when the adaptor indicated a transmit operation is complete. Check
321: * tstat register and increment the appropriate counters. Clear the
322: * timeout we set when we initiated the transmit and clear the transmitActive
323: * flag. Finally, if there are any outgoing packets in the queue, send the
324: * next one.
325: */
326: - (void)_transmitInterruptOccurred
327: {
328: nic_tstat_reg_t tstat_reg;
329: netbuf_t pkt;
330:
331: if (transmitActive) {
332: tstat_reg = get_tstat_reg(base);
333:
334: /*
335: * Always check transmit status (if available) here. On a
336: * transmit error, increment statistics and reset the
337: * adaptor if necessary (not for SMC). NEVER TRY TO
338: * RETRANSMIT A PACKET. Leave this up to higher level
339: * software, which should insure reliability when
340: * it's needed.
341: */
342: if (tstat_reg.ptx)
343: [network incrementOutputPackets];
344: else
345: [network incrementOutputErrors];
346:
347: if (tstat_reg.abort || tstat_reg.twc)
348: [network incrementCollisions];
349:
350: [self clearTimeout];
351: transmitActive = NO;
352: }
353:
354: if (pkt = [transmitQueue dequeue])
355: [self transmit:pkt];
356: }
357:
358: /*
359: * Public Factory Methods
360: */
361:
362: + (BOOL)probe:(IODeviceDescription *)devDesc
363: {
364: SMC16 *dev = [self alloc];
365: IOEISADeviceDescription
366: *deviceDescription = (IOEISADeviceDescription *)devDesc;
367: IORange *io;
368:
369: if (dev == nil)
370: return NO;
371:
372: /*
373: * Valid configuration?
374: */
375: if ( [deviceDescription numPortRanges] < 1
376: ||
377: [deviceDescription numMemoryRanges] < 1
378: ||
379: [deviceDescription numInterrupts] < 1) {
380: [dev free];
381: return NO;
382: }
383:
384: /*
385: * Make sure we're configured for 16K (even though we can only use 8)
386: */
387: io = [deviceDescription memoryRangeList];
388: if (io->size < 16*1024) {
389: [dev free];
390: return NO;
391: }
392:
393: /*
394: * More configuration validation
395: */
396: io = [deviceDescription portRangeList];
397: if (io->size < 16) {
398: [dev free];
399: return NO;
400: }
401:
402: /*
403: * Configuration checks out so let's actually probe for hardware.
404: */
405: if (!checksumLAR(io->start)) {
406: IOLog("SMC16: Adaptor not present or invalid EEROM checksum.\n");
407: [dev free];
408: return NO;
409: }
410:
411: if (!checkBoardRev(io->start)) {
412: IOLog("SMC16: Unsupported board revision.\n");
413: [dev free];
414: return NO;
415: }
416:
417: return [dev initFromDeviceDescription:devDesc] != nil;
418: }
419:
420: /*
421: * Public Instance Methods
422: */
423:
424: - initFromDeviceDescription:(IODeviceDescription *)devDesc
425: {
426: IOEISADeviceDescription
427: *deviceDescription = (IOEISADeviceDescription *)devDesc;
428: IORange *io;
429:
430: if ([super initFromDeviceDescription:devDesc] == nil)
431: return nil;
432:
433: /*
434: * Initialize ivars
435: */
436: irq = [deviceDescription interrupt];
437:
438: io = [deviceDescription portRangeList];
439: base = io->start;
440:
441: io = [deviceDescription memoryRangeList];
442: membase = io->start;
443: memsize = io->size;
444:
445: /*
446: * Broadcasts should be enabled
447: */
448: rconsave.broad = 1;
449:
450: /*
451: * Reset the adaptor, but don't enable yet. We'll receive
452: * -resetAndEnable:YES as a side effect of calling
453: * -attachToNetworkWithAddress:
454: */
455: [self resetAndEnable:NO];
456:
457: IOLog("SMC16 at port %x irq %d\n",base, irq);
458:
459: transmitQueue = [[IONetbufQueue alloc] initWithMaxCount:32];
460:
461: network = [super attachToNetworkWithAddress:myAddress];
462: return self;
463: }
464:
465: - free
466: {
467: [transmitQueue free];
468:
469: return [super free];
470: }
471:
472: - (IOReturn)enableAllInterrupts
473: {
474: unmaskInterrupts(base);
475:
476: setIRQ(irq, YES, base);
477:
478: return [super enableAllInterrupts];
479: }
480:
481: - (void)disableAllInterrupts
482: {
483: setIRQ(irq, NO, base);
484:
485: [super disableAllInterrupts];
486: }
487:
488: - (BOOL)resetAndEnable:(BOOL)enable
489: {
490: [self disableAllInterrupts];
491:
492: transmitActive = NO;
493:
494: [self _initializeHardware];
495:
496: getStationAddress(&myAddress, base);
497:
498: [self _initializeSoftware];
499:
500: if (enable && [self enableAllInterrupts] != IO_R_SUCCESS) {
501: [self setRunning:NO];
502: return NO;
503: }
504:
505: [self setRunning:enable];
506: return YES;
507: }
508:
509: - (void)timeoutOccurred
510: {
511: netbuf_t pkt = NULL;
512:
513: if ([self isRunning]) {
514: if ([self resetAndEnable:YES]) {
515:
516: if (pkt = [transmitQueue dequeue])
517: [self transmit:pkt];
518: }
519: }
520: /*
521: * Value of [self isRunning] may have been modified by
522: * resetAndEnable:
523: */
524: if (![self isRunning]) {
525: /*
526: * Free any packets in the queue since we're not running.
527: */
528: if ([transmitQueue count]) {
529: transmitActive = NO;
530: while (pkt = [transmitQueue dequeue])
531: nb_free(pkt);
532: }
533: }
534: }
535:
536: /*
537: * Called by our IOThread when it receives a message signifying
538: * an interrupt. We check the istat register and vector off
539: * to the appropriate handler routines.
540: */
541: - (void)interruptOccurred
542: {
543: nic_istat_reg_t istat_reg;
544:
545: istat_reg = get_istat_reg(base);
546: put_istat_reg(istat_reg, base);
547:
548: if (istat_reg.ovw)
549: [self _receiveOverwriteOccurred];
550:
551: if (istat_reg.prx)
552: [self _receiveInterruptOccurred];
553:
554: if (istat_reg.ptx || istat_reg.txe)
555: [self _transmitInterruptOccurred];
556: }
557:
558:
559: /*
560: * Enable promiscuous mode (invoked by superclass).
561: */
562: - (BOOL)enablePromiscuousMode
563: {
564: int old_page = sel_reg_page(REG_PAGE0, base);
565:
566: rconsave.prom = 1;
567: put_rcon_reg(rconsave, base);
568: sel_reg_page(old_page, base);
569:
570: return YES;
571: }
572:
573: /*
574: * Disable promiscuous mode (invoked by superclass).
575: */
576: - (void)disablePromiscuousMode
577: {
578: int old_page = sel_reg_page(REG_PAGE0, base);
579:
580: rconsave.prom = 0;
581: put_rcon_reg(rconsave, base);
582: sel_reg_page(old_page, base);
583:
584: }
585:
586:
587: - (BOOL)enableMulticastMode
588: {
589: int old_page = sel_reg_page(REG_PAGE0, base);
590:
591: rconsave.group = 1;
592: put_rcon_reg(rconsave, base);
593: sel_reg_page(old_page, base);
594:
595: return YES;
596: }
597:
598: - (void)disableMulticastMode
599: {
600: int old_page = sel_reg_page(REG_PAGE0, base);
601:
602: rconsave.group = 0;
603: put_rcon_reg(rconsave, base);
604: sel_reg_page(old_page, base);
605:
606: }
607:
608: - (void)transmit:(netbuf_t)pkt
609: {
610: int pkt_len;
611:
612: /*
613: * If we're already transmitting, just queue up the packet.
614: */
615: if (transmitActive)
616: [transmitQueue enqueue:pkt];
617: else {
618:
619: /*
620: * We execute a softare loopback since this adaptor doesn't
621: * deal with this in hardware.
622: */
623: [self performLoopback:pkt];
624:
625: /*
626: * Copy the packet into our transmit buffer, then free it.
627: */
628: pkt_len = nb_size(pkt);
629: IOCopyMemory(
630: nb_map(pkt),
631: (void *)nic_page_addr(tstart,membase),
632: pkt_len,
633: sizeof(short));
634:
635: /*
636: * Once the packet is copied out to the adaptor's onboard RAM,
637: * always free the packet. DON'T SAVE A REFERENCE FOR
638: * RETRANSMISSION PURPOSES. Retransmission should be handled
639: * at the higher levels.
640: */
641: nb_free(pkt);
642:
643: /*
644: * Setup up and initiate the transmit operation
645: */
646: put_tcnt_reg(pkt_len, base);
647: put_tstart_reg(tstart, base);
648: startTransmit(base);
649:
650: /*
651: * Start a timer whose expiration will call -timeoutOccurred, then
652: * set the transmitActive flag so we don't step on this operation.
653: */
654: [self setRelativeTimeout:3000];
655: transmitActive = YES;
656: }
657: }
658:
659:
660: @end
661:
662: /*
663: * Private Functions
664: */
665:
666: static BOOL
667: checksumLAR(
668: IOEISAPortAddress base
669: )
670: {
671: IOEISAPortAddress offset;
672: unsigned char sum = 0;
673:
674: for (offset = BIC_LAR_OFF; offset <= BIC_LAR_CKSUM_OFF; offset++)
675: sum += inb(base + SMC16_BIC_OFF + offset);
676:
677: return (sum == 0xff);
678: }
679:
680: static void
681: getStationAddress(
682: enet_addr_t *ea,
683: IOEISAPortAddress base
684: )
685: {
686: int i;
687: unsigned char *enaddr = (unsigned char *)ea;
688:
689: for (i = 0; i < sizeof (*ea); i++)
690: *(enaddr + i) = inb(base + SMC16_BIC_OFF + BIC_LAR_OFF + i);
691: }
692:
693: static void
694: setStationAddress(
695: enet_addr_t *ea,
696: IOEISAPortAddress base
697: )
698: {
699: int i, old_page;
700: unsigned char *enaddr = (unsigned char *)ea;
701:
702: old_page = sel_reg_page(REG_PAGE1, base);
703:
704: for (i = 0; i < sizeof (*ea); i++)
705: outb(base + SMC16_NIC_OFF + NIC_STA_REG_OFF + i, *(enaddr + i));
706:
707: (void)sel_reg_page(old_page, base);
708: }
709:
710: static BOOL
711: checkBoardRev(
712: IOEISAPortAddress base
713: )
714: {
715: unsigned int bid;
716:
717: bid = get_bid(base);
718:
719: if (SMC16_REV(bid) < 2)
720: return NO;
721:
722: return YES;
723: }
724:
725: static void
726: resetNIC(
727: IOEISAPortAddress base
728: )
729: {
730: bic_msr_t msr = { 0 };
731: nic_istat_reg_t istat_reg;
732:
733: /*
734: * Perform HW Reset of NIC
735: */
736: msr.rst = 1; put_msr(msr, base);
737: IODelay(500);
738: msr.rst = 0; put_msr(msr, base);
739:
740: /*
741: * Wait for NIC to enter stopped state
742: */
743: do {
744: istat_reg = get_istat_reg(base);
745: } while (istat_reg.rst == 0);
746: }
747:
748: static SMC16_len_t
749: setupRAM(
750: vm_offset_t addr,
751: vm_size_t size,
752: IOEISAPortAddress base
753: )
754: {
755: SMC16_len_t total;
756: SMC16_off_t block_addr;
757: bic_laar_t laar;
758: bic_msr_t msr;
759: #ifdef SIXTEEN_BIT_MODE
760: bic_icr_t icr;
761: #endif SIXTEEN_BIT_MODE
762: union {
763: struct {
764: unsigned int :13,
765: madr :6,
766: ladr :5,
767: :8;
768: } bic_addr;
769: struct {
770: unsigned int :16,
771: block :8,
772: :8;
773: } nic_addr;
774: unsigned int address;
775: } _mconv;
776:
777: /*
778: * NOTE: We cannot put the card into 16-bit (and therefore 16K) mode because
779: * the bus interface chip will behave as though a full 64K is mapped, even
780: * though only 16K exists on the board. Needless to say this causes problems,
781: * whether something else is mapped into the top 3/4 of that 64K or not.
782: * Unless the hardware changes, we're limited to using 8K of onboard memory
783: * and 8-bit transfer mode.
784: */
785:
786: #ifdef SIXTEEN_BIT_MODE
787: icr = get_icr(base);
788:
789: total = (icr.msz ? 16 : 64) * 1024;
790:
791: if (total > 16 * 1024)
792: total = 16 * 1024;
793: #else // SIXTEEN_BIT_MODE
794: total = 8 * 1024;
795: #endif SIXTEEN_BIT_MODE
796:
797: if (total > size)
798: total = size;
799:
800: #ifdef DEBUG
801: IOLog("SMC16: using %d bytes of onboard memory\n",total);
802: #endif DEBUG
803:
804: _mconv.address = addr;
805:
806: laar = get_laar(base);
807: #ifdef SIXTEEN_BIT_MODE
808: laar.zws16 = TRUE;
809: laar.l16en = TRUE;
810: laar.m16en = TRUE;
811: #endif SIXTEEN_BIT_MODE
812: laar.ladr = _mconv.bic_addr.ladr;
813: put_laar(laar, base);
814:
815: msr = get_msr(base);
816: msr.madr = _mconv.bic_addr.madr;
817: msr.menb = TRUE;
818: put_msr(msr, base);
819:
820: block_addr = _mconv.nic_addr.block;
821: put_block_reg(block_addr, base);
822:
823: return (total);
824: }
825:
826: static void
827: startNIC(
828: IOEISAPortAddress base,
829: nic_rcon_reg_t rcon_reg
830: )
831: {
832: nic_cmd_reg_t cmd_reg = { 0 };
833: nic_enh_reg_t enh_reg = { 0 };
834: nic_dcon_reg_t dcon_reg = { 0 };
835: nic_tcon_reg_t tcon_reg = { 0 };
836: nic_istat_reg_t istat_reg;
837:
838: enh_reg.slot = NIC_SLOT_512_BIT;
839: enh_reg.wait = 0;
840: put_enh_reg(enh_reg, base);
841:
842: dcon_reg.bsize = NIC_DMA_BURST_8b;
843: #ifdef SIXTEEN_BIT_MODE
844: dcon_reg.bus16 = TRUE;
845: #endif SIXTEEN_BIT_MODE
846: put_dcon_reg(dcon_reg, base);
847:
848: put_tcon_reg(tcon_reg, base);
849:
850: istat_reg = get_istat_reg(base);
851: put_istat_reg(istat_reg, base);
852:
853: cmd_reg.sta = 1;
854: put_cmd_reg(cmd_reg, base);
855:
856: put_rcon_reg(rcon_reg, base);
857: }
858:
859: static void
860: unmaskInterrupts(
861: IOEISAPortAddress base
862: )
863: {
864: nic_imask_reg_t imask_reg = { 0 };
865:
866: /*
867: * Receive conditions
868: */
869: imask_reg.prxe = imask_reg.rxee = imask_reg.ovwe = TRUE;
870:
871: /*
872: * Transmit conditions
873: */
874: imask_reg.ptxe = imask_reg.txee = TRUE;
875:
876: put_imask_reg(imask_reg, base);
877: }
878:
879: static SMC16_off_t
880: getCurrentBuffer(
881: IOEISAPortAddress base
882: )
883: {
884: SMC16_off_t curr;
885: int old_page;
886:
887: old_page = sel_reg_page(REG_PAGE1, base);
888: curr = get_curr_reg(base);
889: if (old_page != REG_PAGE1)
890: sel_reg_page(old_page, base);
891:
892: return (curr);
893: }
894:
895: static void
896: startTransmit(
897: IOEISAPortAddress base
898: )
899: {
900: nic_cmd_reg_t cmd_reg = { 0 };
901:
902: cmd_reg.txp = 1;
903: cmd_reg.sta = 1;
904: put_cmd_reg(cmd_reg, base);
905: }
906:
907: static void
908: setIRQ(
909: int irq,
910: BOOL enable,
911: IOEISAPortAddress base
912: )
913: {
914: bic_irr_t irr;
915: bic_icr_t icr;
916: static char _irx_map[16] = { -1,
917: -1,
918: -1,
919: BIC_IRX_3,
920: BIC_IRX_4,
921: BIC_IRX_5,
922: -1,
923: BIC_IRX_7,
924: -1,
925: BIC_IRX_9,
926: BIC_IRX_10,
927: BIC_IRX_11,
928: -1,
929: -1,
930: -1,
931: BIC_IRX_15 };
932: static char _ir2_map[16] = { -1,
933: -1,
934: -1,
935: ICR_IR2_3,
936: ICR_IR2_4,
937: ICR_IR2_5,
938: -1,
939: ICR_IR2_7,
940: -1,
941: ICR_IR2_9,
942: ICR_IR2_10,
943: ICR_IR2_11,
944: -1,
945: -1,
946: -1,
947: ICR_IR2_15 };
948:
949: irr = get_irr(base);
950: irr.irx = _irx_map[irq];
951: irr.ien = FALSE;
952: put_irr(irr, base);
953:
954: icr = get_icr(base);
955: icr.ir2 = _ir2_map[irq];
956: put_icr(icr, base);
957:
958: irr.ien = enable;
959: put_irr(irr, base);
960: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.