📄 ide.asm
字号:
acall ide_wr ;do init parameters command acall ide_busy mov a, #ide_command mov r2, #ide_cmd_recal ;do recal command (is this necessary?) acall ide_wr acall ide_busy ret;------------------------------------------------------------------; Not quite as low, low level I/O. These routines talk to the drive,; using the low level I/O. Normally a main program should not call; directly to these. ;Read a block of 512 bytes (one sector) from the drive ;and store it in memory @ DPTRread_data: mov r5, #0rdblk2: push dph push dpl mov a, #ide_data acall ide_rd pop dpl pop dph mov a, r2 movx @dptr, a inc dptr mov a, r3 movx @dptr, a inc dptr djnz r5, rdblk2 ret ;Write a block of 512 bytes (at DPTR) to the drivewrite_data: mov r5, #0wrblk2: clr a movc a, @a+dptr mov r2, a inc dptr clr a movc a, @a+dptr mov r3, a inc dptr push dph push dpl mov a, #ide_data acall ide_wr pop dpl pop dph djnz r5, wrblk2 ret ;write the logical block address to the drive's registerswr_lba: mov a, lba+3 anl a, #0x0F orl a, #0xE0 mov r2, a mov a, #ide_head acall ide_wr mov a, #ide_cyl_msb mov r2, lba+2 acall ide_wr mov a, #ide_cyl_lsb mov r2, lba+1 acall ide_wr mov a, #ide_sector mov r2, lba+0 acall ide_wr mov a, #ide_sec_cnt mov r2, #1 acall ide_wr ret ;Wait for the ide drive to not be busy. ;Returns the drive's status in Accide_busy: mov a, #ide_status ;wait for RDY bit to be set acall ide_rd ;mov a, #'.' ;lcall cout mov a, r2 ;should probably check for a timeout here jb acc.7, ide_busy ret ;Wait for the drive to be ready to transfer data. ;Returns the drive's status in Accide_drq: mov a, #ide_status ;wait for DRQ bit to be set acall ide_rd ;mov a, #'_' ;lcall cout mov a, r2 ;should probably check for a timeout here jb acc.7, ide_drq ;wait for BSY to be clear jnb acc.3, ide_drq ;wait for DRQ to be set ret;------------------------------------------------------------------; Low Level I/O to the drive. These are the routines that talk; directly to the drive, via the 8255 chip. Normally a main; program would not call to these. ;Do a read bus cycle to the drive, using the 8255. This ;is slow, because we have to manipulate the 8255 and use ;the 8051's limited moxv and movx to do it (via dptr). ;Note that the drive is read using MOVC, to run on a board ;where the 8255 is read using PSEN. If your board uses ;RD instead of PSEN, chance the MOVC's to MOVX's. ;input acc = ide regsiter address ;output r2 = lower byte read from ide drive ;output r3 = upper byte read from ide drive ;dptr is changedide_rd: push acc mov dptr, #cfg_8255 mov a, #rd_ide_8255 movx @dptr, a ;config 8255 chip, read mode mov dptr, #ide_8255_ctl pop acc movx @dptr, a ;drive address onto control lines orl a, #ide_rd_line movx @dptr, a ;assert read pin mov dptr, #ide_8255_msb clr a movc a, @a+dptr ;read the upper byte mov r3, a mov dptr, #ide_8255_lsb clr a movc a, @a+dptr ;read the lower byte mov r2, a mov dptr, #ide_8255_ctl clr a movx @dptr, a ;deassert all control pins ret ;Do a write bus cycle to the drive, via the 8255 ;input acc = ide register address ;input r2 = lsb to write ;input r3 = msb to write ;dptr is changedide_wr: push acc mov dptr, #cfg_8255 mov a, #wr_ide_8255 movx @dptr, a ;config 8255 chip, write mode mov dptr, #ide_8255_lsb mov a, r2 movx @dptr, a ;drive lower lines with lsb (r2) mov dptr, #ide_8255_msb mov a, r3 movx @dptr, a ;drive upper lines with msb (r3) mov dptr, #ide_8255_ctl pop acc movx @dptr, a ;drive address onto control lines orl a, #ide_wr_line movx @dptr, a ;assert write pin nop clr a movx @dptr, a ;deassert all control pins mov dptr, #cfg_8255 mov a, #rd_ide_8255 movx @dptr, a ;config 8255 chip, read mode ret ;do a hard reset on the drive, by pulsing its reset pin. ;this should usually be followed with a call to "ide_init".ide_hard_reset: mov dptr, #cfg_8255 mov a, #wr_ide_8255 movx @dptr, a ;config 8255 chip, write mode mov dptr, #ide_8255_ctl mov a, #ide_rst_line movx @dptr, a ;hard reset the disk drive mov r2, #250 djnz r2, * ;delay > 25 us (reset pulse width) clr a movx @dptr, a ;no ide control lines asserted ret;------------------------------------------------------------------; Some additional serial I/O routines not available in PAULMON ;print a 16 bit number, located at DPTRprint_parm: clr a movc a, @a+dptr push acc inc dptr clr a movc a, @a+dptr mov dph, a pop dpl ljmp pint16u ;print a string, no more than R0 chars longprint_name: clr a movc a, @a+dptr jz pn_end lcall cout inc dptr djnz r0, print_namepn_end: ret ;get a 32 bit input, in hexghex32_lba: mov r2, #8 mov r3, #0 mov r4, #0 mov r5, #0 mov r6, #0gh32c: lcall cin_filter lcall upper cjne a, #27, gh32d setb c retgh32d: cjne a, #8, gh32f sjmp gh32kgh32f: cjne a, #127, gh32ggh32k: cjne r2, #8, gh32e sjmp gh32cgh32e: lcall cout mov r0, #4gh32yy: clr c mov a, r6 rrc a mov r6, a mov a, r5 rrc a mov r5, a mov a, r4 rrc a mov r4, a mov a, r3 rrc a mov r3, a djnz r0, gh32yy inc r2 sjmp gh32cgh32g: cjne a, #13, gh32i clr c retgh32i: mov r7, a acall asc2hex jc gh32c xch a, r7 lcall cout mov a, r7 swap a mov r7, a mov r0, #4gh32j: mov a, r7 rlc a mov r7, a mov a, r3 rlc a mov r3, a mov a, r4 rlc a mov r4, a mov a, r5 rlc a mov r5, a mov a, r6 rlc a mov r6, a djnz r0, gh32j djnz r2, gh32c clr c ret ;carry set if invalid inputasc2hex: clr c add a, #208 jnc hex_not add a, #246 jc hex_maybe add a, #10 clr c rethex_maybe: add a, #249 jnc hex_not add a, #250 jc hex_not add a, #16 clr c rethex_not:setb c ret ;print a hexdump of the data in the 512 byte bufferhexdump: lcall newline mov r2, #32 ;print 32 lines mov dptr, #bufferhd1: mov a, dph mov r5, a clr c subb a, #buffer >> 8 lcall phex ;print address, starting at zero mov a, dpl mov r4, a lcall phex mov a, #':' lcall cout acall space mov r3, #16 ;print 16 hex bytes per linehd2: clr a movc a, @a+dptr inc dptr lcall phex ;print each byte in hex acall space djnz r3, hd2 acall space acall space acall space mov dpl, r4 mov dph, r5 mov r3, #16 ;print 16 ascii bytes per linehd3: clr a movc a, @a+dptr inc dptr anl a, #01111111b ;only 7 bits for ascii cjne a, #127, hd3b clr a ;avoid 127/255 (delete/rubout) charhd3b: add a, #224 jc hd3c clr a ;avoid control charactershd3c: add a, #32 lcall cout djnz r3, hd3 lcall newline djnz r2, hd1 lcall newline retspace: mov a, #' ' ljmp cout
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -