Source File 1 : 'prucode1.p' (430 Instructions Generated) 1 : : #define CYCLE_CNTR r5 2 : : // This code handles for disk reads getting the MFM bitstream from DDR 3 : : // memory and converting it to pulse width modulation (PWM) words for PRU 0. 4 : : // For write it takes the delta time between MFM transitions, decodes it into 5 : : // clock and data bits and updates the bitstream in the DDR memory. 6 : : // 7 : : // See comments in prucode0.p for more information. 8 : : // 9 : : // The read and write data goes through a circular buffer in shared memory 10 : : // which allows time for the DMA start code to run. 11 : : // Tests show reads can be delayed up to 5 microseconds (1000 cycles). To 12 : : // deal with that the data if fetch using DMA. Two buffers are used. When one 13 : : // buffer is empty and the second is 1/2 empty we start the next DMA. We need 14 : : // to back up when a write starts since we have processed some words 15 : : // that were queued for PRU0. At the end of the write we will need to skip 16 : : // forward some to stay in sync with rotation. 17 : : // 18 : : // Writes seem much better with delays around 200 cycles. Writes are 19 : : // posted which reduces the delay. If we get behind in writes 20 : : // we will corrupt the track. Words need to be written faster than 40 21 : : // cycles (200 ns) on average. 22 : : // Clock is about 200 MHz, 5 nanoseconds. It will be adjusted to generate 23 : : // the desired bit rate. 24 : : 25 : : // An entire cylinder is stored in the DDR memory. If the head select 26 : : // lines are changed PRU 0 will tell us to restart sending data and we 27 : : // will calculate the correct location to send the data from. PRU 0 28 : : // will tell us the starting bit of the write data. We mark the cylinder 29 : : // dirty so the ARM can write it back to disk. 30 : : // PRU 0 handles getting the data updated if the controller selects another 31 : : // cylinder. 32 : : // 33 : : // TODO: Comments haven't all been fixed for the DMA changes. 34 : : // 35 : : // See prucode0.p for information on the transfer memory registers and 36 : : // communication between the two PRU's. 37 : : 38 : : // See mfm_emu.c for PRU1_BIT_TABLE format. 39 : : 40 : : // 41 : : // 11/20/15 DJG Fixed occasional abort due to data not being ready by 42 : : // increasing WRITE_READ_TIME 43 : : // 05/20/15 DJG Significant change to switch to DMA (on PRU1) for reading 44 : : // from DRAM and how data is syncronized to simulated rotation time. 45 : : // 01/04/15 DJG Added logic to allow bit rate to be varied and the 46 : : // index pulse shifted relative to the start of the data. When end of 47 : : // track is reached we wrap without needing a handshake between the PRU 48 : : // and restarting read. 49 : : // 50 : : // Copyright 2014 David Gesswein. 51 : : // This file is part of MFM disk utilities. 52 : : // 53 : : // MFM disk utilities is free software: you can redistribute it and/or modify 54 : : // it under the terms of the GNU General Public License as published by 55 : : // the Free Software Foundation, either version 3 of the License, or 56 : : // (at your option) any later version. 57 : : // 58 : : // MFM disk utilities is distributed in the hope that it will be useful, 59 : : // but WITHOUT ANY WARRANTY; without even the implied warranty of 60 : : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 61 : : // GNU General Public License for more details. 62 : : // 63 : : // You should have received a copy of the GNU General Public License 64 : : // along with MFM disk utilities. If not, see . 65 : : 66 : : .setcallreg r19.w0 67 : : #define RETREG r19 68 : : 69 : : .origin 0 70 : : .entrypoint START 71 : : 72 : : #include "prucode.hp" 73 : : 74 : : #include "inc/cmd.h" 75 : : 76 : : // These are registers that are used globally. Check registers defined in 77 : : // cmd.h if looking for free registers. 78 : : 79 : : // Value 32 80 : : #define CONST_32 r7.b3 81 : : #define NEXT_DMA_WCOUNT r7.w0 82 : : #define NEXT_DMA_WCOUNT_MSB 15 83 : : // r8 PRU1_BUF_STATE 84 : : // r9 PRU0_BUF_STATE 85 : : // Current offset into DDR memory. Not updated during read 86 : : #define DDR_OFFSET r10 87 : : // Words in DDR memory left to process in track 88 : : #define WORDS_LEFT r11 89 : : // r12 unused 90 : : // Address in PRU RAM DMA buffer 91 : : #define BUF_ADDR r13 92 : : // Current data word processing from DDR 93 : : #define WORD1 r14 94 : : // Next data word processing 95 : : #define WORD2 r15 96 : : // r16 unused 97 : : // Total number of bytes in track (need to change LBCO if changed to w0) 98 : : #define TRACK_BYTES r17 99 : : // r18 TRACK_BIT 100 : : // r19.w0 call return addr, r19.w2 save call return 101 : : // r20 is DRIVE_DATA 102 : : // Count of bits in track. Must be in byte field 103 : : #define BIT_COUNT r21.b2 104 : : #define BIT_COUNT_MSB 7 105 : : // Clocks in a MFM clock/data bit cell 106 : : #define BIT_PRU_CLOCKS r21.b1 107 : : // Threshold for detecting zero bit cell 108 : : #define ZERO_THRESHOLD r21.b0 109 : : // Offset from start of DDR memory of track data 110 : : #define TRACK_OFFSET r22 111 : : // Physical address of start of DDR memory 112 : : #define DDR_ADDR r23 113 : : // r24-r29 subroutine usage 114 : : 115 : : // Overwritten when multiply used 116 : : // Base address of EDMA registers 117 : : #define EDMA_BASE r26 118 : : // EDMA channel to use 119 : : #define EDMA_PARAM_BASE r27 120 : : // EDMA channel to use 121 : : #define EDMA_CHANNEL r28 122 : : 123 : : 124 : : // DMA buffers are 64 bytes/16 words. Must be power of 2 and <= 128 125 : : #define DMA_SIZE 64 126 : : // Must be on 256 byte boundry 127 : : #define READ_BUF_1_ADDR 0x400 128 : : #define READ_BUF_2_ADDR (READ_BUF_1_ADDR + DMA_SIZE) 129 : : 130 : : // Time in PRU clocks from write end to output read data 131 : : #define WRITE_READ_TIME 2900/5 132 : : // Time from read time requested to bits we generate 133 : : // 8.5 microseconds in PRU clocks. This allows for completing DMA 134 : : #define NEW_READ_TIME 8500/5 135 : : 136 : : 137 : : START: 138 : : // Enable OCP master port 139 : 0x0000 0x91042480 : LBCO r0, CONST_PRUCFG, 4, 4 140 : : // Clear SYSCFG[STANDBY_INIT] to enable OCP master port 141 : 0x0001 0x1d04e0e0 : CLR r0, r0, 4 142 : 0x0002 0x81042480 : SBCO r0, CONST_PRUCFG, 4, 4 143 : : 144 : : // Configure the programmable pointer register by setting c25_pointer[15:0] 145 : : // field to 0x0020. This will make C25 point to 0x00002000 (Other PRU RAM). 146 : 0x0003 0x240020e0 : MOV r0, 0x00000020 147 : 0x0004 0x240002c4 : MOV r4, PRU1_CONTROL | CTBIR : 0x0005 0x24402084 : 148 : 0x0006 0xe1002480 : SBBO r0, r4, 0, 4 149 : : // Configure the programmable pointer register for PRU0 by setting 150 : : // c31_pointer[15:0] field to 0x0010. This will make C31 point to 151 : : // 0x80001000 (DDR memory). Configure the programmable pointer register 152 : : // for PRU0 by setting c28_pointer[15:0] field to 0x0100. This will 153 : : // make C28 point to 0x00010000 (PRU shared RAM). 154 : 0x0007 0x240100e0 : MOV r0, 0x00000100 155 : 0x0008 0x240002c4 : MOV r4, PRU1_CONTROL | CTPPR_0 : 0x0009 0x24402884 : 156 : 0x000a 0xe1002480 : SBBO r0, r4, 0, 4 157 : : 158 : : // Configure the programmable pointer register for PRU0 by setting 159 : : // c31_pointer[15:0] field to 0x0010. This will make C31 point to 160 : : // 0x80001000 (DDR memory). 161 : 0x000b 0x240010c0 : MOV r0, 0x00100000 : 0x000c 0x24000080 : 162 : 0x000d 0x240002c4 : MOV r4, PRU1_CONTROL | CTPPR_1 : 0x000e 0x24402c84 : 163 : 0x000f 0xe1002480 : SBBO r0, r4, 0, 4 164 : : 165 : : // Get address and size of DDR buffer. Currently we don't use size 166 : 0x0010 0x91003897 : LBCO DDR_ADDR, CONST_PRURAM, PRU_DDR_ADDR, 4 167 : : //LBCO DDR_SIZE, CONST_PRURAM, PRU_DDR_SIZE, 4 168 : : 169 : 0x0011 0x240000e2 : MOV r2, 0 170 : 0x0012 0x81383882 : SBCO r2, CONST_PRURAM, PRU1_BAD_PATTERN_COUNT, 4 171 : 0x0013 0x810c3882 : SBCO r2, CONST_PRURAM, PRU_TEST0, 4 172 : 0x0014 0x81103882 : SBCO r2, CONST_PRURAM, PRU_TEST1, 4 173 : 0x0015 0x81143882 : SBCO r2, CONST_PRURAM, PRU_TEST2, 4 174 : 0x0016 0x81183882 : SBCO r2, CONST_PRURAM, PRU_TEST3, 4 175 : 0x0017 0x811c3882 : SBCO r2, CONST_PRURAM, PRU_TEST4, 4 176 : : 177 : 0x0018 0x81303882 : SBCO r2, CONST_PRURAM, PRU1_DRIVE0_TRK_DIRTY, 4 178 : 0x0019 0x81343882 : SBCO r2, CONST_PRURAM, PRU1_DRIVE1_TRK_DIRTY, 4 179 : : 180 : : // Configure DMA 181 : : 182 : : // Load base addresses into registers 183 : 0x001a 0x244900da : MOV EDMA_BASE, EDMA0_CC_BASE : 0x001b 0x2400009a : 184 : 0x001c 0x916c389c : LBCO EDMA_CHANNEL, CONST_PRURAM, PRU1_DMA_CHANNEL, 4 // Read channel 185 : : 186 : : // Setup EDMA region access for Shadow Region 1 187 : 0x001d 0x240000e4 : MOV r4, 0 188 : : // Bit mask for channel. Only works for channels < 32 189 : 0x001e 0x1efce4e4 : SET r4, EDMA_CHANNEL 190 : 0x001f 0x240348e2 : MOV R2, DRAE1 191 : 0x0020 0xe0e23a84 : SBBO r4, EDMA_BASE, R2, 4 // Region 1 192 : : 193 : : // DCHMAP_# is set by system 194 : : 195 : : // Clear channel event from EDMA event registers 196 : 0x0021 0x241040e3 : MOV r3, GLOBAL_SECR 197 : 0x0022 0xe0e33a84 : SBBO r4, EDMA_BASE, r3, 4 198 : 0x0023 0x241070e3 : MOV r3, GLOBAL_ICR 199 : 0x0024 0xe0e33a84 : SBBO r4, EDMA_BASE, r3, 4 200 : 0x0025 0x241050e3 : MOV r3, GLOBAL_IER 201 : 0x0026 0xf0e33a80 : LBBO r0, EDMA_BASE, r3, 4 202 : : // Disable channel interrupt 203 : 0x0027 0x241058e3 : MOV r3, GLOBAL_IECR 204 : 0x0028 0xe0e33a84 : SBBO r4, EDMA_BASE, r3, 4 205 : : // Enable shadow 1 interrupt. Interrupts don't save time since 206 : : // Syncronizing write to clear interrupt takes as much time as 207 : : // just polling. 208 : : // MOV r3, IESRL 209 : : // SBBO r4, EDMA_BASE, r3, 4 210 : : 211 : : // Clear event missed register 212 : 0x0029 0x240308e3 : MOV r3, EMCR 213 : 0x002a 0xe0e33a84 : SBBO r4, EDMA_BASE, r3, 4 214 : : 215 : : 216 : : // Setup and store PaRAM data for transfer 217 : 0x002b 0x0905fcfb : LSL EDMA_PARAM_BASE, EDMA_CHANNEL, 5 // channel*32 218 : 0x002c 0x244000e4 : MOV r4, PARAM_OFFSET 219 : 0x002d 0x00e4fbfb : ADD EDMA_PARAM_BASE, EDMA_PARAM_BASE, r4 220 : : // Address of our channel PaRAM 221 : 0x002e 0x00fafbfb : ADD EDMA_PARAM_BASE, EDMA_PARAM_BASE, EDMA_BASE 222 : : 223 : : // Build initial DMA descriptors. They will be modifed by dma routines 224 : : // First entry OPT TCC = channel, enable transfer complete interrupt 225 : : // SRC will be set later 226 : : // ACNT = DMA_SIZE, BCNT = 1, 227 : : // DST = buffer 1 228 : : // SRC, DST BIDX = 0 229 : : // LINK = next PaRAM set, BCNTRLD = 0 230 : : // CCNT = 1 231 : 0x002f 0x090cfce0 : LSL r0, EDMA_CHANNEL, 12 232 : 0x0030 0x1310c0c0 : OR r0.w2, r0.w2, 0x10 233 : 0x0031 0xe1003b80 : SBBO r0, EDMA_PARAM_BASE, OPT, 4 234 : : // This will be updated when submitted 235 : 0x0032 0xe1043b97 : SBBO DDR_ADDR, EDMA_PARAM_BASE, SRC, 4 236 : 0x0033 0x240040e0 : MOV r0, DMA_SIZE 237 : 0x0034 0xe1081b80 : SBBO r0, EDMA_PARAM_BASE, A_B_CNT, 2 238 : 0x0035 0x240001e0 : MOV r0, 1 239 : 0x0036 0xe10a1b80 : SBBO r0, EDMA_PARAM_BASE, A_B_CNT+2, 2 240 : 0x0037 0x240400e0 : MOV r0, READ_BUF_1_ADDR 241 : 0x0038 0x91083881 : LBCO r1, CONST_PRURAM, PRU_DATARAM_ADDR, 4 242 : 0x0039 0x00e1e0e0 : ADD r0, r0, r1 243 : 0x003a 0xe10c3b80 : SBBO r0, EDMA_PARAM_BASE, DST, 4 244 : 0x003b 0x240000e0 : MOV r0, 0 245 : 0x003c 0xe1103b80 : SBBO r0, EDMA_PARAM_BASE, SRC_DST_BIDX, 4 246 : 0x003d 0x0120fbe0 : ADD r0, EDMA_PARAM_BASE, 32 247 : 0x003e 0x240000c0 : MOV r0.w2, 0 248 : 0x003f 0xe1143b80 : SBBO r0, EDMA_PARAM_BASE, LINK_BCNTRLD, 4 249 : 0x0040 0x240000e0 : MOV r0, 0 250 : 0x0041 0xe1183b80 : SBBO r0, EDMA_PARAM_BASE, SRC_DST_CIDX, 4 251 : 0x0042 0x240001e0 : MOV r0, 1 252 : 0x0043 0xe11c1b80 : SBBO r0, EDMA_PARAM_BASE, CCNT, 2 253 : : 254 : 0x0044 0x0120fbfb : ADD EDMA_PARAM_BASE, EDMA_PARAM_BASE, 32 // Go to next entry 255 : : 256 : : // Second entry OPT TCC = channel, enable transfer complete interrupt 257 : : // SRC will be set later 258 : : // ACNT = DMA_SIZE, BCNT = 1, 259 : : // DST = buffer 2 260 : : // SRC, DST BIDX = 0 261 : : // LINK = next PaRAM set, BCNTRLD = 0 262 : : // CCNT = 1 263 : 0x0045 0x090cfce0 : LSL r0, EDMA_CHANNEL, 12 264 : 0x0046 0x1310c0c0 : OR r0.w2, r0.w2, 0x10 //TCINTEN and TCC = PruDmaChannel 265 : 0x0047 0xe1003b80 : SBBO r0, EDMA_PARAM_BASE, OPT, 4 266 : : // This will be updated when submitted 267 : 0x0048 0xe1043b97 : SBBO DDR_ADDR, EDMA_PARAM_BASE, SRC, 4 268 : 0x0049 0x240040e0 : MOV r0, DMA_SIZE 269 : 0x004a 0xe1081b80 : SBBO r0, EDMA_PARAM_BASE, A_B_CNT, 2 270 : 0x004b 0x240001e0 : MOV r0, 1 271 : 0x004c 0xe10a1b80 : SBBO r0, EDMA_PARAM_BASE, A_B_CNT+2, 2 272 : 0x004d 0x240400e0 : MOV r0, READ_BUF_1_ADDR 273 : 0x004e 0x91083881 : LBCO r1, CONST_PRURAM, PRU_DATARAM_ADDR, 4 274 : 0x004f 0x00e1e0e0 : ADD r0, r0, r1 275 : 0x0050 0xe10c3b80 : SBBO r0, EDMA_PARAM_BASE, DST, 4 276 : 0x0051 0x240000e0 : MOV r0, 0 277 : 0x0052 0xe1103b80 : SBBO r0, EDMA_PARAM_BASE, SRC_DST_BIDX, 4 278 : : // Reload from this entry 279 : 0x0053 0x10fbfbe0 : MOV r0, EDMA_PARAM_BASE 280 : 0x0054 0x240000c0 : MOV r0.w2, 0 281 : 0x0055 0xe1143b80 : SBBO r0, EDMA_PARAM_BASE, LINK_BCNTRLD, 4 282 : 0x0056 0x240000e0 : MOV r0, 0 283 : 0x0057 0xe1183b80 : SBBO r0, EDMA_PARAM_BASE, SRC_DST_CIDX, 4 284 : 0x0058 0x240001e0 : MOV r0, 1 285 : 0x0059 0xe11c1b80 : SBBO r0, EDMA_PARAM_BASE, CCNT, 2 286 : : 287 : 0x005a 0x0120fbfb : ADD EDMA_PARAM_BASE, EDMA_PARAM_BASE, 32 288 : : 289 : : // Set multiply only mode. Only needs to be done once 290 : 0x005b 0x240000f9 : MOV r25, 0 291 : 0x005c 0x2f000019 : XOUT 0, r25, 1 292 : : 293 : 0x005d 0x91643895 : LBCO ZERO_THRESHOLD, CONST_PRURAM, PRU1_ZERO_BIT_THRESHOLD, 4 294 : 0x005e 0x916838b5 : LBCO BIT_PRU_CLOCKS, CONST_PRURAM, PRU1_BIT_PRU_CLOCKS, 4 295 : : 296 : : // Local memory starts at address 0 in memory map 297 : 0x005f 0x24002067 : MOV CONST_32, 32 298 : : 299 : 0x0060 0x240000e8 : MOV PRU1_BUF_STATE, 0 300 : : // Default to first drive 301 : 0x0061 0x240000f4 : MOV DRIVE_DATA, 0 302 : : 303 : : // Track timer 304 : 0x0062 0x240002c5 : MOV CYCLE_CNTR, PRU0_CONTROL | CYCLE : 0x0063 0x24200c85 : 305 : : 306 : : wait_read: 307 : : //SET r30, 0 308 : : // Wait for PRU0, exit if requested. 309 : 0x0064 0x24000568 : MOV PRU1_STATE, STATE_READ_DONE 310 : 0x0065 0x24000088 : MOV PRU1_BUF_OFFSET, 0 311 : 0x0066 0x2f050188 : XOUT 10, PRU1_BUF_STATE, 4 312 : : wait_read_lp: 313 : 0x0067 0x2e850189 : XIN 10, PRU0_BUF_STATE, 4 314 : 0x0068 0x530a6942 : QBEQ DONE, PRU0_STATE, STATE_EXIT 315 : 0x0069 0x6f0269fe : QBNE wait_read_lp, PRU0_STATE, STATE_READ 316 : : 317 : : // Get offset to drive data for selected drive 318 : 0x006a 0x2e850194 : XIN 10, DRIVE_DATA, 4 319 : : // Get track byte count and convert to words, all must be same 320 : 0x006b 0xf1583491 : LBBO TRACK_BYTES, DRIVE_DATA, PRU1_DRIVE0_TRACK_DATA_BYTES, 4 321 : : 322 : 0x006c 0x240000ea : MOV DDR_OFFSET, 0 323 : 0x006d 0x5100f403 : QBEQ drive_0, DRIVE_DATA, 0 324 : : // Address of second drive data 325 : 0x006e 0x240008ca : MOV DDR_OFFSET, DDR_DRIVE_BUFFER_MAX_SIZE : 0x006f 0x2400008a : 326 : : drive_0: 327 : 0x0070 0x0b02f1eb : LSR WORDS_LEFT, TRACK_BYTES, 2 // divide by 4 to get words 328 : : 329 : : // Calculate start of track by multiply head by track size in bytes 330 : : // and add in header size to get start address of data 331 : : // Get current head from PRU 0 332 : 0x0071 0x9148399d : LBCO r29, CONST_PRURAM_OTHER, PRU0_CUR_HEAD, 4 333 : 0x0072 0x10f1f1fc : MOV r28, TRACK_BYTES 334 : 0x0073 0xf1503480 : LBBO r0, DRIVE_DATA, PRU1_DRIVE0_TRACK_HEADER_BYTES, 4 335 : 0x0074 0x00e0eaea : ADD DDR_OFFSET, DDR_OFFSET, r0 // Point after header 336 : 0x0075 0x00e0fcfc : ADD r28, r28, r0 337 : 0x0076 0x10fcfcfc : MOV r28, r28 // NOP, multiply has one cycle latency 338 : 0x0077 0x2e80039a : XIN 0, r26, 8 // Get multiply results (27,26=28*29) 339 : 0x0078 0x00faeaea : ADD DDR_OFFSET, DDR_OFFSET, r26 // Point to our head track 340 : 0x0079 0x10eaeaf6 : MOV TRACK_OFFSET, DDR_OFFSET 341 : : 342 : : 343 : : // Fetch track time and convert to word offset in r4 and 344 : : // track bit in r27 345 : 0x007a 0xf1002580 : LBBO r0, CYCLE_CNTR, 0, 4 // get track rotation time 346 : 0x007b 0x81fc3880 : SBCO r0, CONST_PRURAM, 0xfc, 4 347 : : 348 : : // Give us enough time to get the bits out. PRU0 will start 349 : : // outputting at this time. 350 : 0x007c 0x2406a4e1 : MOV r1, NEW_READ_TIME 351 : 0x007d 0x00e1e0e0 : ADD r0, r0, r1 352 : : 353 : 0x007e 0x2300d293 : CALL convert_track_time // r4 word offset, r27 bit count 354 : 0x007f 0x0902e4e0 : LSL r0, r4, 2 // Convert word offset to byte 355 : 0x0080 0x00e0f6ea : ADD DDR_OFFSET, TRACK_OFFSET, r0 // Add offset into track 356 : 0x0081 0x04e4ebeb : SUB WORDS_LEFT, WORDS_LEFT, r4 // Get how many words left 357 : : // Convert byte offset from start of track to bits to determine where 358 : : // we start sending data. 359 : 0x0082 0x04f6eaf2 : SUB TRACK_BIT, DDR_OFFSET, TRACK_OFFSET 360 : 0x0083 0x0903f2f2 : LSL TRACK_BIT, TRACK_BIT, 3 // In bytes, convert to bits 361 : 0x0084 0x111ffbe6 : AND r6, r27, 0x1f // Get how many bits into first word 362 : 0x0085 0x00e6f2f2 : ADD TRACK_BIT, TRACK_BIT, r6 363 : 0x0086 0x2f050192 : XOUT 10, TRACK_BIT, 4 // And tell PRU 0 start bit of data 364 : 0x0087 0x24000368 : MOV PRU1_STATE, STATE_READ_BIT_SET 365 : 0x0088 0x2f050188 : XOUT 10, PRU1_BUF_STATE, 4 366 : 0x0089 0x24000088 : MOV PRU1_BUF_OFFSET, 0 // Start filling at first location 367 : : 368 : 0x008a 0x240080e2 : MOV r2, DMA_SIZE*2 369 : 0x008b 0x240400e3 : MOV r3, READ_BUF_1_ADDR 370 : 0x008c 0x10eaeae4 : MOV r4, DDR_OFFSET 371 : 0x008d 0x23015993 : CALL start_dma 372 : 0x008e 0x23019493 : CALL wait_dma 373 : : 374 : 0x008f 0x240400ed : MOV BUF_ADDR, READ_BUF_1_ADDR 375 : : // DMA half way through second buffer. DMA_SIZE is in bytes but we 376 : : // count words. 377 : 0x0090 0x24001887 : MOV NEXT_DMA_WCOUNT, DMA_SIZE/4 + DMA_SIZE/8 378 : : restart_read: 379 : 0x0091 0x24001f55 : MOV BIT_COUNT, 31 // 32 bits to process, negative stop 380 : 0x0092 0x90ed788e : LBCO WORD1, CONST_PRURAM, BUF_ADDR, 8 // Get WORD1,WORD2 381 : : // Increment by two words we read 382 : 0x0093 0x2300e593 : CALL update_dma 383 : 0x0094 0x2300e593 : CALL update_dma 384 : : 385 : 0x0095 0xf1002580 : LBBO r0, CYCLE_CNTR, 0, 4 // get time 386 : 0x0096 0x81f43880 : SBCO r0, CONST_PRURAM, 0xf4, 4 387 : : 388 : : // Do shift to get proper bit to start of word. 389 : 0x0097 0x5100e607 : QBEQ noshift, r6, 0 390 : 0x0098 0x08e6eeee : LSL WORD1, WORD1, r6 391 : 0x0099 0x04e667e0 : SUB r0, CONST_32, r6 392 : 0x009a 0x0ae0efe2 : LSR r2, WORD2, r0 // High bits to move to WORD1 393 : 0x009b 0x12e2eeee : OR WORD1, WORD1, r2 394 : 0x009c 0x08e6efef : LSL WORD2, WORD2, r6 // And move next bits to top 395 : 0x009d 0x04e65555 : SUB BIT_COUNT, BIT_COUNT, r6 396 : : noshift: 397 : : // Clear the next to top most bit so we can't get a decoding 398 : : // error. Bit isn't critical so changing it won't mess up 399 : : // emulation. 400 : 0x009e 0x1d1eeeee : CLR WORD1, 30 401 : : 402 : : // TODO This is a little slow, ~150 ns/output word 200ns is limit 403 : : bitloop: 404 : 0x009f 0x0b1ceee0 : LSR r0, WORD1, 28 // Get upper 4 bits of MFM data 405 : 0x00a0 0x0902e0e0 : LSL r0, r0, 2 // Make byte address of word 406 : 0x00a1 0xf1802080 : LBBO r0, r0, PRU1_BIT_TABLE, 4 // Lookup next PWM word 407 : 0x00a2 0x80883c80 : SBCO r0, CONST_PRUSHAREDRAM, PRU1_BUF_OFFSET, 4 // Store it 408 : 0x00a3 0x01048888 : ADD PRU1_BUF_OFFSET, PRU1_BUF_OFFSET, 4 // Move to next location 409 : : // Wrap if needed 410 : 0x00a4 0x111f8888 : AND PRU1_BUF_OFFSET, PRU1_BUF_OFFSET, SHARED_PWM_READ_MASK 411 : 0x00a5 0x2f050188 : XOUT 10, PRU1_BUF_STATE, 4 // Send our offset 412 : 0x00a6 0xc918e004 : QBBC noerr, r0, 24 413 : 0x00a7 0x91383882 : LBCO r2, CONST_PRURAM, PRU1_BAD_PATTERN_COUNT, 4 414 : 0x00a8 0x0101e2e2 : ADD r2, r2, 1 415 : 0x00a9 0x81383882 : SBCO r2, CONST_PRURAM, PRU1_BAD_PATTERN_COUNT, 4 416 : : noerr: 417 : 0x00aa 0x0b1ce0e4 : LSR r4, r0, 28 // Get shift count 418 : : 419 : : // Here we shift WORD1, WORD2 by r4. If we use up all bits in WORD2 420 : : // we read another word into WORD2 and possibly shift it to correct 421 : : // position. 422 : 0x00ab 0x08e4eeee : LSL WORD1, WORD1, r4 423 : : // This entry is used to move bits from WORD2 after read into WORD1 424 : : shift_word2: 425 : 0x00ac 0x04e467e0 : SUB r0, CONST_32, r4 426 : 0x00ad 0x0ae0efe2 : LSR r2, WORD2, r0 // High bits to move to WORD1 427 : 0x00ae 0x12e2eeee : OR WORD1, WORD1, r2 428 : 0x00af 0x08e4efef : LSL WORD2, WORD2, r4 // And move next bits to top 429 : 0x00b0 0x04e45555 : SUB BIT_COUNT, BIT_COUNT, r4 430 : 0x00b1 0xc907550a : QBBC waitfree, BIT_COUNT, BIT_COUNT_MSB // Branch if bits left in WORD1 431 : 0x00b2 0x0501ebeb : SUB WORDS_LEFT, WORDS_LEFT, 1 432 : 0x00b3 0x5100eb10 : QBEQ finished, WORDS_LEFT, 0 // Branch if no words left 433 : : 434 : : read_next_word: 435 : : // Get next word and update pointer 436 : 0x00b4 0x90ed388f : LBCO WORD2, CONST_PRURAM, BUF_ADDR, 4 437 : 0x00b5 0x2300e593 : CALL update_dma 438 : : 439 : : // If bitcount is -1 then shift done. Otherwise we need to 440 : : // fix the bits that didn't get shifted into WORD1 441 : 0x00b6 0x51ff5504 : QBEQ waitfree_setbit_count, BIT_COUNT, 255 442 : : // Number of bits we need to shift into WORD1 443 : 0x00b7 0x15ff55e4 : XOR r4, BIT_COUNT, 255 444 : 0x00b8 0x24001f55 : MOV BIT_COUNT, 31 // 32 bits to process 445 : 0x00b9 0x2100ac00 : JMP shift_word2 446 : : waitfree_setbit_count: 447 : 0x00ba 0x24001f55 : MOV BIT_COUNT, 31 // 32 bits to process 448 : : // Check to see if space is available before doing next word 449 : : waitfree: 450 : : // Get current read location and state of pru 0. If no longer 451 : : // read go handle. Wait for room 452 : 0x00bb 0x2e850189 : XIN 10, PRU0_BUF_STATE, 4 453 : 0x00bc 0x69026920 : QBNE check_write, PRU0_STATE, STATE_READ 454 : 0x00bd 0x6e8889e2 : QBNE bitloop, PRU0_BUF_OFFSET, PRU1_BUF_OFFSET 455 : : // Indicate buffer has data and PRU 0 can start PWM generation 456 : 0x00be 0x24000468 : MOV PRU1_STATE, STATE_READ_FILLED 457 : 0x00bf 0x2f050188 : XOUT 10, PRU1_BUF_STATE, 4 458 : 0x00c0 0xf1002580 : LBBO r0, CYCLE_CNTR, 0, 4 // get time 459 : 0x00c1 0x81f83880 : SBCO r0, CONST_PRURAM, 0xf8, 4 460 : 0x00c2 0x2100bb00 : JMP waitfree 461 : : 462 : : // Write a zero word to buffer to indicate end of data for track 463 : : finished: 464 : 0x00c3 0x1f00fefe : SET r30, 0 465 : 0x00c4 0x2e850189 : XIN 10, PRU0_BUF_STATE, 4 // Get current read location pru 0 466 : 0x00c5 0x69026917 : QBNE check_write, PRU0_STATE, STATE_READ // Handle state change 467 : 0x00c6 0x50888909 : QBEQ finished_full, PRU0_BUF_OFFSET, PRU1_BUF_OFFSET // no room wait 468 : 0x00c7 0x240000e2 : MOV r2, 0 // Zero marks end of PWM words 469 : 0x00c8 0x80883c82 : SBCO r2, CONST_PRUSHAREDRAM, PRU1_BUF_OFFSET, 4 // Store it 470 : 0x00c9 0x01048888 : ADD PRU1_BUF_OFFSET, PRU1_BUF_OFFSET, 4 // Move to next location 471 : : // Wrap if needed 472 : 0x00ca 0x111f8888 : AND PRU1_BUF_OFFSET, PRU1_BUF_OFFSET, SHARED_PWM_READ_MASK 473 : 0x00cb 0x2f050188 : XOUT 10, PRU1_BUF_STATE, 4 474 : 0x00cc 0x0b02f1eb : LSR WORDS_LEFT, TRACK_BYTES, 2 // divide by 4 to get words 475 : 0x00cd 0x1d00fefe : CLR r30, 0 476 : : #ifdef CHECK_MAGIC 477 : : mov r0, BUF_ADDR 478 : : SUB r0.b0, r0.b0, 4 479 : : AND r0.b0, r0.b0, (DMA_SIZE*2-1) 480 : : LBCO WORD2, CONST_PRURAM, r0, 4 481 : : MOV r2, 0x80808080 482 : : QBEQ read_next_word, r2, WORD2 483 : : LBBO r1, CYCLE_CNTR, 0, 4 // get time 484 : : HALT // Not magic word 485 : : #endif 486 : 0x00ce 0x2100b400 : JMP read_next_word // Start from beginning of track 487 : : finished_full: 488 : : // Indicate buffer has data and PRU 0 can start PWM generation 489 : 0x00cf 0x24000468 : MOV PRU1_STATE, STATE_READ_FILLED 490 : 0x00d0 0x2f050188 : XOUT 10, PRU1_BUF_STATE, 4 491 : 0x00d1 0x2100c300 : JMP finished 492 : : 493 : : // Convert time to track bit and offset from start of track 494 : : // r0: time to convert 495 : : // Out: 496 : : // r4 = offset from start of track 497 : : // r27 = track bit count 498 : : // r26-r29 modified 499 : : convert_track_time: 500 : : // Divide by r0 bit period. We multiply by 1/bit_period 501 : : // scaled by 2^32 then divide the result by 2^32. 502 : 0x00d2 0x9160389d : LBCO r29, CONST_PRURAM, PRU1_INV_BIT_PERIOD_S32, 4 503 : 0x00d3 0x10e0e0fc : MOV r28, r0 504 : 0x00d4 0x10fcfcfc : MOV r28, r28 // NOP, multiply has one cycle latency 505 : 0x00d5 0x2e80039a : XIN 0, r26, 8 // Get multiply results (27,26=28*29) 506 : : // Convert to word offset, divide by 2^5 (32), Also doing divide 2^32 507 : : // by using upper 32 bits of multiply result 508 : 0x00d6 0x0b05fbe4 : LSR r4, r27, 5 509 : : // Convert back to bytes for check 510 : 0x00d7 0x0902e4e4 : LSL r4, r4, 2 511 : : // If more words than in data wrap 512 : 0x00d8 0x48e4f102 : QBLT convert_ret, TRACK_BYTES, r4 513 : 0x00d9 0x04f1e4e4 : SUB r4, r4, TRACK_BYTES 514 : : convert_ret: 515 : : // And back to words 516 : 0x00da 0x0b02e4e4 : LSR r4, r4, 2 517 : 0x00db 0x20930000 : RET 518 : : 519 : : // See if switch to write or terminated was requested. If not restart read. 520 : : check_write: 521 : 0x00dc 0x510a69ce : QBEQ DONE, PRU0_STATE, STATE_EXIT 522 : : // If PRU 0 stopped read restart, wait_read sets state to done 523 : 0x00dd 0x57056987 : QBEQ wait_read, PRU0_STATE, STATE_READ_DONE 524 : 0x00de 0x51066917 : QBEQ do_write, PRU0_STATE, STATE_WRITE_WAIT 525 : 0x00df 0x240001d8 : MOV r24, (1 << GPIO1_TEST) : 0x00e0 0x24000098 : 526 : 0x00e1 0x244804d9 : MOV r25, GPIO1 | GPIO_SETDATAOUT : 0x00e2 0x24c19499 : 527 : 0x00e3 0xe1003998 : SBBO r24, r25, 0, 4 528 : 0x00e4 0x2a000000 : HALT 529 : : 530 : : // Update memory pointers for word read and start DMA if needed 531 : : // r26-29 modified from check_dma and start_dma 532 : : update_dma: 533 : 0x00e5 0x2f058980 : XOUT 11, r0, 20 // Save r0-r4 534 : : // Update pointer 535 : 0x00e6 0x01040d0d : ADD BUF_ADDR.b0, BUF_ADDR.b0, 4 536 : 0x00e7 0x117f0d0d : AND BUF_ADDR.b0, BUF_ADDR.b0, (DMA_SIZE*2-1) 537 : 0x00e8 0x05018787 : SUB NEXT_DMA_WCOUNT, NEXT_DMA_WCOUNT, 1 538 : 0x00e9 0xd10f8702 : QBBS need_dma, NEXT_DMA_WCOUNT, NEXT_DMA_WCOUNT_MSB // Negative 539 : 0x00ea 0x69008709 : QBNE no_dma, NEXT_DMA_WCOUNT, 0 540 : : need_dma: 541 : : // Save return address before we do another call 542 : 0x00eb 0x2f058193 : XOUT 11, RETREG, 4 543 : : 544 : 0x00ec 0x23019d93 : CALL check_dma 545 : : // DMA next buffer 546 : 0x00ed 0x240040e2 : MOV r2, DMA_SIZE 547 : 0x00ee 0x91703883 : LBCO r3, CONST_PRURAM, PRU1_NEXT_DMA_RAM_OFFSET, 4 548 : 0x00ef 0x91743884 : LBCO r4, CONST_PRURAM, PRU1_NEXT_DMA_DDR_OFFSET, 4 549 : 0x00f0 0x23015993 : CALL start_dma 550 : 0x00f1 0x2e858193 : XIN 11, RETREG, 4 551 : : // Schedule next dma 552 : 0x00f2 0x01108787 : ADD NEXT_DMA_WCOUNT, NEXT_DMA_WCOUNT, DMA_SIZE/4 // 4 to get words 553 : : no_dma: 554 : 0x00f3 0x2e858980 : XIN 11, r0, 20 // restore r0-r4 555 : 0x00f4 0x20930000 : RET 556 : : 557 : : do_write: 558 : : // Mark data dirty so ARM can write it to disk. 559 : 0x00f5 0xf1303480 : LBBO r0, DRIVE_DATA, PRU1_DRIVE0_TRK_DIRTY, 4 560 : 0x00f6 0x91483981 : LBCO r1, CONST_PRURAM_OTHER, PRU0_CUR_HEAD, 4 561 : 0x00f7 0x1ee1e0e0 : SET r0, r0, r1 562 : 0x00f8 0xe1303480 : SBBO r0, DRIVE_DATA, PRU1_DRIVE0_TRK_DIRTY, 4 563 : : // Get bit location write starts from and tell PRU 0 we are ready 564 : 0x00f9 0x2e850192 : XIN 10, TRACK_BIT, 4 565 : 0x00fa 0x24000668 : MOV PRU1_STATE, STATE_WRITE_WAIT 566 : 0x00fb 0x24000088 : MOV PRU1_BUF_OFFSET, 0 // Set to start of buffer 567 : 0x00fc 0x2f050188 : XOUT 10, PRU1_BUF_STATE, 4 568 : : // Wait for PRU 0 to go to write state 569 : : write_wait_lp: 570 : 0x00fd 0x2e850189 : XIN 10, PRU0_BUF_STATE, 4 571 : 0x00fe 0x6f0769ff : QBNE write_wait_lp, PRU0_STATE, STATE_WRITE 572 : 0x00ff 0x24000768 : MOV PRU1_STATE, STATE_WRITE 573 : 0x0100 0x2f050188 : XOUT 10, PRU1_BUF_STATE, 4 574 : : 575 : 0x0101 0x0b05f2ea : LSR DDR_OFFSET, TRACK_BIT, 5 // Convert bit count to word count 576 : : 577 : 0x0102 0x10eaeae2 : MOV r2, DDR_OFFSET 578 : 0x0103 0x23014393 : CALL find_buf_loc 579 : : 580 : : // Now convert to bit in word. We count from msb bit = 31 - remainder 581 : 0x0104 0x111ff255 : AND BIT_COUNT, TRACK_BIT, 0x1f // Remainder 582 : 0x0105 0x24001fe0 : MOV r0, 31 583 : 0x0106 0x0455e055 : SUB BIT_COUNT, r0, BIT_COUNT 584 : : // Convert DDR_OFFSET in words to bytes and add to start of track to 585 : : // get offset of words we're writing. 586 : 0x0107 0x0902eaea : LSL DDR_OFFSET, DDR_OFFSET, 2 587 : 0x0108 0x00f6eaea : ADD DDR_OFFSET, DDR_OFFSET, TRACK_OFFSET 588 : : // Clear WORD1 & 2. WORD1 will be a mask of the bits write didn't change 589 : : // WORD2 the changed bits. We need this to combine the modified 590 : : // bits with the unmodified bits in the word at the start and end of 591 : : // the write. 592 : 0x0109 0x2eff018e : FILL &WORD1, 4 593 : 0x010a 0x2eff818f : ZERO &WORD2, 4 594 : : #ifdef bolix 595 : : LBCO r0, CONST_PRURAM, BUF_ADDR, 4 // Get word 596 : : LBBO r1, DDR_ADDR, DDR_OFFSET, 4 597 : : QBEQ delta_loop, r0, r1 598 : : MOV r24, (1 << GPIO1_TEST) 599 : : MOV r25, GPIO1 | GPIO_SETDATAOUT 600 : : SBBO r24, r25, 0, 4 601 : : HALT // Pointers mismatch 602 : : #endif 603 : : 604 : : delta_loop: 605 : 0x010b 0x2e850189 : XIN 10, PRU0_BUF_STATE, 4 606 : 0x010c 0x568889ff : QBEQ delta_loop, PRU0_BUF_OFFSET, PRU1_BUF_OFFSET // Wait for data 607 : : // Get word, stop if zero. Update offset in buffer 608 : 0x010d 0x90883c84 : LBCO r4, CONST_PRUSHAREDRAM, PRU1_BUF_OFFSET, 4 609 : 0x010e 0x5100e422 : QBEQ write_done, r4, 0 610 : 0x010f 0x01048888 : ADD PRU1_BUF_OFFSET, PRU1_BUF_OFFSET, 4 611 : 0x0110 0x117f8888 : AND PRU1_BUF_OFFSET, PRU1_BUF_OFFSET, SHARED_DELTAS_WRITE_MASK 612 : 0x0111 0x2f050188 : XOUT 10, PRU1_BUF_STATE, 4 613 : : // If time is less than bit-period * 1.5 we will call it just a 614 : : // one otherwise some zeros precede the one. 615 : 0x0112 0x6015e407 : QBGT done_zeros, r4, ZERO_THRESHOLD 616 : : // Write a zero bit, decrement time and check if more zero 617 : : wzero: 618 : 0x0113 0x1c55eeee : CLR WORD1, WORD1, BIT_COUNT 619 : 0x0114 0x05015555 : SUB BIT_COUNT, BIT_COUNT, 1 620 : : // If count went negative write the word back to DDR 621 : 0x0115 0xc9075502 : QBBC wnext, BIT_COUNT, BIT_COUNT_MSB 622 : 0x0116 0x23011f93 : CALL write_word 623 : : wnext: 624 : 0x0117 0x0435e4e4 : SUB r4, r4, BIT_PRU_CLOCKS 625 : 0x0118 0x5e15e4fb : QBLE wzero, r4, ZERO_THRESHOLD 626 : : // Write a one 627 : : done_zeros: 628 : 0x0119 0x1c55eeee : CLR WORD1, WORD1, BIT_COUNT 629 : 0x011a 0x1e55efef : SET WORD2, WORD2, BIT_COUNT 630 : 0x011b 0x05015555 : SUB BIT_COUNT, BIT_COUNT, 1 631 : 0x011c 0xcf0755ef : QBBC delta_loop, BIT_COUNT, BIT_COUNT_MSB 632 : 0x011d 0x23011f93 : CALL write_word 633 : 0x011e 0x21010b00 : JMP delta_loop 634 : : 635 : : // Write the word back to DDR. If the mask is all ones we don't 636 : : // need to read the existing word and combine. 637 : : // r0 modified and r26-29 modified from update_dma 638 : : write_word: 639 : 0x011f 0x5100ee04 : QBEQ just_write, WORD1, 0 640 : 0x0120 0x90ed3880 : LBCO r0, CONST_PRURAM, BUF_ADDR, 4 // Get word 641 : 0x0121 0x10eee0e0 : AND r0, r0, WORD1 // Clear bits we wish to change 642 : 0x0122 0x12e0efef : OR WORD2, WORD2, r0 // And put them in 643 : : just_write: 644 : 0x0123 0xe0ea378f : SBBO WORD2, DDR_ADDR, DDR_OFFSET, 4 // Store word 645 : 0x0124 0x0104eaea : ADD DDR_OFFSET, DDR_OFFSET, 4 // Point to next 646 : 0x0125 0x0501ebeb : SUB WORDS_LEFT, WORDS_LEFT, 1 647 : : // Save return address before we do another call 648 : 0x0126 0x109393d3 : MOV RETREG.w2, RETREG.w0 649 : 0x0127 0x2300e593 : CALL update_dma 650 : 0x0128 0x10d3d393 : MOV RETREG.w0, RETREG.w2 651 : 0x0129 0x6900eb03 : QBNE write_ret, WORDS_LEFT, 0 // Branch if more words in track 652 : 0x012a 0x10f6f6ea : MOV DDR_OFFSET, TRACK_OFFSET // Wrap to beginning of track 653 : 0x012b 0x0b02f1eb : LSR WORDS_LEFT, TRACK_BYTES, 2 // divide by 4 to get words 654 : : write_ret: 655 : 0x012c 0x24001f55 : MOV BIT_COUNT, 31 656 : 0x012d 0x2eff018e : FILL &WORD1, 4 657 : 0x012e 0x2eff818f : ZERO &WORD2, 4 658 : 0x012f 0x20930000 : RET 659 : : 660 : : write_done: 661 : : // Write word in progress 662 : 0x0130 0x23011f93 : CALL write_word 663 : : // Let PRU 0 continue. 664 : 0x0131 0x24000868 : MOV PRU1_STATE, STATE_WRITE_DONE 665 : 0x0132 0x2f050188 : XOUT 10, PRU1_BUF_STATE, 4 666 : : write_done_wait: 667 : 0x0133 0x2e850189 : XIN 10, PRU0_BUF_STATE, 4 // Get pru0 status 668 : 0x0134 0x6f0269ff : QBNE write_done_wait, PRU0_STATE, STATE_READ 669 : : //set r0 for proper bit 670 : 0x0135 0xf1002580 : LBBO r0, CYCLE_CNTR, 0, 4 // get track rotation time 671 : 0x0136 0x240244e1 : MOV r1, WRITE_READ_TIME 672 : 0x0137 0x00e1e0e0 : ADD r0, r0, r1 673 : 0x0138 0x2300d293 : CALL convert_track_time // r4 word offset, r27 bit count 674 : 0x0139 0x10e4e4e2 : MOV r2, r4 675 : 0x013a 0x23014393 : CALL find_buf_loc 676 : 0x013b 0x111ffbe6 : AND r6, r27, 0x1f // Get how many bits into first word 677 : 0x013c 0x10fbfbf2 : MOV TRACK_BIT, r27 678 : 0x013d 0x2f050192 : XOUT 10, TRACK_BIT, 4 // And tell PRU 0 start bit of data 679 : 0x013e 0x24000368 : MOV PRU1_STATE, STATE_READ_BIT_SET 680 : 0x013f 0x2f050188 : XOUT 10, PRU1_BUF_STATE, 4 681 : : 682 : : 683 : 0x0140 0xf1002580 : LBBO r0, CYCLE_CNTR, 0, 4 // get time 684 : 0x0141 0x81f03880 : SBCO r0, CONST_PRURAM, 0xf0, 4 685 : : 686 : : 687 : : // Restart read at BUF_LOC at r6 bit. NEXT_DMA_WCOUNT and WORDS_LEFT 688 : : // set by find_buf_loc 689 : 0x0142 0x21009100 : JMP restart_read 690 : : 691 : : // Given bit count find location in buffer for word and count to 692 : : // next DMA 693 : : // in r2 = words into track buffer to convert, modified 694 : : // out BUF_ADDR, NEXT_DMA_WCOUNT modified 695 : : // r0 modified 696 : : find_buf_loc: 697 : 0x0143 0x0b02f1eb : LSR WORDS_LEFT, TRACK_BYTES, 2 // divide by 4 to get words 698 : 0x0144 0x04e2ebeb : SUB WORDS_LEFT, WORDS_LEFT, r2 // Words left 699 : 0x0145 0x0902e2e2 : LSL r2, r2, 2 // Convert to byte 700 : 0x0146 0x00f6e2e2 : ADD r2, r2, TRACK_OFFSET // Convert to DDR address 701 : : // Find number of bytes we need to back up. Handle if DMA address 702 : : // wrapped to beginning of track 703 : 0x0147 0x91743898 : LBCO r24, CONST_PRURAM, PRU1_NEXT_DMA_DDR_OFFSET, 4 704 : 0x0148 0x70f8e202 : QBGE no_wrap2, r2, r24 705 : 0x0149 0x00f1f8f8 : ADD r24, r24, TRACK_BYTES 706 : : no_wrap2: 707 : 0x014a 0x04e2f8f8 : SUB r24, r24, r2 708 : : // At least 3 words from end and no more than full buffer 709 : : // one word to notice we need to start DMA and two more to 710 : : // cover time DMA takes. 711 : 0x014b 0x710cf802 : QBGE err2, r24, 3*4 712 : 0x014c 0x7180f807 : QBGE noerr2, r24, 2*DMA_SIZE 713 : : err2: 714 : 0x014d 0x240001d8 : MOV r24, (1 << GPIO1_TEST) : 0x014e 0x24000098 : 715 : 0x014f 0x244804d9 : MOV r25, GPIO1 | GPIO_SETDATAOUT : 0x0150 0x24c19499 : 716 : 0x0151 0xe1003998 : SBBO r24, r25, 0, 4 717 : 0x0152 0x2a000000 : HALT 718 : : // r24 is now number of words we need to back up from end 719 : : // of last DMA (next DMA addr). We need to do next dma at that 720 : : // many bytes minus half a buffer. 721 : : noerr2: 722 : 0x0153 0x0b02f887 : LSR NEXT_DMA_WCOUNT, r24, 2 // Words to end of buffer 723 : : // We want to DMA half way in 724 : 0x0154 0x05088787 : SUB NEXT_DMA_WCOUNT, NEXT_DMA_WCOUNT, DMA_SIZE/2/4 725 : : // Back up by BUF_ADDR from end of last ram buffer address 726 : : // if we go below first address wrap to end of buffer 727 : 0x0155 0x91703882 : LBCO r2, CONST_PRURAM, PRU1_NEXT_DMA_RAM_OFFSET, 4 728 : 0x0156 0x04f8020d : SUB BUF_ADDR.b0, r2.b0, r24 729 : 0x0157 0x117f0d0d : AND BUF_ADDR.b0, BUF_ADDR.b0, (DMA_SIZE*2-1) 730 : 0x0158 0x20930000 : RET 731 : : 732 : : // Start DMA from DDR to local memory 733 : : // r2 = size in bytes 734 : : // r3 = destination local address 735 : : // r4 = ddr offset 736 : : // r2, r24-r29 modified 737 : : start_dma: 738 : 0x0159 0x91e03898 : LBCO r24, CONST_PRURAM, 0xe0, 4 739 : 0x015a 0x81e43898 : SBCO r24, CONST_PRURAM, 0xe4, 4 740 : 0x015b 0xf1002598 : LBBO r24, CYCLE_CNTR, 0, 4 // get time 741 : 0x015c 0x81e03898 : SBCO r24, CONST_PRURAM, 0xe0, 4 742 : : 743 : 0x015d 0x00e2e3f8 : ADD r24, r3, r2 744 : 0x015e 0x117f1818 : AND r24.b0, r24.b0, (DMA_SIZE*2-1) 745 : 0x015f 0x81703898 : SBCO r24, CONST_PRURAM, PRU1_NEXT_DMA_RAM_OFFSET, 4 746 : 0x0160 0x00e2e4f8 : ADD r24, r4, r2 747 : 0x0161 0x00f6f1f9 : ADD r25, TRACK_BYTES, TRACK_OFFSET 748 : : // If past end of track wrap 749 : 0x0162 0x48f8f903 : QBLT addr_ok, r25, r24 750 : 0x0163 0x04f9f8f8 : SUB r24, r24, r25 751 : 0x0164 0x00f6f8f8 : ADD r24, r24, TRACK_OFFSET 752 : : addr_ok: 753 : 0x0165 0x81743898 : SBCO r24, CONST_PRURAM, PRU1_NEXT_DMA_DDR_OFFSET, 4 754 : : // Load base addresses into registers 755 : 0x0166 0x244900da : MOV EDMA_BASE, EDMA0_CC_BASE : 0x0167 0x2400009a : 756 : 0x0168 0x916c389c : LBCO EDMA_CHANNEL, CONST_PRURAM, PRU1_DMA_CHANNEL, 4 757 : : // Setup and store PaRAM data for transfer 758 : 0x0169 0x0905fcfb : LSL EDMA_PARAM_BASE, EDMA_CHANNEL, 5 // channel*32 759 : 0x016a 0x244000f8 : MOV r24, PARAM_OFFSET 760 : 0x016b 0x00f8fbfb : ADD EDMA_PARAM_BASE, EDMA_PARAM_BASE, r24 761 : 0x016c 0x00fafbfb : ADD EDMA_PARAM_BASE, EDMA_PARAM_BASE, EDMA_BASE 762 : : 763 : 0x016d 0x00f7e4f8 : ADD r24, r4, DDR_ADDR 764 : 0x016e 0xe1043b98 : SBBO r24, EDMA_PARAM_BASE, SRC, 4 765 : 0x016f 0x81d43898 : sbco r24, CONST_PRURAM, 0xd4, 4 766 : 0x0170 0x91083898 : LBCO r24, CONST_PRURAM, PRU_DATARAM_ADDR, 4 767 : 0x0171 0x00e3f8f8 : ADD r24, r24, r3 768 : 0x0172 0xe10c3b98 : SBBO r24, EDMA_PARAM_BASE, DST, 4 769 : : 770 : : // Find bytes left in track 771 : 0x0173 0x00f6f1fd : ADD r29, TRACK_BYTES, TRACK_OFFSET 772 : 0x0174 0x04e4fdfd : SUB r29, r29, r4 773 : : // First entry OPT TCC = channel, enable transfer complete interrupt 774 : : // SRC will be set later 775 : : // ACNT = DMA_SIZE, BCNT = 1, 776 : : // DST = buffer 1 777 : : // SRC, DST BIDX = 0 778 : : // LINK = next PaRAM set, BCNTRLD = 0 779 : : // CCNT = 1 780 : 0x0175 0x090cfcf8 : LSL r24, EDMA_CHANNEL, 12 781 : 0x0176 0x70fde210 : QBGE nowrap, r2, r29 782 : : // We need to wrap, chain to next 783 : 0x0177 0x1340d8d8 : OR r24.w2, r24.w2, 0x40 784 : 0x0178 0xe1003b98 : SBBO r24, EDMA_PARAM_BASE, OPT, 4 785 : 0x0179 0x10fdfdf8 : MOV r24, r29 786 : 0x017a 0x240001d8 : MOV r24.w2, 1 787 : 0x017b 0x81d03898 : sbco r24, CONST_PRURAM, 0xd0, 4 788 : 0x017c 0xe1083b98 : SBBO r24, EDMA_PARAM_BASE, A_B_CNT, 4 789 : : 790 : 0x017d 0x0120fbfb : ADD EDMA_PARAM_BASE, EDMA_PARAM_BASE, 32 // Go to next entry 791 : : 792 : : // Remaining bytes 793 : 0x017e 0x04fde2e2 : SUB r2, r2, r29 794 : : // Start at beginning of track 795 : 0x017f 0x00f7f6f8 : ADD r24, TRACK_OFFSET, DDR_ADDR 796 : 0x0180 0xe1043b98 : SBBO r24, EDMA_PARAM_BASE, SRC, 4 797 : 0x0181 0x91083898 : LBCO r24, CONST_PRURAM, PRU_DATARAM_ADDR, 4 798 : : // And after last data transferd for dest 799 : 0x0182 0x00e3f8f8 : ADD r24, r24, r3 800 : 0x0183 0x00fdf8f8 : ADD r24, r24, r29 801 : 0x0184 0xe10c3b98 : SBBO r24, EDMA_PARAM_BASE, DST, 4 802 : : 803 : : // This will set the required last few entries for the first when jumped 804 : : // here or for the second on fall through 805 : 0x0185 0x090cfcf8 : LSL r24, EDMA_CHANNEL, 12 806 : : nowrap: 807 : 0x0186 0x1310d8d8 : OR r24.w2, r24.w2, 0x10 808 : 0x0187 0xe1003b98 : SBBO r24, EDMA_PARAM_BASE, OPT, 4 809 : : 810 : 0x0188 0x10e2e2f8 : MOV r24, r2 811 : 0x0189 0x240001d8 : MOV r24.w2, 1 812 : 0x018a 0xe1083b98 : SBBO r24, EDMA_PARAM_BASE, A_B_CNT, 4 813 : : 814 : : // Clear flag 815 : 0x018b 0x240000f8 : MOV r24, 0 816 : 0x018c 0x1efcf8f8 : SET r24, EDMA_CHANNEL 817 : 0x018d 0x242270f9 : MOV r25, ICR 818 : 0x018e 0xe0f93a98 : SBBO r24, EDMA_BASE, r25, 4 819 : 0x018f 0x242210f9 : MOV r25, ESR 820 : : // Triggering the transfer 821 : 0x0190 0xe0f93a98 : SBBO r24, EDMA_BASE, r25, 4 822 : 0x0191 0xf1002598 : LBBO r24, CYCLE_CNTR, 0, 4 // get time 823 : 0x0192 0x81e83898 : SBCO r24, CONST_PRURAM, 0xe8, 4 824 : 0x0193 0x20930000 : RET 825 : : 826 : : 827 : : // r24-r26 modified 828 : : wait_dma: 829 : : // Load base addresses into registers 830 : 0x0194 0x244900da : MOV EDMA_BASE, EDMA0_CC_BASE : 0x0195 0x2400009a : 831 : 0x0196 0x242268f9 : MOV r25, IPR 832 : 0x0197 0x916c389c : LBCO EDMA_CHANNEL, CONST_PRURAM, PRU1_DMA_CHANNEL, 4 833 : : wait_dma_loop: 834 : : // TODO: This is slow, should we use interrupt? 835 : 0x0198 0xf0f93a98 : LBBO r24, EDMA_BASE, r25, 4 836 : 0x0199 0xcefcf8ff : QBBC wait_dma_loop, r24, EDMA_CHANNEL 837 : 0x019a 0xf1002598 : LBBO r24, CYCLE_CNTR, 0, 4 // get time 838 : 0x019b 0x81ec3898 : SBCO r24, CONST_PRURAM, 0xec, 4 839 : 0x019c 0x20930000 : RET 840 : : 841 : : // r24-r26 modified 842 : : check_dma: 843 : : // Load base addresses into registers 844 : 0x019d 0x244900da : MOV EDMA_BASE, EDMA0_CC_BASE : 0x019e 0x2400009a : 845 : 0x019f 0x242268f9 : MOV r25, IPR 846 : 0x01a0 0x916c389c : LBCO EDMA_CHANNEL, CONST_PRURAM, PRU1_DMA_CHANNEL, 4 847 : : // TODO: This is slow, should we use interrupt? 848 : 0x01a1 0xf0f93a98 : LBBO r24, EDMA_BASE, r25, 4 849 : 0x01a2 0xc8fcf802 : QBBC wait_dma_halt, r24, EDMA_CHANNEL 850 : 0x01a3 0x20930000 : RET 851 : : wait_dma_halt: 852 : 0x01a4 0x240001d8 : MOV r24, (1 << GPIO1_TEST) : 0x01a5 0x24000098 : 853 : 0x01a6 0x244804d9 : MOV r25, GPIO1 | GPIO_SETDATAOUT : 0x01a7 0x24c19499 : 854 : 0x01a8 0xe1003998 : SBBO r24, r25, 0, 4 855 : 0x01a9 0x2a000000 : HALT 856 : : 857 : : DONE: 858 : : // Send notification to Host for program completion 859 : 0x01aa 0x2400241f : MOV r31.b0, PRU1_ARM_INTERRUPT+16 860 : : 861 : : // Halt the processor 862 : 0x01ab 0x2a000000 : HALT 863 : : 864 : : // Restarted here if the ARM wishes to abort an operation. Any needed 865 : : // cleanup should be here to restore to a good state. Currently none 866 : : .ORIGIN RESTART_ADDR 867 : : // Send notification to Host for program completion 868 : 0x0400 0x2400241f : MOV r31.b0, PRU1_ARM_INTERRUPT+16 869 : : 870 : : // Halt the processor 871 : 0x0401 0x2a000000 : HALT 872 : : 873 : : Source File 2 : 'prucode.hp' (No Output Generated) 1 : : // prucode.hp 2 : : 3 : : #ifndef __PRUCODE_HP__ 4 : : #define __PRUCODE_HP__ 5 : : 6 : : // Definitions 7 : : 8 : : // Refer to this mapping in the file - pruss_intc_mapping.h 9 : : #define PRU0_PRU1_INTERRUPT 17 10 : : #define PRU1_PRU0_INTERRUPT 18 11 : : #define PRU0_ARM_INTERRUPT 19 12 : : #define PRU1_ARM_INTERRUPT 20 13 : : #define ARM_PRU0_INTERRUPT 21 14 : : #define ARM_PRU1_INTERRUPT 22 15 : : 16 : : #define CONST_PRUSSINTC C0 17 : : #define CONST_DMTIMER2 C1 18 : : #define CONST_ECAP C3 19 : : #define CONST_PRUCFG C4 20 : : #define CONST_PRURAM C24 21 : : #define CONST_PRURAM_OTHER C25 22 : : #define CONST_IEP C26 23 : : #define CONST_PRUSHAREDRAM C28 24 : : #define CONST_DDR C31 25 : : 26 : : // Base addresses for the following control registers 27 : : #define PRU0_CONTROL 0x00022000 28 : : #define PRU1_CONTROL 0x00024000 29 : : // Address for the control register (CONTROL) 30 : : #define CONTROL 0x0 31 : : // Address for the cycle counter register (CYCLE) 32 : : #define CYCLE 0x0c 33 : : // Address for the Constant table Block Index Register (CTBIR) 34 : : #define CTBIR 0x20 35 : : // Address for the Constant table Block Index Register (CTBIR1) 36 : : #define CTBIR1 0x24 37 : : // Address for the Constant table Programmable Pointer Register 0(CTPPR_0) 38 : : #define CTPPR_0 0x28 39 : : // Address for the Constant table Programmable Pointer Register 1(CTPPR_1) 40 : : #define CTPPR_1 0x2C 41 : : 42 : : 43 : : // Interrupt controller registers 44 : : #define GER_OFFSET 0x10 45 : : #define HIESR_OFFSET 0x34 46 : : #define SICR_OFFSET 0x24 47 : : #define SISR_OFFSET 0x20 48 : : #define EISR_OFFSET 0x28 49 : : #define GPIR_OFFSET 0x80 50 : : #define HOST_NUM 0 51 : : #define CHN_NUM 0 52 : : 53 : : #define ECAP0_EVT 31 54 : : #define GPIO0_EVT 57 55 : : // Enhanced capture registers 56 : : #define TSCTR 0x00 57 : : #define CAP1 0x08 58 : : #define CAP2 0x0c 59 : : #define CAP3 0x10 60 : : #define CAP4 0x14 61 : : #define ECCTL1 0x28 62 : : #define ECCTL2 0x2a 63 : : #define ECFLG 0x2e 64 : : #define ECCLR 0x30 65 : : 66 : : // IEP 67 : : #define IEP_COUNT 0x0c 68 : : #define INTC_REGS_BASE 0x00004000 69 : : #define INTC_CHNMAP_REGS_OFFSET 0x0400 70 : : #define INTC_HOSTMAP_REGS_OFFSET 0x0800 71 : : #define INTC_HOSTINTPRIO_REGS_OFFSET 0x0900 72 : : #define INTC_SYS_INT_REGS_OFFSET 0x0D00 73 : : #define INTC_HOSTNEST_REGS_OFFSET 0x1100 74 : : 75 : : #define GPIO0 0x44e07000 76 : : #define GPIO1 0x4804c000 77 : : #define GPIO2 0x481Ac000 78 : : #define GPIO_IRQSTATUS_0 0x02c 79 : : #define GPIO_IRQSTATUS_1 0x030 80 : : #define GPIO_IRQSTATUS_RAW_0 0x024 81 : : #define GPIO_IRQSTATUS_RAW_1 0x028 82 : : #define GPIO_IRQSTATUS_SET_0 0x034 83 : : #define GPIO_IRQSTATUS_SET_1 0x038 84 : : #define GPIO_DATIN 0x138 85 : : #define GPIO_LEVELDECTECT0 0x140 86 : : #define GPIO_LEVELDECTECT1 0x144 87 : : #define GPIO_RISINGDETECT 0x148 88 : : #define GPIO_FALLINGDETECT 0x14c 89 : : #define GPIO_CLEARDATAOUT 0x190 90 : : #define GPIO_SETDATAOUT 0x194 91 : : 92 : : 93 : : //EDMA registers 94 : : #define EDMA0_CC_BASE 0x49000000 95 : : #define DMAQNUM0 0x0240 96 : : #define QUEPRI 0x0284 97 : : #define EMR 0x0300 98 : : #define EMCR 0x0308 99 : : #define EMCRH 0x030C 100 : : #define QEMCR 0x0314 101 : : #define CCERRCLR 0x031C 102 : : #define DRAE0 0x0340 103 : : #define DRAE1 0x0348 104 : : #define DRAE2 0x0350 105 : : #define DRAE3 0x0358 106 : : #define QWMTHRA 0x0620 107 : : #define GLOBAL_ESR 0x1010 108 : : #define GLOBAL_CER 0x1018 109 : : #define GLOBAL_EECR 0x1028 110 : : #define GLOBAL_SECR 0x1040 111 : : #define GLOBAL_IER 0x1050 112 : : #define GLOBAL_IECR 0x1058 113 : : #define GLOBAL_IESR 0x1060 114 : : #define GLOBAL_ICR 0x1070 115 : : // 0x1000 + 0x200 * region, we use region 1 116 : : #define DRAE_OFFSET 0x1200 117 : : //#define DRAE_OFFSET 0x0000 118 : : #define ESR (0x1010+DRAE_OFFSET) 119 : : #define EECR (0x1028+DRAE_OFFSET) 120 : : #define SECR (0x1040+DRAE_OFFSET) 121 : : #define IER (0x1050+DRAE_OFFSET) 122 : : #define IPR (0x1068+DRAE_OFFSET) 123 : : #define ICR (0x1070+DRAE_OFFSET) 124 : : #define IESRL (0x1060+DRAE_OFFSET) 125 : : #define IEVAL (0x1078+DRAE_OFFSET) 126 : : #define IECR (0x1058+DRAE_OFFSET) 127 : : 128 : : 129 : : //EDMA PARAM registers 130 : : #define PARAM_OFFSET 0x4000 131 : : #define OPT 0x00 132 : : #define SRC 0x04 133 : : #define A_B_CNT 0x08 134 : : #define DST 0x0C 135 : : #define SRC_DST_BIDX 0x10 136 : : #define LINK_BCNTRLD 0x14 137 : : #define SRC_DST_CIDX 0x18 138 : : #define CCNT 0x1C 139 : : 140 : : #endif // __PRUCODE_HP__ 141 : : Source File 3 : 'cmd.h' (No Output Generated) 1 : : // These defines are used in both the PRU assembly language and in the C 2 : : // code so they can only be simple defines. 3 : : 4 : : // The commands to the PRU 5 : : #define CMD_NONE 0 6 : : #define CMD_START 1 7 : : 8 : : // The command status. All commands other than CMD_READ_TRACK 9 : : // return their status when done. CMD_READ_TRACK returns 10 : : // CMD_STATUS_READ_STARTED when the read has started and CMD_STATUS_OK 11 : : // or an error status when the read is finished. 12 : : #define CMD_STATUS_OK 0x0ff 13 : : #define CMD_STATUS_READ_STARTED 0x100 14 : : 15 : : 16 : : // Registers used locally and XFER bank 10 to communicate with PRU0 17 : : #define PRU1_BUF_OFFSET r8.w0 18 : : #define PRU1_STATE r8.b3 19 : : #define PRU1_BUF_STATE r8 20 : : #define PRU0_BUF_OFFSET r9.w0 21 : : #define PRU0_STATE r9.b3 22 : : #define PRU0_BUF_STATE r9 23 : : #define TRACK_BIT r18 24 : : // 0 for first drive, 4 for second to access variables that depend on selected drive 25 : : #define DRIVE_DATA r20 26 : : 27 : : #define STATE_IDLE 1 28 : : #define STATE_READ 2 29 : : #define STATE_READ_BIT_SET 3 30 : : #define STATE_READ_FILLED 4 31 : : #define STATE_READ_DONE 5 32 : : #define STATE_WRITE_WAIT 6 33 : : #define STATE_WRITE 7 34 : : #define STATE_WRITE_DONE 8 35 : : #define STATE_RESTART_READ 9 36 : : #define STATE_EXIT 10 37 : : 38 : : // All these are the memory address to communicate with the PRU code 39 : : 40 : : // These are on both PRUs. 41 : : // Physical address and size of shared DDR memory 42 : : #define PRU_DDR_ADDR 0x00 43 : : #define PRU_DDR_SIZE 0x04 44 : : // Physical address of PRU dataram 45 : : #define PRU_DATARAM_ADDR 0x08 46 : : 47 : : #define PRU_TEST0 0x0c 48 : : #define PRU_TEST1 0x10 49 : : #define PRU_TEST2 0x14 50 : : #define PRU_TEST3 0x18 51 : : #define PRU_TEST4 0x1c 52 : : 53 : : // Command location, command data, and status 54 : : #define PRU0_CMD 0x30 55 : : #define PRU0_CMD_DATA 0x34 56 : : #define PRU0_STATUS 0x38 57 : : // Count and register value if we got a GPIO interrupt without data changing 58 : : #define PRU0_HEAD_SELECT_GLITCH_VALUE 0x3c 59 : : #define PRU0_HEAD_SELECT_GLITCH_COUNT 0x40 60 : : // Decoded head and raw bits from GPIO register. See PRU0_DRIVE#_CUR_CYL 61 : : // for current cylinder 62 : : #define PRU0_CUR_HEAD 0x48 63 : : #define PRU0_CUR_SELECT_HEAD 0x4c 64 : : // Time in 200 MHz clocks from ARM interrupt to data returned 65 : : #define PRU0_SEEK_TIME 0x50 66 : : // Number of bytes in each drive# value. 67 : : #define DRIVE_DATA_BYTES 4 68 : : // Parameters of simulated disk 69 : : #define PRU0_DRIVE0_NUM_CYL 0x54 70 : : #define PRU0_DRIVE1_NUM_CYL 0x58 71 : : #define PRU0_DRIVE0_NUM_HEAD 0x5c 72 : : #define PRU0_DRIVE1_NUM_HEAD 0x60 73 : : // Internal variable 74 : : #define PRU0_WAITING_CMD 0x64 75 : : // Overrun on ECAP if non zero 76 : : #define PRU0_ECAP_OVERRUN 0x68 77 : : // PRU 0-1 queue underrun count 78 : : #define PRU0_RQUEUE_UNDERRUN 0x6c 79 : : #define PRU0_WQUEUE_OVERRUN 0x70 80 : : // Drive select numbers we should respond to. 0 or bit number in GPIO 81 : : // register that is our drive select. Keep adjacent. 82 : : #define PRU0_DRIVE0_SELECT 0x74 83 : : #define PRU0_DRIVE1_SELECT 0x78 84 : : // The select and head lines we are looking at. If < 8 cyl then only low 3 85 : : #define PRU0_HEAD_MASK 0x7c 86 : : 87 : : // Current cylinder 88 : : #define PRU0_DRIVE0_CUR_CYL 0x80 89 : : #define PRU0_DRIVE1_CUR_CYL 0x84 90 : : 91 : : // 0 normal, 1 to command PRU to exit 92 : : #define PRU0_EXIT 0x88 93 : : 94 : : // Used to convert bit-count to cycles at current rate (4 bytes) 95 : : #define PRU0_BIT_PRU_CLOCKS 0x8c 96 : : 97 : : // Cycle count for PWM logic 1 at current data rate (4 bytes) 98 : : #define PRU0_DEFAULT_PULSE_WIDTH 0x90 99 : : 100 : : // Start and end time for generating index pulse in PRU clocks 101 : : #define PRU0_START_INDEX_TIME 0x94 102 : : #define PRU0_END_INDEX_TIME 0x98 103 : : 104 : : // Time for a disk rotation in PRU clocks 105 : : #define PRU0_ROTATION_TIME 0x9c 106 : : 107 : : // 0xa0 unused 108 : : 109 : : // Last cylinder requested from ARM 110 : : #define PRU0_DRIVE0_LAST_ARM_CYL 0xa4 111 : : #define PRU0_DRIVE1_LAST_ARM_CYL 0xa8 112 : : #define PRU0_LAST_SELECT_HEAD 0xac 113 : : 114 : : // Bits 0-n indicate track 0-n been modified in cylinder data 115 : : #define PRU1_DRIVE0_TRK_DIRTY 0x30 116 : : // Bits 0-n indicate track 0-n been modified in cylinder data 117 : : #define PRU1_DRIVE1_TRK_DIRTY 0x34 118 : : // Non zero indicates error in converting bits to PWM words 119 : : #define PRU1_BAD_PATTERN_COUNT 0x38 120 : : #define PRU1_DRIVE0_TRACK_HEADER_BYTES 0x50 121 : : #define PRU1_DRIVE1_TRACK_HEADER_BYTES 0x54 122 : : #define PRU1_DRIVE0_TRACK_DATA_BYTES 0x58 123 : : #define PRU1_DRIVE1_TRACK_DATA_BYTES 0x5c 124 : : 125 : : // inverse bit period scaled 2^32, 2^32/bit_period 126 : : #define PRU1_INV_BIT_PERIOD_S32 0x60 127 : : 128 : : // If we don't see a transition by this number of cycles, 129 : : // assume zero. 130 : : #define PRU1_ZERO_BIT_THRESHOLD 0x64 131 : : // Nominal bit cell cycles 132 : : #define PRU1_BIT_PRU_CLOCKS 0x68 133 : : // DMA channel to use 134 : : #define PRU1_DMA_CHANNEL 0x6c 135 : : // Last DMA RAM and DDR offset, internal PRU use 136 : : #define PRU1_NEXT_DMA_RAM_OFFSET 0x70 137 : : #define PRU1_NEXT_DMA_DDR_OFFSET 0x74 138 : : 139 : : #define PRU_WORD_SIZE_BYTES 4 140 : : 141 : : // Location bit lookup table stored 142 : : #define PRU1_BIT_TABLE 0x80 143 : : 144 : : // Maximum size of cylinder buffer. 145 : : #define DDR_DRIVE_BUFFER_MAX_SIZE (16*32768) 146 : : // PRU queues are in shared memory locations 0 to mask 147 : : #define SHARED_PWM_READ_MASK 0x1f 148 : : #define SHARED_DELTAS_WRITE_MASK 0x7f 149 : : 150 : : // Bits in registers for the control lines 151 : : #define R30_DRIVE0_SEL 1 152 : : #define R30_SEEK_COMPLETE_BIT 2 153 : : // Rev A,B 154 : : #define R30_WRITE_FAULT_BIT 3 155 : : // Rev C 156 : : #define GPIO1_WRITE_FAULT_BIT 19 157 : : #define R30_READY_BIT 4 158 : : #define R30_INDEX_BIT 5 159 : : #define R30_MFM0_IN_ENABLE 15 160 : : #define R30_MFM1_IN_ENABLE 14 161 : : 162 : : #define R31_WRITE_GATE 0 163 : : #define R31_SEEK_DIR_BIT 6 164 : : #define R31_STEP_BIT 7 165 : : // Rev C 166 : : #define R31_SEL1_BIT 14 167 : : #define R31_SEL2_BIT 16 168 : : 169 : : #define REVB_DETECT_PIN 46 // GPIO 1_14 170 : : #define REVC_DETECT_PIN 61 // GPIO 1_29 171 : : 172 : : // Rev A,B 173 : : #define GPIO0_TRACK_0 30 174 : : // Rev C 175 : : #define R30_TRACK_0_BIT 3 176 : : #define GPIO0_DRIVE0_LED 14 177 : : // Rev A,B 178 : : #ifndef REVC 179 : : #define GPIO0_DRIVE1_LED 15 180 : : #else 181 : : // Rev C 182 : : #define GPIO0_DRIVE1_LED 30 183 : : #endif 184 : : #define GPIO0_DRIVE1_SEL_RECOVERY 31 185 : : 186 : : #define GPIO1_TEST 16 187 : : 188 : : #define GPIO_SELECT1 22 189 : : #define GPIO_SELECT2 23 190 : : #ifdef REVC 191 : : #define GPIO_HEAD0 8 192 : : #define GPIO_HEAD1 9 193 : : #define GPIO_HEAD2 10 194 : : #define GPIO_HEAD3 11 195 : : #define GPIO_DRIVE_SELECT_LINES 196 : : #else 197 : : #ifdef REVB 198 : : #define GPIO_HEAD0 8 199 : : #define GPIO_HEAD1 9 200 : : #define GPIO_HEAD2 10 201 : : #define GPIO_HEAD3 11 202 : : #define GPIO_DRIVE_SELECT_LINES (1 << GPIO_SELECT1) | (1 << GPIO_SELECT2) 203 : : #else 204 : : #define GPIO_HEAD0 2 205 : : #define GPIO_HEAD1 3 206 : : #define GPIO_HEAD2 4 207 : : #define GPIO_HEAD3 5 208 : : #define GPIO_SELECT3 26 209 : : #define GPIO_SELECT4 27 210 : : #define GPIO_DRIVE_SELECT_LINES (1 << GPIO_SELECT1) | (1 << GPIO_SELECT2) | (1 << GPIO_SELECT3) | (1 << GPIO_SELECT4) 211 : : #endif 212 : : #endif 213 : : #define CUR_SELECT_HEAD_WRITE_ERR 31 214 : : 215 : : #define GPIO_DRIVE_HEAD_LINES (1 << GPIO_HEAD0) | (1 << GPIO_HEAD1) | (1 << GPIO_HEAD2) | (1 << GPIO_HEAD3) 216 : : #define GPIO_DRIVE_SELECT_HEAD_LINES (GPIO_DRIVE_HEAD_LINES | GPIO_DRIVE_SELECT_LINES) 217 : : 218 : : // Address in PRU code for stopping current operation 219 : : #define RESTART_ADDR 0x400 220 : : // Offset from start of PRU0_DATARAM to the PRU control register 221 : : #define PRU_CONTROL_REG 0x22000 222 : : #define PRU_STATUS_REG 0x22004 223 : : #define PRU_DEBUG 0x22400 224 : : 225 : : // TODO, these should be common 226 : : #define CLOCK_BASE 0x44e00000 227 : : #define CM_AUTOIDEL_DPLL_DISP 0x448 228 : : #define CM_IDLEST_DPLL_DISP 0x448 229 : : #define CM_SSC_DELTAMSTEP_DPLL_DISP 0x44c 230 : : #define CM_SSC_MODFREQDIV_DPLL_DISP 0x450 231 : : #define CM_CLKSEL_DPLL_DISP 0x454 232 : : #define CM_CLKMODE_DPLL_DISP 0x498 233 : : #define CM_DIV_M2_DPLL_DISP 0x4a4 234 : : #define CLKSEL_PRU_ICSS_OCP_CLK 0x530 235 : :