⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ide_old.asm

📁 8051和8255一起控制硬盘读写的程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:
; Simple communication with an IDE disk drive; see http://www.pjrc.com/tech/8051/ide/ for more info; This old code was designed and tested on the old rev 2 board,; which is no longer available.  If you use this code for a; modern hard drive, there may be a bug in the ide_wr routine; where the WR signal is deasserted.  See the newer code if you; are unable to control the drive (but able to read the status; register);  This code is an original work by Paul Stoffregen, written;  in December 1999.  This code has been placed in the;  public domain.  You may use it without any restrictions.;  You may include it in your own projects, even commercial;  (for profit) products.;  This code is distributed in the hope that they will be useful,;  but without any warranty; without even the implied warranty of;  merchantability or fitness for a particular purpose..equ	location, 0x2100	;where this program will exist.equ	buffer, 0x3000		;a 512 byte buffer;------------------------------------------------------------------; Hardware Configuration;8255 chip.  Change these to specify where the 8255 is addressed,;and which of the 8255's ports are connected to which ide signals.;The first three control which 8255 ports have the control signals,;upper and lower data bytes.  The last two are mode setting for the;8255 to configure its ports, which must correspond to the way that;the first three lines define which ports are connected..equ	ide_8255_lsb, 0x4000	;lower 8 bits.equ	ide_8255_msb, 0x4001	;upper 8 bits.equ	ide_8255_ctl, 0x4002	;control lines.equ	cfg_8255, 0x4003.equ	rd_ide_8255, 10010010b	;ide_8255_ctl out, ide_8255_lsb/msb input.equ	wr_ide_8255, 10000000b	;all three ports output;ide control lines for use with ide_8255_ctl.  Change these 8;constants to reflect where each signal of the 8255 each of the;ide control signals is connected.  All the control signals must;be on the same port, but these 8 lines let you connect them to;whichever pins on that port..equ	ide_a0_line, 0x01	;direct from 8255 to ide interface.equ	ide_a1_line, 0x02	;direct from 8255 to ide interface.equ	ide_a2_line, 0x04	;direct from 8255 to ide interface.equ	ide_cs0_line, 0x08	;inverter between 8255 and ide interface.equ	ide_cs1_line, 0x10	;inverter between 8255 and ide interface.equ	ide_wr_line, 0x20	;inverter between 8255 and ide interface.equ	ide_rd_line, 0x40	;inverter between 8255 and ide interface.equ	ide_rst_line, 0x80	;inverter between 8255 and ide interface;------------------------------------------------------------------; More symbolic constants... these should not be changed, unless of; course the IDE drive interface changes, perhaps when drives get; to 128G and the PC industry will do yet another kludge.;some symbolic constants for the ide registers, which makes the;code more readable than always specifying the address pins.equ	ide_data,	ide_cs0_line.equ	ide_err,	ide_cs0_line + ide_a0_line.equ	ide_sec_cnt,	ide_cs0_line + ide_a1_line.equ	ide_sector,	ide_cs0_line + ide_a1_line + ide_a0_line.equ	ide_cyl_lsb,	ide_cs0_line + ide_a2_line.equ	ide_cyl_msb,	ide_cs0_line + ide_a2_line + ide_a0_line.equ	ide_head,	ide_cs0_line + ide_a2_line + ide_a1_line.equ	ide_command,	ide_cs0_line + ide_a2_line + ide_a1_line + ide_a0_line.equ	ide_status,	ide_cs0_line + ide_a2_line + ide_a1_line + ide_a0_line.equ	ide_control,	ide_cs1_line + ide_a2_line + ide_a1_line.equ	ide_astatus,	ide_cs1_line + ide_a2_line + ide_a1_line + ide_a0_line;IDE Command Constants.  These should never change..equ	ide_cmd_recal, 0x10.equ	ide_cmd_read, 0x20.equ	ide_cmd_write, 0x30.equ	ide_cmd_init, 0x91.equ	ide_cmd_id, 0xEC.equ	ide_cmd_spindown, 0xE0.equ	ide_cmd_spinup, 0xE1;------------------------------------------------------------------;internal ram usage.equ	lba, 0x10		;4 bytes, 28 bit Logical Block Address.equ	stack, 0x40;routines within paulmon2.  To make this code stand-alone, just copy;and paste these bits of code from the paulmon2.asm file..equ    cout, 0x0030            ;Send Acc to serial port.equ    cin, 0x0032             ;Get Acc from serial port.equ    phex, 0x0034            ;Print Hex value of Acc.equ    pstr, 0x0038            ;Print string pointed to by DPTR,.equ    upper, 0x0040           ;Convert Acc to uppercase.equ    newline, 0x0048         ;print CR/LF (13 and 10).equ    pint8u, 0x004D          ;print Acc at an integer, 0 to 255.equ    pint16u, 0x0053         ;print DPTR as an integer, 0 to 65535.equ    cin_filter, 0x0062      ;get a character, but look for esc sequences;------------------------------------------------------------------; Main Program, a simple menu driven interface..org	location.db     0xA5,0xE5,0xE0,0xA5     ;signiture bytes.db     35,255,0,0              ;id, 35=program.db     0,0,0,0                 ;reserved.db     0,0,0,0                 ;reserved.db     0,0,0,0                 ;reserved.db     0,0,0,0                 ;reserved.db     0,0,0,0                 ;user defined.db     255,255,255,255         ;length and checksum (255=unused).db     "IDE Disk Drive Test",0.org    location+64             ;executable code begins herebegin:	mov	sp, #stack	mov	dptr, #msg_1	;print a welcome message	lcall	pstr	;initialize the drive.  If there is no drive, this may hang	acall	ide_init	;get the drive id info.  If there is no drive, this may hang	acall	drive_id	; print the drive's model number	mov	dptr, #msg_mdl	lcall	pstr	mov	dptr, #buffer + 60	mov	r0, #40	acall	print_name	lcall	newline	; print the drive's serial number	mov	dptr, #msg_sn	lcall	pstr	mov	dptr, #buffer + 20	mov	r0, #20	acall	print_name	lcall	newline	; print the drive's cylinder, head, and sector specs	mov	dptr, #msg_cy	lcall	pstr	mov	dptr, #buffer + 2	acall	print_parm	mov	dptr, #msg_hd	lcall	pstr	mov	dptr, #buffer + 6	acall	print_parm	mov	dptr, #msg_sc	lcall	pstr	mov	dptr, #buffer + 12	acall	print_parm	lcall	newline	lcall	newline	; default position will be first block (master boot record)	clr	a	mov	lba+0, a	mov	lba+1, a	mov	lba+2, a	mov	lba+3, amain_loop:				;print a 1-line prompt	mov	dptr, #msg_l	lcall	pstr	mov	a, lba+3	lcall	phex	mov	a, lba+2	lcall	phex	mov	a, lba+1	lcall	phex	mov	a, lba+0	lcall	phex	mov	dptr, #msg_pmt	lcall	pstr	lcall	cin	lcall	uppermain1:	cjne	a, #'R', main2		;read a sector	acall	read_sector	jz	main1b	push	acc	mov	dptr, #msg_err	lcall	pstr	pop	acc	lcall	phex	lcall	newline	ajmp	main_loopmain1b:	mov	dptr, #msg_rd	lcall	pstr	ajmp	main_loopmain2:	cjne	a, #'W', main3		;write a sector	mov	dptr, #msg_sure	lcall	pstr	lcall	cin	lcall	upper	cjne	a, #'Y', main2c	acall	write_sector	jz	main2b	push	acc	mov	dptr, #msg_err	lcall	pstr	pop	acc	lcall	phex	lcall	newline	ajmp	main_loopmain2b:	mov	dptr, #msg_wr	lcall	pstrmain2c: ajmp	main_loopmain3:	cjne	a, #'L', main4		;set the logical block address	mov	dptr, #msg_cyh	lcall	pstr	lcall	ghex32_lba	jc	main3b	mov	lba+0, r3	mov	lba+1, r4	mov	lba+2, r5	mov	lba+3, r6main3b:	lcall	newline	ajmp	main_loopmain4:	cjne	a, #'U', main5		;cause the drive to spin up	acall	spinup	ajmp	main_loopmain5:	cjne	a, #'D', main6		;cause the drive to spin down	acall	spindown	ajmp	main_loopmain6:	cjne	a, #'Q', main7		;quit	ljmp	0main7:	cjne	a, #'H', main8	acall	hexdump	ajmp	main_loopmain8:	ajmp	main_loopmsg_1:	.db	"IDE Disk Drive Test Program",13,10,13,10,0msg_mdl:.db	"Model: ",0msg_sn: .db	"S/N:   ",0msg_cy:	.db	"Cylinders: ", 0msg_hd:	.db	", Heads: ", 0msg_sc:	.db	", Sectors: ", 0msg_cyh:.db	"Enter LBA (in hex): ", 0msg_l:	.db	"LBA=0x",0msg_pmt:.db	", (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit",13,10,0msg_sure:.db	"Warning: this will change data on the drive, are you sure?",13,10,0msg_rd:	.db	"Sector Read OK",13,10,0msg_wr:	.db	"Sector Write OK",13,10,0msg_err:.db	"Error, code = ",0;------------------------------------------------------------------; Routines that talk with the IDE drive, these should be called by; the main program.	;read a sector, specified by the 4 bytes in "lba",	;Return, acc is zero on success, non-zero for an errorread_sector:	acall	ide_busy		;make sure drive is ready	acall	wr_lba			;tell it which sector we want	mov	a, #ide_command	mov	r2, #ide_cmd_read	acall	ide_wr			;ask the drive to read it	acall	ide_drq			;wait until it's got the data	jb	acc.0, get_err	mov	dptr, #buffer	acall	read_data		;grab the data	clr	a	ret	;when an error occurs, we get acc.0 set from a call to ide_drq	;or ide_busy (which read the drive's status register).  If	;that error bit is set, we should jump here to read the drive's	;explaination of the error, to be returned to the user.  If for	;some reason the error code is zero (shouldn't happen), we'll	;return 255, so that the main program can always depend on a	;return of zero to indicate success.get_err:mov	a, #ide_err	acall	ide_rd	mov	a, r2	jz	gerr2	retgerr2:	mov	a, #255	ret	;write a sector, specified by the 4 bytes in "lba",	;whatever is in the buffer gets written to the drive!	;Return, acc is zero on success, non-zero for an errorwrite_sector:	acall	ide_busy		;make sure drive is ready	acall	wr_lba			;tell it which sector we want	mov	a, #ide_command	mov	r2, #ide_cmd_write	acall	ide_wr			;tell drive to write a sector	acall	ide_drq			;wait unit it wants the data	jb	acc.0, get_err	mov	dptr, #buffer	acall	write_data		;give the data to the drive	acall	ide_busy		;wait until the write is complete	jb	acc.0, get_err	clr	a	ret	;do the identify drive command, and return with the buffer	;filled with info about the drivedrive_id:	acall	ide_busy	mov	a, #ide_command	mov	r2, #ide_cmd_id	acall	ide_wr	acall	ide_drq	mov	dptr, #buffer	acall	read_data	ret	;tell the drive to spin upspinup:	mov	r2, #ide_cmd_spinupspup2:	mov	a, #ide_command	acall	ide_wr	acall	ide_busy	ret	;tell the drive to spin downspindown:	acall	ide_busy	mov	r2, #ide_cmd_spindown	sjmp	spup2	;initialize the ide driveide_init:	mov	a, #ide_head	mov	r2, #10100000b	acall	ide_wr			;select the master device	mov	a, #ide_status	acall	ide_rd	;mov	a, #'*'	;lcall	cout	mov	a, r2	;should probably check for a timeout here	jnb	acc.6, ide_init		;wait for RDY bit to be set	jb	acc.7, ide_init		;wait for BSY bit to be clear	mov	a, #ide_head	mov	r2, #0x20	acall	ide_wr			;what should this config parm be?	mov	a, #ide_sec_cnt

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -