Subversion Repositories Kolibri OS

Rev

Rev 5363 | Rev 5570 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
2288 clevermous 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 5569 $
9
 
5569 Pathoswith 10
; HDD driver
2288 clevermous 11
 
3742 clevermous 12
struct HD_DATA
13
hdbase  dd      ?
14
hdid    dd      ?
15
hdpos   dd      ?
16
ends
5569 Pathoswith 17
;-----------------------------------------------------------------
3742 clevermous 18
iglobal
2288 clevermous 19
align 4
3742 clevermous 20
ide_callbacks:
5569 Pathoswith 21
        dd      ide_callbacks.end - ide_callbacks   ; strucsize
22
        dd      0   ; no close function
23
        dd      0   ; no closemedia function
3742 clevermous 24
        dd      ide_querymedia
25
        dd      ide_read
26
        dd      ide_write
5569 Pathoswith 27
        dd      0   ; no flush function
28
        dd      0   ; use default cache size
3742 clevermous 29
.end:
2288 clevermous 30
 
3742 clevermous 31
hd0_data        HD_DATA         ?,    0, 1
32
hd1_data        HD_DATA         ?, 0x10, 2
33
hd2_data        HD_DATA         ?,    0, 3
34
hd3_data        HD_DATA         ?, 0x10, 4
4700 mario79 35
hd4_data        HD_DATA         ?,    0, 5
36
hd5_data        HD_DATA         ?, 0x10, 6
37
hd6_data        HD_DATA         ?,    0, 7
38
hd7_data        HD_DATA         ?, 0x10, 8
39
hd8_data        HD_DATA         ?,    0, 9
40
hd9_data        HD_DATA         ?, 0x10, 10
41
hd10_data       HD_DATA         ?,    0, 11
42
hd11_data       HD_DATA         ?, 0x10, 12
4273 clevermous 43
 
4700 mario79 44
ide_mutex_table:
45
        dd ide_channel1_mutex
46
        dd ide_channel2_mutex
47
        dd ide_channel3_mutex
48
        dd ide_channel4_mutex
49
        dd ide_channel5_mutex
50
        dd ide_channel6_mutex
3742 clevermous 51
endg
5569 Pathoswith 52
;-----------------------------------------------------------------
3742 clevermous 53
uglobal
54
ide_mutex               MUTEX
55
ide_channel1_mutex      MUTEX
56
ide_channel2_mutex      MUTEX
4700 mario79 57
ide_channel3_mutex      MUTEX
58
ide_channel4_mutex      MUTEX
59
ide_channel5_mutex      MUTEX
60
ide_channel6_mutex      MUTEX
5569 Pathoswith 61
blockSize:
62
rb 4
63
sector:
64
rb 6
65
allow_dma_access        db ?
66
IDE_common_irq_param    db ?
67
eventPointer            dd ?
68
eventID                 dd ?
3742 clevermous 69
endg
5569 Pathoswith 70
;-----------------------------------------------------------------
71
proc ide_read stdcall uses esi edi ebx, \
3742 clevermous 72
        hd_data, buffer, startsector:qword, numsectors
73
        ; hd_data = pointer to hd*_data
74
        ; buffer = pointer to buffer for data
75
        ; startsector = 64-bit start sector
76
        ; numsectors = pointer to number of sectors on input,
77
        ;  must be filled with number of sectors really read
78
locals
79
sectors_todo    dd      ?
80
channel_lock    dd      ?
81
endl
5569 Pathoswith 82
; get number of requested sectors and say that no sectors were read yet
3742 clevermous 83
        mov     ecx, [numsectors]
84
        mov     eax, [ecx]
85
        mov     dword [ecx], 0
86
        mov     [sectors_todo], eax
5569 Pathoswith 87
; acquire the global lock
3742 clevermous 88
        mov     ecx, ide_mutex
89
        call    mutex_lock
4700 mario79 90
        mov     ecx, [hd_data]
91
        mov     ecx, [ecx+HD_DATA.hdpos]
92
        dec     ecx
93
        shr     ecx, 1
94
        shl     ecx, 2
95
        mov     ecx, [ecx + ide_mutex_table]
3742 clevermous 96
        mov     [channel_lock], ecx
97
        call    mutex_lock
5569 Pathoswith 98
; prepare worker procedures variables
3742 clevermous 99
        mov     ecx, [hd_data]
100
        mov     eax, [ecx+HD_DATA.hdbase]
101
        mov     [hdbase], eax
102
        mov     eax, [ecx+HD_DATA.hdid]
103
        mov     [hdid], eax
104
        mov     eax, [ecx+HD_DATA.hdpos]
105
        mov     [hdpos], eax
106
        mov     eax, dword [startsector]
5569 Pathoswith 107
        mov     [sector], eax
108
        mov     ax, word [startsector+4]
109
        mov     [sector+4], ax
110
        mov     esi, [buffer]
111
        mov     bl, 25h     ; READ DMA EXT
4720 mario79 112
        mov     ecx, [hdpos]
113
        dec     ecx
114
        shr     ecx, 2
115
        imul    ecx, sizeof.IDE_DATA
116
        add     ecx, IDE_controller_1
117
        mov     [IDE_controller_pointer], ecx
118
        mov     eax, [hdpos]
119
        dec     eax
120
        and     eax, 11b
121
        shr     eax, 1
122
        add     eax, ecx
123
        cmp     [eax+IDE_DATA.dma_hdd_channel_1], 1
5569 Pathoswith 124
        jz      .next
125
        dec     bl      ; READ SECTOR(S) EXT
126
        mov     edi, esi
127
; worker procedures take max 8000h sectors per time
128
; loop until all sectors will be processed
129
.next:
130
        mov     ecx, 8000h
131
        cmp     ecx, [sectors_todo]
132
        jbe     @f
133
        mov     ecx, [sectors_todo]
2288 clevermous 134
@@:
5569 Pathoswith 135
        mov     [blockSize], ecx
136
        push    ecx
137
        call    IDE_transfer
138
        pop     ecx
139
        jc      .out
140
        mov     eax, [numsectors]
141
        add     [eax], ecx
142
        sub     [sectors_todo], ecx
143
        jz      .out
144
        add     [sector], ecx
145
        adc     word [sector+4], 0
146
        jmp     .next
147
; loop is done, either due to error or because everything is done
148
; release the global lock and return the corresponding status
149
.out:
150
        sbb     eax, eax
151
        push    eax
3742 clevermous 152
        mov     ecx, [channel_lock]
153
        call    mutex_unlock
154
        mov     ecx, ide_mutex
155
        call    mutex_unlock
5569 Pathoswith 156
        pop     eax
3742 clevermous 157
        ret
158
endp
5569 Pathoswith 159
;-----------------------------------------------------------------
160
proc ide_write stdcall uses esi edi ebx, \
3742 clevermous 161
        hd_data, buffer, startsector:qword, numsectors
162
        ; hd_data = pointer to hd*_data
163
        ; buffer = pointer to buffer with data
164
        ; startsector = 64-bit start sector
165
        ; numsectors = pointer to number of sectors on input,
166
        ;  must be filled with number of sectors really written
167
locals
168
sectors_todo    dd      ?
169
channel_lock    dd      ?
170
endl
5569 Pathoswith 171
; get number of requested sectors and say that no sectors were read yet
3742 clevermous 172
        mov     ecx, [numsectors]
173
        mov     eax, [ecx]
174
        mov     dword [ecx], 0
175
        mov     [sectors_todo], eax
5569 Pathoswith 176
; acquire the global lock
3742 clevermous 177
        mov     ecx, ide_mutex
178
        call    mutex_lock
4700 mario79 179
        mov     ecx, [hd_data]
180
        mov     ecx, [ecx+HD_DATA.hdpos]
181
        dec     ecx
182
        shr     ecx, 1
183
        shl     ecx, 2
184
        mov     ecx, [ecx + ide_mutex_table]
3742 clevermous 185
        mov     [channel_lock], ecx
186
        call    mutex_lock
5569 Pathoswith 187
; prepare worker procedures variables
3742 clevermous 188
        mov     ecx, [hd_data]
189
        mov     eax, [ecx+HD_DATA.hdbase]
190
        mov     [hdbase], eax
191
        mov     eax, [ecx+HD_DATA.hdid]
192
        mov     [hdid], eax
193
        mov     eax, [ecx+HD_DATA.hdpos]
194
        mov     [hdpos], eax
5569 Pathoswith 195
        mov     eax, dword [startsector]
196
        mov     [sector], eax
197
        mov     ax, word [startsector+4]
198
        mov     [sector+4], ax
3742 clevermous 199
        mov     esi, [buffer]
5569 Pathoswith 200
        mov     bl, 35h     ; WRITE DMA EXT
4720 mario79 201
        mov     ecx, [hdpos]
202
        dec     ecx
203
        shr     ecx, 2
204
        imul    ecx, sizeof.IDE_DATA
205
        add     ecx, IDE_controller_1
206
        mov     [IDE_controller_pointer], ecx
207
        mov     eax, [hdpos]
208
        dec     eax
209
        and     eax, 11b
210
        shr     eax, 1
211
        add     eax, ecx
212
        cmp     [eax+IDE_DATA.dma_hdd_channel_1], 1
5569 Pathoswith 213
        jz      .next
214
        dec     bl      ; WRITE SECTOR(S) EXT
215
; worker procedures take max 8000h sectors per time
216
; loop until all sectors will be processed
217
.next:
218
        mov     ecx, 8000h
219
        cmp     ecx, [sectors_todo]
220
        jbe     @f
221
        mov     ecx, [sectors_todo]
222
@@:
223
        mov     [blockSize], ecx
224
        push    ecx
225
        call    IDE_transfer
226
        pop     ecx
227
        jc      .out
3742 clevermous 228
        mov     eax, [numsectors]
229
        add     [eax], ecx
230
        sub     [sectors_todo], ecx
5569 Pathoswith 231
        jz      .out
232
        add     [sector], ecx
233
        adc     word [sector+4], 0
234
        jmp     .next
235
; loop is done, either due to error or because everything is done
236
; release the global lock and return the corresponding status
237
.out:
238
        sbb     eax, eax
239
        push    eax
3742 clevermous 240
        mov     ecx, [channel_lock]
241
        call    mutex_unlock
242
        mov     ecx, ide_mutex
243
        call    mutex_unlock
5569 Pathoswith 244
        pop     eax
3742 clevermous 245
        ret
246
endp
5569 Pathoswith 247
;-----------------------------------------------------------------
248
; this is a stub
3742 clevermous 249
proc ide_querymedia stdcall, hd_data, mediainfo
250
        mov     eax, [mediainfo]
251
        mov     [eax+DISKMEDIAINFO.Flags], 0
252
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
253
        or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
254
        or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
255
        xor     eax, eax
256
        ret
257
endp
5569 Pathoswith 258
;-----------------------------------------------------------------
259
; input: esi -> buffer, bl = command, [sector], [blockSize]
260
; output: esi -> next block in buffer
261
; for pio read esi equal edi
262
IDE_transfer:
3702 mario79 263
        mov     edx, [hdbase]
5569 Pathoswith 264
        add     edx, 6
3702 mario79 265
        mov     al, byte [hdid]
5569 Pathoswith 266
        add     al, 224
267
        out     dx, al  ; select the desired drive
268
        call    save_hd_wait_timeout
269
        inc     edx
270
@@:
271
        call    check_hd_wait_timeout
272
        jc      .hd_error
273
        in      al, dx
274
        test    al, 128 ; ready for command?
275
        jnz     @b
276
        pushfd          ; fill the ports
2288 clevermous 277
        cli
278
        mov     edx, [hdbase]
279
        inc     edx
280
        inc     edx
5569 Pathoswith 281
        mov     al, [blockSize+1]
282
        out     dx, al  ; Sector count (15:8)
2288 clevermous 283
        inc     edx
5569 Pathoswith 284
        mov     eax, [sector+3]
285
        out     dx, al  ; LBA (31:24)
2288 clevermous 286
        inc     edx
287
        shr     eax, 8
5569 Pathoswith 288
        out     dx, al  ; LBA (39:32)
2288 clevermous 289
        inc     edx
290
        shr     eax, 8
5569 Pathoswith 291
        out     dx, al  ; LBA (47:40)
292
        sub     edx, 3
293
        mov     al, [blockSize]
294
        out     dx, al  ; Sector count (7:0)
2288 clevermous 295
        inc     edx
5569 Pathoswith 296
        mov     eax, [sector]
297
        out     dx, al  ; LBA (7:0)
2288 clevermous 298
        inc     edx
3702 mario79 299
        shr     eax, 8
5569 Pathoswith 300
        out     dx, al  ; LBA (15:8)
3702 mario79 301
        inc     edx
302
        shr     eax, 8
5569 Pathoswith 303
        out     dx, al  ; LBA (23:16)
3702 mario79 304
        inc     edx
305
        mov     al, byte [hdid]
5569 Pathoswith 306
        add     al, 224
307
        out     dx, al
308
        test    bl, 1
309
        jz      .PIO
310
; DMA
311
        mov     dword [esp], 0x1000
312
        call    kernel_alloc
313
        mov     edi, eax
314
        push    eax
315
        shl     dword [blockSize], 9
316
        mov     eax, esi
317
        add     eax, [blockSize]
318
        push    eax
319
; check buffer pages physical addresses and fill the scatter-gather list
320
; buffer may be not aligned and may have size not divisible by page size
321
; [edi] = block physical address, [edi+4] = block size in bytes
322
; block addresses can not cross 10000h borders
323
        mov     ecx, esi
324
        and     ecx, 0xFFF
325
        jz      .aligned
326
        mov     eax, esi
327
        call    get_pg_addr
328
        add     eax, ecx
329
        neg     ecx
330
        add     ecx, 0x1000
331
        mov     [edi], eax
332
        cmp     ecx, [blockSize]
333
        jnc     .end
334
        mov     [edi+4], ecx
335
        add     esi, 0x1000
336
        add     edi, 8
337
        sub     [blockSize], ecx
338
.aligned:
339
        mov     eax, esi
340
        call    get_pg_addr
341
        mov     ecx, eax
342
        mov     [edi], eax
343
        and     ecx, 0xFFFF
344
        neg     ecx
345
        add     ecx, 0x10000
346
        cmp     [blockSize], ecx
347
        jnc     @f
348
        mov     ecx, [blockSize]
349
        and     ecx, 0xF000
350
        jz      .end
351
@@:
352
        push    ecx
353
@@:
354
        add     esi, 0x1000
355
        add     eax, 0x1000
356
        sub     ecx, 0x1000
357
        jz      @f
358
        mov     edx, eax
359
        mov     eax, esi
360
        call    get_pg_addr
361
        cmp     eax, edx
362
        jz      @b
363
@@:
364
        pop     edx
365
        sub     edx, ecx
366
        mov     [edi+4], edx
367
        add     edi, 8
368
        sub     [blockSize], edx
369
        jnz     .aligned
370
        sub     edi, 8
371
        jmp     @f
372
.end:
373
        mov     ecx, [blockSize]
374
        mov     [edi+4], ecx
375
@@:
376
        mov     byte [edi+7], 80h   ; list end
377
        pop     esi
378
        pop     edi
379
; select controller Primary or Secondary
380
        mov     ecx, [IDE_controller_pointer]
381
        mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
382
        mov     eax, [hdpos]
383
        dec     eax
384
        test    eax, 10b
385
        jz      @f
386
        add     edx, 8
387
@@:
388
        add     edx, 2      ; Bus Master IDE Status register
389
        mov     al, 6
390
        out     dx, al      ; clear Error bit and Interrupt bit
2288 clevermous 391
 
5569 Pathoswith 392
        add     edx, 2      ; Bus Master IDE PRD Table Address
393
        mov     eax, edi
394
        call    get_pg_addr
395
        out     dx, eax     ; send scatter-gather list physical address
2288 clevermous 396
 
5569 Pathoswith 397
        push    edx
2288 clevermous 398
        mov     edx, [hdbase]
5569 Pathoswith 399
        add     edx, 7      ; ATACommand
400
        mov     al, bl
401
        out     dx, al      ; Start hard drive
402
        pop     edx
2288 clevermous 403
 
5569 Pathoswith 404
        sub     edx, 4      ; Bus Master IDE Command register
405
        mov     al, 1       ; set direction
406
        cmp     bl, 35h     ; write
407
        jz      @f
408
        add     al, 8       ; read
409
@@:
410
        out     dx, al      ; Start Bus Master
411
        mov     [IDE_common_irq_param], 14
412
        mov     eax, [hdpos]
413
        dec     eax
414
        test    eax, 10b
415
        jz      @f
416
        inc     [IDE_common_irq_param]
417
@@:
418
        push    edi esi ebx
419
        xor     ecx, ecx
420
        xor     esi, esi
421
        call    create_event
422
        mov     [eventPointer], eax
423
        mov     [eventID], edx
424
        sti
425
        mov     ebx, edx
426
        mov     ecx, 300
427
        call    wait_event_timeout
428
        test    eax, eax
429
        jnz     @f
430
        mov     [IDE_common_irq_param], 0
431
        mov     eax, [eventPointer]
432
        mov     ebx, [eventID]
433
        call    destroy_event
434
        mov     [eventPointer], 0
435
@@:
436
        pop     ebx esi
437
        call    kernel_free
438
        cmp     [eventPointer], 0
439
        jz      .hd_error
2288 clevermous 440
        ret
5569 Pathoswith 441
.PIO:
442
        inc     edx     ; ATACommand
443
        mov     al, bl
444
        out     dx, al  ; Start hard drive
3881 mario79 445
        popfd
5569 Pathoswith 446
.sectorTransfer:
447
        call    save_hd_wait_timeout
448
        in      al, dx
449
        in      al, dx
450
        in      al, dx
451
        in      al, dx
452
@@:
453
        call    check_hd_wait_timeout
454
        jc      .hd_error
455
        in      al, dx
456
        test    al, 8   ; ready for transfer?
457
        jz      @b
458
        cmp     [hd_setup], 1   ; do not mark error for setup request
459
        jz      @f
460
        test    al, 1   ; previous command ended up with an error
461
        jnz     .hd_error
462
@@:
3712 mario79 463
        pushfd
2288 clevermous 464
        cli
5569 Pathoswith 465
        cld
2288 clevermous 466
        mov     ecx, 256
467
        mov     edx, [hdbase]
5569 Pathoswith 468
        cmp     bl, 34h
469
        jz      .write
470
        rep insw
471
        jmp     @f
472
.write:
2288 clevermous 473
        rep outsw
5569 Pathoswith 474
@@:
3712 mario79 475
        popfd
5569 Pathoswith 476
        add     edx, 7
477
        dec     dword [blockSize]
478
        jnz     .sectorTransfer
2288 clevermous 479
        ret
5569 Pathoswith 480
.hd_error:
481
        cmp     bl, 30h
482
        jnc     hd_write_error
483
;-----------------------------------------------------------------
2288 clevermous 484
hd_read_error:
3712 mario79 485
        if lang eq sp
486
        DEBUGF 1,"K : FS - HD error de lectura\n"
487
        else
488
        DEBUGF 1,"K : FS - HD read error\n"
489
        end if
5569 Pathoswith 490
        stc
2288 clevermous 491
        ret
5569 Pathoswith 492
;-----------------------------------------------------------------
2288 clevermous 493
hd_write_error:
3309 esevece 494
        if lang eq sp
495
        DEBUGF 1,"K : FS - HD error de escritura\n"
496
        else
497
        DEBUGF 1,"K : FS - HD write error\n"
498
        end if
5569 Pathoswith 499
        stc
2288 clevermous 500
        ret
5569 Pathoswith 501
;-----------------------------------------------------------------
502
save_hd_wait_timeout:
503
        mov     eax, [timer_ticks]
504
        add     eax, 300        ; 3 sec timeout
505
        mov     [hd_wait_timeout], eax
2288 clevermous 506
        ret
5569 Pathoswith 507
;-----------------------------------------------------------------
508
check_hd_wait_timeout:
509
        mov     eax, [timer_ticks]
510
        cmp     [hd_wait_timeout], eax
511
        jc      @f
512
        ret
3712 mario79 513
@@:
5569 Pathoswith 514
        if lang eq sp
515
        DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
516
        else
517
        DEBUGF 1,"K : FS - HD timeout\n"
518
        end if
519
        stc
2288 clevermous 520
        ret
5569 Pathoswith 521
;-----------------------------------------------------------------
2288 clevermous 522
align 4
3870 mario79 523
IDE_irq_14_handler:
524
IDE_irq_15_handler:
5569 Pathoswith 525
IDE_common_irq_handler:
526
; DEBUGF  1, 'K : IDE_irq_handler %x\n', [IDE_common_irq_param]:2
527
        cmp     [IDE_common_irq_param], 0
528
        jz      .exit
3870 mario79 529
        pushfd
530
        cli
531
        pushad
4700 mario79 532
        mov     ecx, [IDE_controller_pointer]
533
        mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
5569 Pathoswith 534
        cmp     [IDE_common_irq_param], 14
4291 mario79 535
        jz      @f
3870 mario79 536
        add     dx, 8
537
@@:
5569 Pathoswith 538
        add     edx, 2  ; Bus Master IDE Status register
4291 mario79 539
        in      al, dx
5569 Pathoswith 540
        test    al, 4
4291 mario79 541
        jz      @f
5569 Pathoswith 542
        mov     [IDE_common_irq_param], 0
543
        out     dx, al  ; clear Interrupt bit
4291 mario79 544
        sub     edx, 2
545
        xor     eax, eax
5569 Pathoswith 546
        out     dx, al  ; clear Bus Master IDE Command register
4291 mario79 547
        mov     edx, [hdbase]
5569 Pathoswith 548
        add     edx, 7
549
        in      al, dx  ; read status register
550
        mov     eax, [eventPointer]
551
        mov     ebx, [eventID]
552
        xor     edx, edx
553
        xor     esi, esi
554
        call    raise_event
2288 clevermous 555
        popad
556
        popfd
5569 Pathoswith 557
        mov     al, 1   ; remove the interrupt request
4291 mario79 558
        ret
559
@@:
560
        popad
5569 Pathoswith 561
        popfd
3870 mario79 562
.exit:
5569 Pathoswith 563
        xor     eax, eax    ; not our interrupt
2288 clevermous 564
        ret
5569 Pathoswith 565
;-----------------------------------------------------------------
4578 clevermous 566
proc clear_pci_ide_interrupts
567
        mov     esi, pcidev_list
4700 mario79 568
align 4
4578 clevermous 569
.loop:
570
        mov     esi, [esi+PCIDEV.fd]
571
        cmp     esi, pcidev_list
572
        jz      .done
4700 mario79 573
 
4720 mario79 574
;        cmp     [esi+PCIDEV.class], 0x01018F
575
        mov     eax, [esi+PCIDEV.class]
576
        shr     eax, 4
577
        cmp     eax, 0x01018
4578 clevermous 578
        jnz     .loop
4700 mario79 579
 
4578 clevermous 580
        mov     ah, [esi+PCIDEV.bus]
581
        mov     al, 2
582
        mov     bh, [esi+PCIDEV.devfn]
583
        mov     bl, 0x20
584
        call    pci_read_reg
4700 mario79 585
 
4578 clevermous 586
        and     eax, 0FFFCh
587
        mov     edx, eax
588
        add     edx, 2
589
        in      al, dx
590
        DEBUGF 1,'K : clear_pci_ide_interrupts: port[%x] = %x ',dx,al
591
        out     dx, al
592
        in      al, dx
593
        DEBUGF 1,'-> %x; ',al
594
        add     edx, 8
595
        in      al, dx
596
        DEBUGF 1,'port[%x] = %x ',dx,al
597
        out     dx, al
598
        in      al, dx
599
        DEBUGF 1,'-> %x\n',al
600
        jmp     .loop
601
.done:
602
        ret
603
endp