📄 simple_cdrom_controller.a51
字号:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; A Simple 8051 based ATAPI CDROM audio controller version 0,; Copyright (C) 2000 Jason Nunn <jsno@downunder.net.au>; August 2000;; This software comes under the GNU public license agreement. See the COPYING; file in this distribution.;; If you use this code (or parts) of it, then please credit me.;; 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; either version 2 of the License, or; (at your option) any later version.;; 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.;; Snail: 32 Rothdale Rd; Moil NT 0810; Australia;; WWW: jsno.downunder.net.au;; If you use this code (or parts) of it, then please credit me.;; coded to parse by LA51 assembler (ASM51); current target: DARMICON development board (SAB80C537 @ 12Mhz); (by Felino MOLINA & Howard PULLEN- www.ntu.edu.au);; ====================================================================;; designed for one device only (set to master);; design references:;; - ATA/ATAPI-5 (T13/1321D R3) (www.t10.org); - ATA packet interface for CDROM's (SFF-8020i) (fission.dt.wdc.com);; other references used:;; - linux 2.2.x source code (/usr/src/linux/drivers/ide*); (had to be referred to seens that the SFF-8020i spec is so shitty);; - ATAPI references & Black magic in ATA/ATAPI; by Constantine Sapuntzakis <csapuntz@stanford.edu>; http://www.stanford.edu/~csapuntz/ide.html; http://www.stanford.edu/~csapuntz/blackmagic.html;; - 8052 Basic project page (IDE logger section); by Sergey Zorin <zorinsn@rs-pribor.ru>; http://www.nomad.ee/micros/8052bas.html; (nb/ very very helpful);; - General ATAPI info (including some source code); Hale Landis's ATAPI pages http://www.ata-atapi.com; (a good introduction to it all, as i knew nothing when i first started; this project);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CODE_BASE = 8000h;;delete me;;;;;;;;;;;;;;;;;;;;;;;;;;prhex code 0142hwritechar code 0133hlprint code 0148hprcrlf code 013fh;;delete me;;;;;;;;;;;;;;;;;;;;;;;;;;;ctrl bus;; 7 6 5 4 3 2 1 0;+DA2+DA1+DA0+CS1+CS0+---+---+---+;| X | X | X | X | X | | | |;+---+---+---+---+---+---+---+---+;ATA_ADDR data p1ATA_nDIOR bit p3.0 ;read strobeATA_nDIOW bit p3.1 ;write strobeATA_nRESET bit p3.2ATA_INTRQ bit p3.3 ;irq;data busATA_DATA_LS data p5ATA_DATA_MS data p4; variable data;packet_size data 50hstart_track data 51htmp0 data 52htmp1 data 53htmp2 data 54htmp3 data 55hstart_M data 56hstart_S data 57hstart_F data 58hend_M data 59hend_S data 5ahend_F data 5bhpacket_tab idata 70hpacket_cmd data 70hpacket_1 data 71hpacket_2 data 72hpacket_3 data 73hpacket_4 data 74hpacket_5 data 75hpacket_6 data 76hpacket_7 data 77hpacket_8 data 78hpacket_9 data 79hpacket_10 data 7ahpacket_11 data 7bhpacket_12 data 7chpacket_13 data 7dhpacket_14 data 7ehpacket_15 data 7fhorg CODE_BASE ajmp start;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; atomic routines;; Nb/ code assumes 1us clock cycle (12Mhz xtal clock);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;delay_100000us: mov r7,#0c8hdelay_100000us_l0: mov r6,#0f8hdelay_100000us_l1: djnz r6,delay_100000us_l1 nop djnz r7,delay_100000us_l0 ret;r5 = secondsdelay: acall delay_100000us acall delay_100000us acall delay_100000us acall delay_100000us acall delay_100000us acall delay_100000us acall delay_100000us acall delay_100000us acall delay_100000us acall delay_100000us djnz r5,delay retread_cycle: mov ATA_DATA_LS,#0ffh mov ATA_DATA_MS,#0ffh clr ATA_nDIOR mov a,ATA_DATA_LS mov b,ATA_DATA_MS setb ATA_nDIOR retread_cycle_ls: mov ATA_DATA_LS,#0ffh clr ATA_nDIOR mov a,ATA_DATA_LS setb ATA_nDIOR retwrite_cycle: mov ATA_DATA_LS,a mov ATA_DATA_MS,b clr ATA_nDIOW nop setb ATA_nDIOW retwrite_cycle_ls: mov ATA_DATA_LS,a clr ATA_nDIOW nop setb ATA_nDIOW retwait_irq: setb ATA_INTRQ jnb ATA_INTRQ,wait_irq ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cylinder register;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;get_cyl_high_register: mov ATA_ADDR,#10110000b acall read_cycle_ls retget_cyl_low_register: mov ATA_ADDR,#10010000b acall read_cycle_ls retset_cyl_high_register: mov ATA_ADDR,#10110000b acall write_cycle_ls retset_cyl_low_register: mov ATA_ADDR,#10010000b acall write_cycle_ls ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; a = cmd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;set_cmd_register: mov ATA_ADDR,#11110000b acall write_cycle_ls ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; data register;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ret: a = ls b = msget_data: mov ATA_ADDR,#00010000b acall read_cycle ret; a = ls b = msset_data: mov ATA_ADDR,#00010000b acall write_cycle ret; a = lsset_data_ls: mov ATA_ADDR,#00010000b acall write_cycle_ls ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; device/head register;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;get_devhead_register: mov ATA_ADDR,#11010000b acall read_cycle_ls retset_devhead_register: mov ATA_ADDR,#11010000b acall write_cycle_ls ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; error register;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ERROR_REG_AMNF bit acc.0ERROR_REG_TK0NF bit acc.1ERROR_REG_ABRT bit acc.2ERROR_REG_MCR bit acc.3ERROR_REG_IDNF bit acc.4ERROR_REG_MC bit acc.5ERROR_REG_UNC bit acc.6ERROR_REG_RES bit acc.7get_error_register: mov ATA_ADDR,#00110000b acall read_cycle_ls ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sector register's;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;get_sector_c_register: mov ATA_ADDR,#01010000b acall read_cycle_ls retget_sector_n_register: mov ATA_ADDR,#01110000b acall read_cycle_ls ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; status register;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;STATUS_REG_ERR bit acc.0STATUS_REG_IDX bit acc.1STATUS_REG_CORR bit acc.2STATUS_REG_DRQ bit acc.3STATUS_REG_DSC bit acc.4STATUS_REG_DF bit acc.5STATUS_REG_DRDY bit acc.6STATUS_REG_BSY bit acc.7get_status_register: mov ATA_ADDR,#11110000b acall read_cycle_ls retbsy_wait: nop nop nop nop acall get_status_register jb STATUS_REG_BSY,bsy_wait retbsy_drdy_wait: nop nop nop nop acall delay_100000us acall get_status_register jb STATUS_REG_BSY,bsy_drdy_wait jnb STATUS_REG_DRDY,bsy_drdy_wait retdrq_wait: nop nop nop nop acall get_status_register jb STATUS_REG_BSY,drq_wait jnb STATUS_REG_DRQ,drq_wait retndrq_wait: nop nop nop nop acall get_status_register jb STATUS_REG_BSY,drq_wait jb STATUS_REG_DRQ,drq_wait ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; main routines;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; misc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;print_done: lcall lprint db 'done.',13,10,0 retprint_yes: lcall lprint db 'yes.',13,10,0 retprint_no: lcall lprint db 'no.',13,10,0 ret; clocks data out of buffer until all done (DRQ goes low);skip_rest_of_packet: acall get_status_register jnb STATUS_REG_DRQ,skip_rest_of_packet_d acall get_data sjmp skip_rest_of_packetskip_rest_of_packet_d: retget_MSF_field: acall get_data mov tmp1,b mov a,b lcall prhex mov a,#' ' lcall writechar acall get_data mov tmp2,a mov tmp3,b lcall prhex mov a,#' ' lcall writechar mov a,b lcall prhex lcall prcrlf ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; init ATA device routines..;; also detects the device during the process of initing it.;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;init_ata_device: lcall lprint db 'Initing device...',13,10,0;*;* i've noticed that when using this on one of my CDROM devices (a swank;* little DVD unit-E608 (manufactured by ASUSTek Computer Inc) that the 10k;* pulldown resister (recommended in T13/1321D R3- see P11) pulls DD7 down;* too well, hence causing data loss on this line. i've therefore had to;* remove the resister from the controller design and comment out this;* code. anyone else noticed the same thing????.;*;* Nb/ try uncommenting the code, and put a 10k pulldown on DD7 and see;* what happens.;*;*; sense that a device is connected;*; if device disconnected, then DD7 is pulled down;*;;* lcall lprint;* db 'Device connected?..',0;*;* mov ATA_DATA_LS,#0ffh;* mov a,ATA_DATA_LS;* jb acc.7,init_device_c0;* acall print_no;* sjmp $;*init_device_c0:;* acall print_yes; do hard reset..;; nb/ you have a wait a bit after pulling the reset back high. if you; don't, then bsy flag will falsey pass. i haven't figured out a way; yet to determine when the device controller is busy during hard reset; lcall lprint db 'Hard Reset..',0 clr ATA_nRESET acall delay_100000us setb ATA_nRESET mov r5,#2 acall delay acall bsy_wait acall print_done;select device 0;;the device will now respond to commands now; lcall lprint db 'selecting device 0..',0 acall get_devhead_register clr ATA_DATA_LS.4 ;set device to 0 acall set_devhead_register acall print_done; test for device signature to determine if it's 'packet command' device; if it's not a packet command, then it's probably a harddisk or; something, and we can't continue.;; we have to check this inorder to know if we can issue the 'identify; packet device' ATA command.; lcall lprint db 'ATA Packet device?..',0 acall bsy_wait acall get_cyl_low_register cjne a,#14h,init_device_s_error acall get_cyl_high_register cjne a,#0ebh,init_device_s_error;* acall get_sector_c_register ;code not used due to inconsistencies;* cjne a,#01h,init_device_s_error ;among devices.;* acall get_sector_n_register ;(refer to Black magic in ATA/ATAPI);* cjne a,#01h,init_device_s_error;* acall get_devhead_register;* jz init_device_s_done;* cjne a,#10h,init_device_s_error sjmp init_device_s_doneinit_device_s_error: acall print_no sjmp $init_device_s_done: acall print_yes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -