-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathtail.asm
708 lines (595 loc) · 17.6 KB
/
tail.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
; PC/FTP Packet Driver source, conforming to version 1.05 of the spec
; Updated to version 1.08 Feb. 17, 1989.
; Copyright 1988-1996 Russell Nelson
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, version 1.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
include defs.asm
code segment word public
assume cs:code, ds:code
public is_eisa
is_eisa db 0 ;=0 if ISA, =1 if EISA
public is_pci
is_pci db 0 ;=0 if PCI, =1 if PCI
extrn sys_features: byte ;bitmask of system features.
extrn is_186: byte ;=0 if 808[68], =1 if 80[1234]86.
extrn is_286: byte ;=0 if 80[1]8[68], =1 if 80[234]86.
extrn is_386: byte ;=0 if 80[12]8[68], =1 if 80[34]86.
extrn int_no: byte ;the board's interrupt level.
extrn hw_int_no: byte ;the 8259 interrupt level.
extrn driver_class: byte ;the class of this driver, per the spec.
extrn rcv_modes: word ;count of modes followed by mode handles.
;-> last byte of static memory used by driver-dependent code.
extrn end_resident: byte
extrn end_free_mem: byte
;-> the fixed address of the card.
extrn rom_address: byte
;-> the current address of the card.
extrn my_address: byte
extrn phd_dioa: byte
extrn phd_environ: word
extrn flagbyte: byte
include printnum.asm
include decout.asm
include digout.asm
include crlf.asm
include chrout.asm
free_mem dw end_resident ;allocate memory from here.
;also see memory_to_keep.
public malloc
malloc:
;enter with dx = amount of memory desired.
;exit with nc, dx -> that memory, or cy if there isn't enough memory.
add dx,free_mem ;make a pointer after that much memory.
cmp dx,offset end_free_mem ;is it still in the free area?
ja malloc_1 ;no, we're in trouble.
xchg dx,free_mem ;get the pointer back, store ptr->end.
clc
ret
malloc_1:
stc
ret
end_tail_1 label byte ; end of the delayed init driver
;usage_msg is of the form "usage: driver [options] <packet_int_no> <args>"
extrn usage_msg: byte
extrn mca_usage_msg: byte
options_i_msg label byte
db" -i -- Force driver to report itself as IEEE 802.3 instead of Ethernet II.",CR,LF
options_msg label byte
db" -d -- Delayed initialization. Used for diskless booting",CR,LF
db" -n -- NetWare conversion. Converts 802.3 packets into 8137 packets",CR,LF
db" -w -- Windows hack, obsoleted by winpkt",CR,LF
db" -p -- Promiscuous mode disable",CR,LF
if M_OPTION
db" -m -- Micronetics MSM compatibility",CR,LF
endif
db" -u -- Uninstall",CR,LF
db '$'
;copyright_msg is of the form:
;"Packet driver for the foobar",CR,LF
;"Portions Copyright 19xx, J. Random Hacker".
extrn copyright_msg: byte
copyleft_msg label byte
db "Packet driver skeleton copyright 1988-96, Crynwr Software.",CR,LF
db "This program is freely copyable; source must be available; NO WARRANTY.",CR,LF
db "See the file COPYING.DOC for details; send FAX to +1-315-268-9201 for a copy.",CR,LF
db CR,LF,'$'
no_resident_msg label byte
db CR,LF,"*** Packet driver failed to initialize the board ***",CR,LF,'$'
;parse_args should parse the arguments.
;called with ds:si -> immediately after the entry_point.
extrn parse_args: near
;print_parameters should print the arguments.
extrn print_parameters: near
extrn our_isr: near, their_isr: dword
extrn entry_point: byte
eisa_signature db "EISA"
system_msg db "System: ",'$'
i386_msg db "[345]86 processor",'$'
i286_msg db "286 processor",'$'
i186_msg db "186 processor",'$'
i8088_msg db "8088/8086 processor",'$'
mca_msg db ", Microchannel bus",'$'
eisa_msg db ", EISA bus",'$'
isa_msg db ", ISA bus",'$'
two_8259_msg db ", Two 8259s",'$'
entry_point_name db "Packet driver software interrupt is ",'$'
eaddr_msg db "My Ethernet address is ",'$'
aaddr_msg db "My ARCnet address is ",'$'
already_msg db CR,LF,"Error: there is already a packet driver (you may uninstall it using -u) at ",'$'
no_pkint_msg db CR,LF,"Error: there is no packet driver at ",'$'
no_pkt_msg db CR,LF,"Error: no packet driver found between 0x60 and 0x80",CR,LF,'$'
two_pkts_msg db CR,LF,"Error: there are two packets drivers (specify the desired one after -u).",CR,LF,'$'
int_msg db CR,LF
db "Error: <hardware_irq> should be between 0 and "
int_msg_num label word
db "15 inclusive", '$'
xt_hd_warn_msg db CR,LF,"Warning: the hard disk on an XT usually uses IRQ 5. Use a different interrupt",CR,LF,'$'
no_ieee_msg db CR,LF,"Error: this driver doesn't implement both IEEE 802.3 and Ethernet II",CR,LF,'$'
terminated_msg db "Uninstall completed",'$'
handle dw ?
entry_point_fnd db 0
bogus_type db 0,0 ;totally bogus type code.
our_recv:
xor di,di
mov es,di
retf
public etopen_diagn
etopen_diagn db 0 ; errorlevel from etopen if set
;etopen should initialize the device. If it needs to give an error, it
;can issue the error message and quit to dos.
extrn etopen: near
memory_to_keep dw end_resident ;keep at least this much memory.
;also see free_mem.
already_error:
mov dx,offset already_msg
already_error_1:
mov di,offset entry_point
call print_number
mov ax,4c05h ; give errorlevel 5
int 21h
usage_error:
mov dx,offset usage_msg
test sys_features,SYS_MCA
je usage_error_1
mov dx,offset mca_usage_msg
usage_error_1:
mov ah,9
int 21h
mov dx,offset options_msg
cmp word ptr driver_class,BLUEBOOK + IEEE8023*256 ;both present?
jne error
mov dx,offset options_i_msg
public error
error:
mov ah,9
int 21h
mov ax,4c0ah ; give errorlevel 10
int 21h
;;; include timeout.asm
public start_1
start_1:
cld
;** First, print a few welcoming messages.
mov dx,offset copyright_msg
mov ah,9
int 21h
mov dx,offset copyleft_msg
mov ah,9
int 21h
mov dx,offset branding_msg
mov ah,9
int 21h
;** Identify the bus type (PCI, EISA, 8-bit ISA, 16-bit ISA, MCA)
xor cx,cx
xor dx,dx
mov ax,0b101h ;PCI BIOS present?
int 1ah
jc not_pci
cmp dx,'P'*256+'C'
jne not_pci
cmp cx,'I'*256+' '
jne not_pci
inc is_pci ;yes.
not_pci:
mov dx,0f000h ;ROM segment
mov es,dx
mov di,0ffd9h
mov si,offset eisa_signature
mov cx,2
repe cmpsw
jne not_eisa
inc is_eisa
not_eisa:
;
; Get the feature byte (if reliable) so we can know if it is a microchannel
; computer and how many interrupts there are.
;
mov ah,0c0h
int 15h ; es:bx <- sys features block
jc look_in_ROM ; error, must use rom.
or ah,ah
jnz look_in_ROM
mov dx,es:[bx] ; # of feature bytes
cmp dx,4 ; do we have the feature byte we want?
jae got_features ;yes.
look_in_ROM:
cmp byte ptr es:[0fffeh],0fch;is this an AT?
jne identified ;no.
or sys_features,TWO_8259 ; ATs have 2nd 8259
jmp short identified ; assume no microchannel
got_features:
mov ah,es:[bx+2] ; model byte
cmp ah,0fch
je at_ps2
ja identified ; FD, FE and FF are not ATs
cmp ah,0f8h
je at_ps2
ja identified ; F9, FA and FB are not ATs
cmp ah,09ah
jbe identified ; old non-AT Compacs go here
at_ps2: ; 9B - F8 and FC are assumed to
mov ah,es:[bx+5] ; have reliable feature byte
mov sys_features,ah
identified:
;** Identify which processor we're running on.
;Determine the processor type. The 8088 and 8086 will actually shift ax
;over by 33 bits, while the 80[123]86 use a shift count mod 32.
mov cl,33
mov ax,0ffffh
shl ax,cl ;186 or better?
jz processor_identified ;no.
mov is_186,1
push sp
pop ax
cmp ax,sp ;286 or better?
jne processor_identified ;no.
mov is_286,1
pushf
pop ax
or ax,7000h ;the 386 lets us set these bits
push ax
popf ;this should be a real popf.
pushf
pop ax
test ax,7000h ;did the bits get set?
je processor_identified
mov is_386,1
processor_identified:
;** Parse the command line.
mov si,offset phd_dioa+1
call skip_blanks ;end of line?
cmp al,CR
je usage_error_j_1
chk_options:
;** Look for -<single-letter> options.
call skip_blanks
cmp al,'-' ; any options?
jne no_more_opt
inc si ; skip past option char
lodsb ; read next char
or al,20h ; convert to lower case
cmp al,'d'
jne not_d_opt
or flagbyte,D_OPTION
jmp chk_options
not_d_opt:
cmp al,'n'
jne not_n_opt
or flagbyte,N_OPTION
jmp chk_options
not_n_opt:
cmp al,'w'
jne not_w_opt
or flagbyte,W_OPTION
jmp chk_options
not_w_opt:
cmp al,'p'
jne not_p_opt
cmp rcv_modes,6 ;do they even *have* a promiscuous mode?
jbe chk_options ;no.
mov rcv_modes+2[6*2],0 ;yes, nuke it.
jmp chk_options
not_p_opt:
cmp al,'u'
jne not_u_opt
or flagbyte,U_OPTION
jmp chk_options
not_u_opt:
if M_OPTION
cmp al,'m'
jne not_m_opt
or flagbyte,M_OPTION
jmp chk_options
not_m_opt:
endif
cmp al,'i'
jne not_i_opt
cmp word ptr driver_class,BLUEBOOK + IEEE8023*256 ;both present?
mov dx,offset no_ieee_msg
jne usage_error_j_1 ;no - give error
mov word ptr driver_class,IEEE8023 + BLUEBOOK*256 ;yes, swap them.
jmp chk_options
not_i_opt:
usage_error_j_1:
jmp usage_error
no_more_opt:
;** get the packet driver interrupt number.
mov di,offset entry_point ;parse the packet interrupt number
call get_number ; for them.
;** see if they wanted to terminate the existing driver.
test flagbyte,U_OPTION ;should we terminate the driver?
jne terminate
jmp not_terminate
terminate:
cmp entry_point,0 ;did they ask for the default?
jne terminate_int_ok ;no, run with it.
;**Look for the existing packet driver interrupt
mov entry_point,60h
terminate_check_int:
call verify_packet_int
jc terminate_check_int_1
jne terminate_check_int_1
cmp entry_point_fnd,0 ;did we already find one?
jne terminate_check_int_2 ;yes, it's ambiguous - give error.
mov al,entry_point ;no, remember it.
mov entry_point_fnd,al
terminate_check_int_1:
inc entry_point ;go look at the next one
cmp entry_point,80h
jbe terminate_check_int ;keep going to the end.
mov al,entry_point_fnd ;restore the last one found.
mov entry_point,al
cmp entry_point_fnd,0 ;did we find one?
jne terminate_int_ok ;yes.
mov dx,offset no_pkt_msg ;no packet drivers installed!
jmp error
terminate_check_int_2:
mov dx,offset two_pkts_msg ;two packet drivers - which one??
jmp error
terminate_int_ok:
call verify_packet_int ;is the one they specified acceptable?
jnc terminate_1 ;no, it's not in range.
jmp error
terminate_1:
je terminate_2 ;go if we found a signature.
mov dx,offset no_pkint_msg ;no packet driver there.
jmp already_error_1
terminate_2:
mov their_isr.offs,bx
mov their_isr.segm,es
mov ax,1ffh ;driver_info
pushf
cli
call their_isr
call fatal_error
movseg ds,cs
mov ah,2 ;access_type
mov al,ch ;their class from driver_info().
mov bx,dx ;their type from driver_info().
mov dl,cl ;their number from driver_info().
mov cx,2 ;use type length 2.
mov si,offset bogus_type
movseg es,cs
mov di,offset our_recv
pushf
cli
call their_isr
call fatal_error
mov handle,ax
mov ah,5 ;terminate the driver.
mov bx,handle
pushf
cli
call their_isr
jnc now_close
call print_error
mov ah,3 ;release_type
mov bx,handle
pushf
cli
call their_isr
int 20h
now_close:
mov dx,offset terminated_msg
mov ah,9
int 21h
int 20h
usage_error_j_2:
jmp usage_error
not_terminate:
;** ask the driver to parse any remaining parameters.
call parse_args
jc usage_error_j_2
call skip_blanks ;end of line?
cmp al,CR
jne usage_error_j_2
call verify_packet_int
jnc packet_int_ok
jmp error
packet_int_ok:
jne packet_int_unused
jmp already_error ;give an error if there's one there.
packet_int_unused:
;** Verify that the hardware interrupt number they gave is valid.
cmp int_no,15 ;can't possibly be > 15.
ja int_bad
test sys_features,TWO_8259 ; 2nd 8259 ?
jnz int_ok ;yes, no need to check for <= 7.
mov int_msg_num,'7'+' '*256 ;correct the error message, just in case.
cmp int_no,7 ;make sure that the packet interrupt
jbe int_ok_7 ; number is in range.
int_bad:
mov dx,offset int_msg
jmp error
int_ok_7:
;** IRQ 5 on an XT is not available -- it's used by the hard disk.
cmp int_no,5 ;Are they trying to use irq 5 on an XT?
jne int_ok ;no.
push ds
mov ax,40h
mov ds,ax
mov al,ds:[75h] ;get the number of hard disks.
pop ds
or al,al ;do they have one?
je int_ok ;unbelievably, no.
mov dx,offset xt_hd_warn_msg
mov ah,9
int 21h
int_ok:
;
; Map IRQ 2 to IRQ 9 if needed.
;
test sys_features,TWO_8259 ; 2nd 8259 ?
je no_mapping_needed ;no, no mapping needed
cmp int_no,2 ;map IRQ 2 to IRQ 9.
jne no_mapping_needed
mov int_no,9
no_mapping_needed:
; If they chose the -d option, don't call etopen when we are loaded,
; but when we are called for the first time
;
; Save part of the tail, needed by delayed etopen
test flagbyte,D_OPTION
jz open_now
mov memory_to_keep,offset end_tail_1 ; save first part of tail
jmp delayed_open_1
open_now:
call etopen ;init the driver. If any errors,
;this routine returns cy.
jnc yes_resident
jmp no_resident
yes_resident:
;** etopen has set rom_address to their hardware address. Set our copy of
;** the current address.
mov si,offset rom_address ;copy their original address to
movseg es,ds
mov di,offset my_address ; their current address.
mov cx,MAX_ADDR_LEN/2
rep movsw
;** tell them what kind of system they have.
mov dx,offset system_msg
mov ah,9
int 21h
mov dx,offset i386_msg
cmp is_386,0
jne have_processor
mov dx,offset i286_msg
cmp is_286,0
jne have_processor
mov dx,offset i186_msg
cmp is_186,0
jne have_processor
mov dx,offset i8088_msg
have_processor:
mov ah,9
int 21h
mov dx,offset mca_msg
test sys_features,SYS_MCA
jne have_bus
mov dx,offset eisa_msg
cmp is_eisa,0
jne have_bus
mov dx,offset isa_msg
have_bus:
mov ah,9
int 21h
test sys_features,TWO_8259
je only_one_8259
mov dx,offset two_8259_msg
mov ah,9
int 21h
only_one_8259:
call crlf
mov di,offset entry_point
mov dx,offset entry_point_name
call print_number
call print_parameters ;echo our parameters.
or flagbyte,CALLED_ETOPEN
cmp driver_class,BLUEBOOK ;Blue Book Ethernet?
je print_eaddr ;yes.
cmp driver_class,IEEE8023 ;IEEE 802.3 Ethernet?
jne print_addr_2 ;no, don't print what we don't have.
print_eaddr:
mov dx,offset eaddr_msg
mov ah,9
int 21h
mov si,offset rom_address
call print_ether_addr
call crlf
print_addr_2:
cmp driver_class,8 ;ARCnet?
jne print_addr_3 ;no, don't print what we don't have.
mov dx,offset aaddr_msg
mov ah,9
int 21h
mov al,rom_address
mov cl,' ' ;Don't eliminate leading zeroes.
call byteout
call crlf
print_addr_3:
delayed_open_1:
;** Take care of installing ourselves in memory.
mov ah,35h ;remember their packet interrupt.
mov al,entry_point
int 21h
mov their_isr.offs,bx
mov their_isr.segm,es
mov ah,25h ;install our packet interrupt
mov dx,offset our_isr
int 21h
mov ah,49h ;free our environment, because
mov es,phd_environ ; we won't need it.
int 21h
mov bx,1 ;get the stdout handle.
mov ah,3eh ;close it in case they redirected it.
int 21h
test flagbyte,D_OPTION
jne f_release_type_1 ;no.
cmp rcv_modes+2[3*2],0 ;does mode 3 exist?
je f_release_type_1 ;no.
call rcv_modes+2[3*2] ; call it.
f_release_type_1:
mov dx,memory_to_keep ;keep the greater of this and
cmp dx,free_mem ; free_mem.
jae go_resident
mov dx,free_mem
go_resident:
add dx,0fh ;round up to next highest paragraph.
mov cl,4
shr dx,cl
mov ah,31h ;terminate, stay resident.
mov al,etopen_diagn ; errorlevel (0 - 9, just diagnostics)
int 21h
no_resident:
mov ah,9 ;print their error message.
int 21h
mov dx,offset no_resident_msg
mov ah,9
int 21h
mov ax,4c00h + 32 ; give errorlevel 32
cmp al,etopen_diagn
ja no_et_diagn ; etopen gave specific reason?
mov al,etopen_diagn ; yes, use that for error level
no_et_diagn:
int 21h
; Suggested errorlevels:
;
; _____________________ 0 = normal
; 1 = unsuitable memory address given; corrected
; In most cases every- 2 = unsuitable IRQ level given; corrected
; thing should work as 3 = unsuitable DMA channel given; corrected
; expected for lev 1-5 4 = unsuitable IO addr given; corrected (only 1 card)
; _____________________ 5 = packet driver for this int # already loaded
; External errors, when 20 = general cable failure (but pkt driver is loaded)
; corrected normal 21 = network cable is open -"-
; operation starts 22 = network cable is shorted -"-
; _____________________ 23 =
; Packet driver not 30 = usage message
; loaded. A new load 31 = arguments out of range
; attempt must be done 32 = unspecified device initialization error
; 33 =
; 34 = suggested memory already occupied
; 35 = suggested IRQ already occupied
; 36 = suggested DMA channel already occupied
; 37 = could not find the network card at this IO address
include verifypi.asm
include getnum.asm
include getdig.asm
include skipblk.asm
include printea.asm
include pkterr.asm
include getenv.asm
public branding_msg
branding_msg db '$'
code ends
end