1 /**************************************************************************************\
2 * *
3 * The Lisa Emulator Project V1.2.6 DEV 2007.12.04 *
4 * http://lisaem.sunder.net *
5 * *
6 * Copyright (C) 1998, 2007 Ray A. Arachelian *
7 * All Rights Reserved *
8 * *
9 * This program is free software; you can redistribute it and/or *
10 * modify it under the terms of the GNU General Public License *
11 * as published by the Free Software Foundation; either version 2 *
12 * of the License, or (at your option) any later version. *
13 * *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License *
20 * along with this program; if not, write to the Free Software *
21 * Foundation, Inc., 59 Temple Place #330, Boston, MA 02111-1307, USA. *
22 * *
23 * or visit: http://www.gnu.org/licenses/gpl.html *
24 * *
25 * *
26 * Profile Hard Disk Routines *
27 * *
28 \**************************************************************************************/
29
30
31 #define IN_PROFILE_C
32 #include "vars.h"
33
34
35
36 // what's the size of a Profile image file header (so we can skip the start when doing data...)
37 #define PROFILE_IMG_HEADER_SIZE 2048
38
39 #define PROFILE_WAIT_EXEC_CYCLE 3 // #of ProFile Loops to wait after got 55 before we return results to Lisa
40
41 #define PRO_STATUS_CLEAR {P->DataBlock[0]=0;P->DataBlock[1]=0;P->DataBlock[2]=0;P->DataBlock[3]=0;}
42 #define PRO_STATUS_GOT55 {P->DataBlock[0]|=128;} // signal that I got 0x55 response
43 #define PRO_STATUS_NO55 {P->DataBlock[0]&=127;} // signal that I didn't
44 #define PRO_STATUS_BUFFER_OVERFLOW {P->DataBlock[0]|=64; } // Lisa sent too much data
45 #define PRO_STATUS_FAILED {P->DataBlock[0]|=1; } // operation failed
46 #define PRO_STATUS_WAS_RESET {P->DataBlock[3]|=128; P->last_reset_cpuclk=cpu68k_clocks;} // profile was reset
47 #define PRO_INVALID_BLOCK_NO {P->DataBlock[3]|=64; } // asked to access invalid block #
48
49
50 char ProFile_Spare_table[536]=
51 {
52
53 /*
54
55 * The first 13 bytes show the device name, e.g. "PROFILE ". Other drives are called "PROFILE 10M " or "Widget-10 ".
56 * The next three bytes hold the device number, which is $000000 for a 5MB ProFile, $000010 for a 10MB ProFile, and $001000 for a Widget 10 drive.
57 * The next two bytes indicate the firmware revision, e.g. $0398 for 3.98.
58 * The next three bytes hold the total number of blocks available on the device. This is $002600 for 5MB and $004C00 for 10MB. You see, up to 8GB are possible. IDE reached its first limit at 520MB!
59 * The next two bytes indicate the number of bytes per block: $0214 means 532. 532 means 512 byted user data and 20 bytes tag. This is the same format Macintosh MFS volumes and 400k/800k disks use. Send a MFS HD20SC with ST225N mechanism a read capacity command - the response will be 532 bytes per sector!
60 * The next byte contains the total number of spare blocks available on the device, which is $20.
61 * This is followed by the number of spare blocks currently allocated. A good drive uses less than three spares. When all these 32 blocks are allocated, the host will ask the user to call a qualified Apple Service technician for reformatting.
62 * The next byte contains the number of bad blocks currently allocated. A bad block turns into a spared block during the next power-on self test.
63
64
65 */
66
67
68
69
70
71 // 0 1 2 3 4 5 6 7 8 9 a b c <- 13 bytes
72 'P','R','O','F','I','L','E',' ',' ',' ',' ',' ',0 , // device name
73 // d e f
74 0, 0, 0, // 0,0,0x10-10MB ProFile // device #
75 // 0x10,0x11
76 0x03, 0x98, // ProFile firmware revsion
77 // 0x12, 0x13, 0x14
78 0x00, 0x26, 0x00, // # of available blocks to user *play with this*
79 /*20, 21 */
80 0x02, 0x14, // bytes/sector =532
81 32, // number of spares (blocks) byte 22
82 0, // byte 23
83 0, // byte 24
84 0xFF,0xFF,0xFF, // byte 25,26,27
85 0,0,0,0, // byte 28,29,30,31 (now we need 500 more bytes full of zeros)
86
87 // 50 0 bytes * 10 lines = 500 bytes... for both spare and error tables. (virtual profiles are perfect!)
88 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, // 1
89 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, // 2
90 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, // 3
91 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, // 4
92 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, // 5
93 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, // 6
94 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, // 7
95 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, // 8
96 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, // 9
97 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0 // 10
98 };
99
100
101 /*
102 * do the actual reading and writing of the blocks off the profile hard drive image file
103 *
104 */
105
106 void ProfileReset(ProFileType *P);
107 void ProfileResetOff(ProFileType *P);
108
109
110 #ifdef DEBUG
111
112 // This is an appender log, flush+close so that incase there's a crash, no pending data gets lost.
113
dump_profile_block(FILE * f,uint8 * RAM,long sectornumber,char * text)114 void dump_profile_block(FILE *f, uint8 *RAM, long sectornumber, char *text)
115 {
116 int i,j;
117 char c;
118
119 if (!debug_log_enabled) return;
120
121 fprintf(f ,"%s %ld tags::",text,sectornumber);
122
123 for (i=0; i<20; i++) fprintf(f ,"%02x ",RAM[i]);
124
125 for (i=0; i<512; i+=16)
126 {
127 fprintf(f ,"\n%s %ld %04x:: ",text,sectornumber,i);
128
129 for (j=0; j<16; j++) fprintf( f,"%02x ",RAM[20+i+j]);
130
131 fputc('|',f);
132
133 for (j=0; j<16; j++)
134 { c=RAM[20+i+j];
135 c &=0x7f;
136 if (c< 32) c|=32;
137 if (c>125) c='.';
138 fputc(c,f);
139 }
140 }
141 fputc('\n',f);
142 }
143
dump_profile_block_to_log(uint8 * RAM,long sectornumber,char * text)144 void dump_profile_block_to_log(uint8 *RAM, long sectornumber, char *text)
145 {
146 FILE *f;
147 int i,j;
148 char c;
149
150 return;
151
152 f=fopen("./lisaem-output.profile","a");
153 if (!f) return;
154
155 fprintf(f ,"%s %ld tags::",text,sectornumber);
156
157 for (i=0; i<20; i++) fprintf(f ,"%02x ",RAM[i]);
158
159 for (i=0; i<512; i+=16)
160 {
161 fprintf(f ,"\n%s %ld %04x:: ",text,sectornumber,i);
162
163 for (j=0; j<16; j++) fprintf( f,"%02x ",RAM[20+i+j]);
164
165 fputc('|',f);
166
167 for (j=0; j<16; j++)
168 { c=RAM[20+i+j];
169 c &=0x7f;
170 if (c< 32) c|=32;
171 if (c>125) c='.';
172 fputc(c,f);
173 }
174 }
175 fputc('\n',f);
176 fclose(f);
177
178
179 }
180
append_profile_log(int level,char * s,...)181 void append_profile_log(int level, char *s,...)
182 {
183 FILE *f;
184 //fprintf(buglog,s);
185
186
187
188 if (level>DEBUGLEVEL) return;
189
190 return;
191
192 f=fopen("./lisaem-output.profile","a");
193
194 if (f) {va_list params;
195
196 printlisatime(f);
197 fprintf(f,"pc24:%08x ",pc24);
198
199 va_start(params, s);
200 vfprintf(f,s, params);
201 va_end(params);
202
203 if (debug_log_enabled)
204 {
205 printlisatime(buglog);
206 fprintf(buglog,"pc24:%08x ",pc24);
207 va_start(params, s);
208 vfprintf(buglog,s, params);
209 va_end(params);
210 fprintf(buglog,"\n");
211 }
212 fprintf(f,"\n");
213 fflush(f);
214 fclose(f);
215
216 }
217 }
218
219 #else
220
221 #define dump_profile_block(s...) {;}
222 #define dump_profile_block_to_log(s...) {;}
223 #define append_profile_log(s...) {;}
224
225 #endif
226
interleave5(long sector)227 long interleave5(long sector)
228 {
229 static const int offset[]={0,5,10,15,4,9,14,3,8,13,2,7,12,1,6,11,16,21,26,31,20,25,30,19,24,29,18,23,28,17,22,27};
230 return offset[sector&31] + sector-(sector&31);
231 }
232
deinterleave5(long sector)233 long deinterleave5(long sector)
234 {
235 static const int offset[]={0,13,10,7,4,1,14,11,8,5,2,15,12,9,6,3,16,29,26,23,20,17,30,27,24,21,18,31,28,25,22,19};
236 return offset[sector&31] + sector-(sector&31);
237 }
238
239
get_profile_spare_table(ProFileType * P)240 void get_profile_spare_table(ProFileType *P)
241 {
242 // copy spare table template
243 DEBUG_LOG(0,"Profile spare table");
244 memset(&P->DataBlock[4],0,536);
245 memcpy(&P->DataBlock[4],ProFile_Spare_table,512);
246
247
248 P->DataBlock[0]=0;
249 P->DataBlock[1]=0;
250 P->DataBlock[2]=0;
251 P->DataBlock[3]=0;
252
253
254 // fill in profile size of this profile
255
256 // 0x12, 0x13, 0x14
257 if (P->DC42.numblocks==0) P->DC42.numblocks= (P->DC42.datasizetotal/P->DC42.sectorsize);
258
259 char a,b,c;
260 switch (P->DC42.numblocks)
261 {
262 case 19456: a='1'; b='0'; c='M'; break;//10M
263 case 32768: a='1'; b='6'; c='M'; break;//16M
264 case 40960: a='2'; b='0'; c='M'; break;//20M
265 case 65536: a='3'; b='2'; c='M'; break;//32M
266 case 81920: a='4'; b='0'; c='M'; break;//40M
267 case 131072: a='6'; b='4'; c='M'; break;//64M
268 //case 9728:
269 default: a=' '; b=' '; c=' '; // 5M
270 }
271
272
273 P->DataBlock[4+0x08]=a;
274 P->DataBlock[4+0x09]=b;
275 P->DataBlock[4+0x0a]=c;
276 P->DataBlock[4+0x0b]=' ';
277
278 if (P->DC42.numblocks>9728) P->DataBlock[4+0x0f]=0x10;
279
280 // PROFILE 10M " $000010 or "Widget-10 " $001000
281
282 P->DataBlock[4+18]=(( (P->DC42.numblocks ) >> 16) & 0x0000ff); // msb
283 P->DataBlock[4+19]=(( (P->DC42.numblocks ) >> 8) & 0x0000ff); // middle
284 P->DataBlock[4+20]=(( (P->DC42.numblocks ) ) & 0x0000ff); // lsb
285
286 P->indexread=0; // reset index pointers to status
287 P->indexwrite=4;
288
289 return;
290 }
291
292
do_profile_read(ProFileType * P,uint32 block)293 void do_profile_read(ProFileType *P, uint32 block)
294 {
295 //uint16 i,j;
296 uint8 *blk;
297 //#ifdef DEBUG
298 uint32 oblock=block;
299 //#endif
300
301 if (!P ) {ALERT_LOG(0,"ProfileType P is null!"); return;} // no image is opened!
302 if (!P->DC42.sectorsize) {ALERT_LOG(0,"Profile sector size is 0!"); return;}
303
304
305 // if (block==0x00ffffff || block<30)
306 // ALERT_LOG(0,"Slot 1 ID:%04x, Slot 2 ID:%04x, Slot 3 ID:%04x, via:%d blk:%d",
307 // lisa_ram_safe_getword(1,0x298), lisa_ram_safe_getword(1,0x29a), lisa_ram_safe_getword(1,0x29c),P->vianum,block )
308
309
310 // convert unbootable fake dual parallel card to have the proper ID.
311 if (block==0x00ffffff && (pc24 & 0x00ff0000)==0x00fe0000 && !romless && dualparallelrom[0x30]==0xff && dualparallelrom[0x31]==0xff)
312 {
313 if (lisa_ram_safe_getbyte(1,0x299)==0x02) lisa_ram_safe_setbyte(1,0x298,0xe0);
314 if (lisa_ram_safe_getbyte(1,0x29b)==0x02) lisa_ram_safe_setbyte(1,0x29a,0xe0);
315 if (lisa_ram_safe_getbyte(1,0x29d)==0x02) lisa_ram_safe_setbyte(1,0x29c,0xe0);
316 }
317
318 if (block<0x00f00000) block=deinterleave5(block);
319
320 if ( block==0x00fffffe) // return ProfileRAM buffer contents
321 {
322 P->indexread=0; // reset index pointers to status
323 P->indexwrite=4;
324
325 dump_profile_block(buglog, &(P->DataBlock[4]), block, "read");
326 dump_profile_block_to_log( &(P->DataBlock[4]), block, "read");
327 return;
328 }
329
330
331 if ( block==0x00ffffff) {get_profile_spare_table(P); return;} // return Profile spare table
332
333
334 if (P->DC42.numblocks==0 && P->DC42.sectorsize) P->DC42.numblocks= (P->DC42.datasizetotal/P->DC42.sectorsize);
335 if ( block>=P->DC42.numblocks) // wrong block #
336 {
337 P->DataBlock[3] |=64; // set status byte to block number is invalid
338 P->indexread=0; // reset index pointers to status
339 P->indexwrite=4;
340 return;
341 }
342
343
344
345 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
346
347 blk=dc42_read_sector_data(&(P->DC42),block);
348
349 if (P->DC42.retval || blk==NULL)
350 {ALERT_LOG(0,"Read sector from blk#%d failed with error:%d %s",block,P->DC42.retval,P->DC42.errormsg);}
351
352 if (blk!=NULL) memcpy( &(P->DataBlock[4+P->DC42.tagsize]), blk, P->DC42.datasize); //4
353
354
355 blk=dc42_read_sector_tags(&(P->DC42),block);
356 if (P->DC42.retval || blk==NULL)
357 {ALERT_LOG(0,"Read tags from blk#%d failed with error:%d %s",block,P->DC42.retval,P->DC42.errormsg);}
358
359 if (blk!=NULL) memcpy( &(P->DataBlock[4 ]), blk, P->DC42.tagsize); //4+512
360
361
362 #ifdef DEBUG
363 dump_profile_block(buglog, &(P->DataBlock[4]), block, "read");
364 #endif
365
366 if ( errno )
367 {
368 DEBUG_LOG(0,"Error reading ProFile Image! errno: %d, State:%d,IndexWrite:%d,ProfileCommand:%d,BSY:%d,Data:%d,CMDL:%d,buffer:%2x:%2x:%2x:%2x:%2x:%2x\n",
369 errno,
370 P->indexwrite,
371 P->StateMachineStep,P->Command,P->BSYLine,P->VIA_PA,P->CMDLine,
372 P->DataBlock[4],P->DataBlock[5],P->DataBlock[6],P->DataBlock[7],
373 P->DataBlock[8],P->DataBlock[9]);
374
375 }
376
377
378 P->indexread=0; // reset index pointers to status
379 P->indexwrite=4;
380 }
381
382
do_profile_write(ProFileType * P,uint32 block)383 void do_profile_write(ProFileType *P,uint32 block)
384 {
385 uint16 i;
386 #ifdef DEBUG
387 uint8 *blk;
388 uint32 oblock=block;
389 #endif
390
391 if (!P ) {ALERT_LOG(0,"Request for null profile blk=%d!",block); return;} // no image is opened!
392 if (!P->DC42.sectorsize) {ALERT_LOG(0,"Profile sector size is 0!"); return;}
393
394 if (block<0x00f00000) block=deinterleave5(block);
395
396 DEBUG_LOG(0,"ProFile write request block #%ld 0x%08x deinterleaved:%ld 0x%08x\n",block,block,oblock,oblock);
397
398 if ( block==0x00fffffe) // write ProfileRAM buffer contents
399 {
400 P->indexread=0; // reset index pointers to status
401 P->indexwrite=4;
402 return;
403 }
404
405 if ( block==0x00ffffff) // pretend to write ProfileRAM buffer contents
406 {
407 // copy spare table template
408
409 for ( i=0; i<532; i++) {P->DataBlock[4+i]=ProFile_Spare_table[i];}
410
411 // fill in profile size of this profile
412
413 P->DataBlock[18]=((P->DC42.numblocks >> 16) & 0x0000ff); // msb
414 P->DataBlock[19]=((P->DC42.numblocks >> 8) & 0x0000ff); // middle
415 P->DataBlock[20]=((P->DC42.numblocks ) & 0x0000ff); // lsb
416 P->Command=-2; // is now idle
417 P->indexread=0; // reset index pointers to status
418 P->indexwrite=4;
419
420 return;
421 }
422
423 if ( P->DC42.fd<2 && !P->DC42.fh) { P->Command=-1; return; } // if the handle isn't open, disable profile.
424
425
426
427 if (P->DC42.numblocks==0) P->DC42.numblocks= (P->DC42.datasizetotal/P->DC42.sectorsize);
428 if ( block>=P->DC42.numblocks) // wrong block #
429 {
430 P->DataBlock[3] |=64; // set status byte to block number is invalid
431 P->indexread=0; // reset index pointers to status
432 P->indexwrite=4;
433 return;
434 }
435
436
437 //2007.01.25
438 //P->DC42.synconwrite=1; // Ensure data is immediately written to the disk.
439
440 errno=0;
441
442 //fprintf(stderr,"ProFile write to %ld %d bytes\n",block,P->DC42.datasize);
443 dc42_write_sector_data(&P->DC42,block,&(P->DataBlock[4+6+P->DC42.tagsize]));
444 if (P->DC42.retval) {DEBUG_LOG(0,"Write sector from blk#%d failed with error:%d %s",block,P->DC42.retval,P->DC42.errormsg);}
445
446 dc42_write_sector_tags(&P->DC42,block,&(P->DataBlock[4+6]));
447 if (P->DC42.retval) {DEBUG_LOG(0,"Write tags from blk#%d failed with error:%d %s",block,P->DC42.retval,P->DC42.errormsg);}
448
449
450 // 20061223 - gprof catches the calculate checksums call that this calls to be very expensive
451 //dc42_sync_to_disk(&P->DC42);
452
453
454 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
455
456 if ( errno )
457 {
458
459 EXIT(0,0,"Error reading ProFile Image! errno: %d, State:%d,IndexWrite:%d,ProfileCommand:%d,BSY:%d,Data:%d,CMDL:%d,buffer:%2x:%2x:%2x:%2x:%2x:%2x\n",
460 errno,
461 P->indexwrite,
462 P->StateMachineStep,P->Command,P->BSYLine,P->VIA_PA,P->CMDLine,
463 P->DataBlock[4],P->DataBlock[5],P->DataBlock[6],P->DataBlock[7],
464 P->DataBlock[8],P->DataBlock[9]);
465 }
466
467 P->Command=-2; // is now idle
468 P->indexread=0; // reset index pointers to status
469 P->indexwrite=4;
470 }
471
472
473
474 /******************************************************************************\
475 * Reset the Profile PB7 on VIA because we got a signal to do so or because *
476 * we just booted up. *
477 * *
478 \******************************************************************************/
479
init_Profiles(void)480 void init_Profiles(void)
481 {
482 //ProfileReset(via[0].ProFile); // this can be ignored since no profile lives here.
483 //
484 ProfileReset(via[1].ProFile);
485
486 ProfileReset(via[2].ProFile);
487 ProfileReset(via[3].ProFile);
488 ProfileReset(via[4].ProFile);
489 ProfileReset(via[5].ProFile);
490 ProfileReset(via[6].ProFile);
491
492
493 // ProFileType profiles[7]; -- no need these are attached to the VIA's, so it's via[x]->Profile. *Burp*
494 }
495
496
497
498
499
profile_unmount(void)500 void profile_unmount(void)
501 {
502 int i;
503 for ( i=2; i<9; i++)
504 {
505 if (via[i].ProFile)
506 { dc42_close_image(&via[i].ProFile->DC42);}
507
508 }
509
510 }
511
profile_mount(char * filename,ProFileType * P)512 int profile_mount(char *filename, ProFileType *P)
513 {
514 int i;
515
516 // Open the profile - if it doesn't exist, create it.
517 //9728+1 - 5mb profile + space for spare table at -1.
518
519
520 #ifndef __MSVCRT__
521 i=dc42_open(&P->DC42,filename,"wb");
522 #else
523 i=dc42_open(&P->DC42,filename,"wn"); //win32
524 #endif
525 if (i)
526 { int sz;
527 int blocks[]={9728,19456,32768,40960,65536,81920,131072};
528 // 0 1 2 3 4 5 6
529 // 5M 10M 16M 20M 32M 40M 64M
530
531 DEBUG_LOG(0,"Did not find %s, asking user what size drive to create",filename);
532 sz=pickprofilesize(filename); if (sz<0 || sz>6) return -1;
533
534 i=dc42_create(filename,"-lisaem.sunder.net hd-",blocks[sz]*512,blocks[sz]*20);
535 i=dc42_open(&P->DC42,filename,"wm");
536 //if (i) {DEBUG_LOG(0,"Failed to open newly created ProFile drive!"); exit(1);}
537 }
538
539 if (i) return -1;
540 // 9690blks ~~5mb? 9728-9690= 38
541 //19448blks ~~10mb? 19448+38 = 19486 likely is 19486 blocks.
542
543 return 0;
544 }
545
ProfileResetOff(ProFileType * P)546 void ProfileResetOff(ProFileType *P)
547 {
548 P->last_reset_cpuclk=-1;
549 }
550
ProfileReset(ProFileType * P)551 void ProfileReset(ProFileType *P)
552 {
553 if (!P) return;
554
555 P->DataBlock[0]=0;
556 P->DataBlock[1]=0;
557 PRO_STATUS_WAS_RESET;
558 P->DataBlock[3]=0;
559
560 // reset state machine
561
562 P->Command=-2; // is now idle
563 P->StateMachineStep=0; // no step, just idle
564 P->CMDLine=0;
565 P->BSYLine=0; // not busy
566 P->DENLine=1;
567 P->RRWLine=0;
568 P->VIA_PA= 1; // must always be 1 when ProFile is ready.
569 P->clock_e=0;
570 P->last_cmd=1;
571 //DEBUG_LOG(0,"PROFILE RESET - ACK 01 tag:via2_ora");
572 //append_profile_log(0,"PROFILE RESET - ACK 01 tag:via2_ora");
573
574 //if (cpu68k_clocks>1000 && !debug_log_enabled) { debug_on("profile-reset"); debug_log_enabled=1; }
575
576
577 // reset buffer pointers
578
579 P->indexread = 0; // reset index pointers to data
580 P->indexwrite = 4;
581
582 P->blocktowrite = 0;
583
584 P->last_a_accs = 0;
585 P->last_reset_cpuclk = 0;
586
587 memset(P->DataBlock, 0, 542);
588 }
589
590
591 /*
592 *
593 * this gets called by the VIA code. Via code passes pointer to profile structure AND
594 * sets the event. if the control lines are set, event code is zero, if data (pa read)
595 * then event=1, if pawrite event=2.
596 // uint8 CMDLine; // set by Lisa
597 // uint8 BSYLine; // set by ProFile
598 // uint8 DENLine; // set by Lisa (drive enabled)
599 // uint8 RRWLine; // set by Lisa (read or write)
600 //
601 // uint8 VIA_PA; // data to from VIA PortA (copied to/from V->via[0])
602 *
603 *
604 */
605
606
607
608
609 // Macros to make the code a lot more readable/maintainable
610
611 // these are why the profile loop was called
612 #define PROLOOP_EV_IRB 0 // event=0 <- Read from IRB
613 #define PROLOOP_EV_IRA 1 // event=1 <- Read from IRA
614 #define PROLOOP_EV_ORA 2 // event=2 <- write to ORA
615 #define PROLOOP_EV_ORB 3 // event=3 <- write to ORB
616 #define PROLOOP_EV_NUL 4 // event=4 <- null event - called occasionally by event handling to allow timeouts
617
618 #define EVENT_READ_IRB (event==0)
619 #define EVENT_READ_IRA (event==1)
620 #define EVENT_WRITE_ORA (event==2)
621 #define EVENT_WRITE_ORB (event==3)
622 #define EVENT_WRITE_NUL (event==4)
623
624
625 char *profile_event_names[5]=
626 {
627 "IRB",
628 "IRA",
629 "ORA",
630 "ORB",
631 "NUL"
632 };
633
634
635 // implement a timeout that resets the state machine back to state 0, and various delays.
636
637 // alarm_len_e gets set to x 1st to avoid using (x) twice - avoids macro side effects
638 #define SET_PROFILE_LOOP_TIMEOUT(x) {P->alarm_len_e=(x); P->clock_e=cpu68k_clocks + P->alarm_len_e;}
639
640 // same as above, but disable pre-entry delay
641 #define SET_PROFILE_LOOP_NO_PREDELAY(x) {P->alarm_len_e=0; P->clock_e=cpu68k_clocks + (x); }
642
643 #define CHECK_PROFILE_LOOP_TIMEOUT {if (P->clock_e<=cpu68k_clocks) \
644 { \
645 P->StateMachineStep=IDLE_STATE; \
646 SET_PROFILE_LOOP_TIMEOUT(TENTH_OF_A_SECOND);\
647 P->last_cmd=1; \
648 return;} \
649 }
650
651 //#define WAIT_FOR_PROFILE_LOOP_TIMEOUT {if (P->clock_e >cpu68k_clocks) return; } // delete me not used
652
653
654 // have we gone past x clk cycles since the last time the timeout was set? useful for faking delays.
655 #define TIMEPASSED_PROFILE_LOOP(x) ((P->clock_e - P->alarm_len_e+(x)) < cpu68k_clocks)
656
657 #define TIMEPASSED_LEFT(x) ((P->clock_e - P->alarm_len_e+(x)) )
658
659 // this disables the above, allowing us to skip the initial delay before a state becomes active.
660 #define DISABLE_TIMEPASSED_DELAY {P->alarm_len_e=0;}
661
662
663
664 // -- actual clock_expiration this is the bug, the issue is that it's the size of the window
665 // + . not the mini expiration I'm looking for.
666 // |\ .
667 // | \__alarm_e_len .
668 // | / <cpu68k_clocks
669 // |/ .
670 // | + .
671 // -- clock set . -- actually, no, this should work just fine
672
673 // steps of ProFile state machine
674
675 // initial handshaking steps - common to both read/write states
676
677 #define IDLE_STATE 0 // wait for Lisa to flip CMD, then send 01 and flip BSY
678 #define WAIT_1st_0x55_STATE 2 // wait for Lisa to answer 01 with 0x55
679
680 //define DELAY_BEFORE_CMD_STATE 3 // delay entry into next state <- get rid of this
681 #define GET_CMDBLK_STATE 4 // read the 6 byte cmd block from the Lisa, send cmd response byte
682
683 #define WAIT_2nd_0x55_STATE 5 // wait for 2nd 0x55 response to cmd response byte
684 #define PARSE_CMD_STATE 6 // parse the command and switch to read or write block
685
686 // states for block writes
687 #define ACCEPT_DATA_FOR_WRITE_STATE 7 // for write block, accept the data+tag bytes
688 #define WAIT_3rd_0x55_STATE 8 // wait for 3rd 0x55 confirmation before writing block
689 #define WRITE_BLOCK_STATE 9 // waste some time simulating a busy profile, and actually write the block
690 #define SEND_STATUS_BYTES_STATE 12 // Let Lisa read the status bytes after the write is done, then return to idle.
691
692 // states for block reads
693 #define SEND_DATA_AND_TAGS_STATE 10 // send the status+data+tags back to the Lisa
694 #define FINAL_FLIP_TO_IDLE_STATE 11 // short delay and return back to idle.
695
696
ProfileLoop(ProFileType * P,int event)697 void ProfileLoop(ProFileType *P, int event)
698 {
699 uint32 blocknumber=0;
700
701 if ( !(profile_power & (1<<(P->vianum-2)) ) ) return;
702
703 if ( !P->DENLine && P->vianum==2) {DEBUG_LOG(0,"DEN is disabled on via#%d- ignoring ProFile commands",P->vianum); return;} // Drive Enabled is off (active low 0=enabled, 1=disable profile)
704 if ( !P->DENLine && P->vianum!=2) {ALERT_LOG(0,"DEN is disabled on via#%d- ignoring ProFile commands",P->vianum); return;} // Drive Enabled is off (active low 0=enabled, 1=disable profile)
705
706
707 switch (P->StateMachineStep)
708 {
709
710
711 case IDLE_STATE: // 0 StateMachineStep is idle - wait for CMD to go low, then BUSY=0
712 CHECK_PROFILE_LOOP_TIMEOUT;
713
714 #ifdef DEBUG // don't fill up the log with useless shit
715 if (!(EVENT_WRITE_NUL))
716 DEBUG_LOG(0,"In state 0 now - idle - CMDLine is:%d && P->last_cmd:%d if non zero, should see state transition.",P->CMDLine,P->last_cmd);
717 #endif
718
719 P->BSYLine=0;
720 if (EVENT_WRITE_NUL) return;
721
722 // not active. If Lisa lowers CMD, we lower BSYLine and goto state 2
723 if (P->CMDLine && P->last_cmd) {
724 P->StateMachineStep=WAIT_1st_0x55_STATE;
725 SET_PROFILE_LOOP_TIMEOUT(TENTH_OF_A_SECOND);
726
727 P->BSYLine=1; // flip BSY
728 P->VIA_PA=0x01; // ACK cmd on bus
729 P->last_a_accs=0;
730
731 DEBUG_LOG(0,"ACK CMD - sending 01 - State Transition to 3");
732 return;
733 }
734
735 if (!P->CMDLine) P->last_cmd=1; // prevent a too early entry into state 3
736 else {
737 P->last_cmd=0;
738 SET_PROFILE_LOOP_TIMEOUT(HUN_THOUSANDTH_OF_A_SEC);
739 DEBUG_LOG(0,"cmd is still 0, lengthening timeout");
740
741 }
742
743
744 return;
745
746
747 // case 1: // waiting for CMD==1, if it does, raise BSY and ack with 01.
748 // CHECK_PROFILE_LOOP_TIMEOUT;
749 //
750 // P->last_cmd=0; // clear return to state 0 to wait for cmd toggle
751 //
752 // #ifdef DEBUG
753 // if (!(EVENT_WRITE_NUL))
754 // DEBUG_LOG(0,"In state 1 - waiting for CMD==0, if I get it will raise BSY. BSY:%d CMD:%d",P->BSYLine,P->CMDLine);
755 // #endif
756 //
757 //
758 // P->BSYLine=1;
759 //
760 //
761 // P->BSYLine=0;
762 // P->VIA_PA=0x01;
763 // P->last_a_accs=0;
764 //
765 // P->StateMachineStep=3; //skip 2 from now on
766 // SET_PROFILE_LOOP_TIMEOUT(TENTH_OF_A_SECOND);
767 // DEBUG_LOG(0,"ACK CMD - sending 01 - State Transition to 3");
768 //
769 //
770 // return;
771
772
773
774 case WAIT_1st_0x55_STATE: // 2 // Is CMDLine supposed to be down now?
775
776 CHECK_PROFILE_LOOP_TIMEOUT;
777
778 // basically, waith 1/100t of a second before flipping BSY, or if Lisa wrote a byte, then skip the wait
779 if ( !TIMEPASSED_PROFILE_LOOP(HUN_THOUSANDTH_OF_A_SEC) && !EVENT_WRITE_ORA) //20060429// was 1/1000th sec
780 {
781 #ifdef DEBUG // don't fill up the log with useless shit
782 if (!(EVENT_WRITE_NUL))
783
784 DEBUG_LOG(0,"In state 2 - wasting while waiting for 55, got %02x, last_a_accs:%d before turning BSY to 0: left:%016llx",
785 P->VIA_PA,
786 P->last_a_accs,
787 (TIMEPASSED_LEFT(HUN_THOUSANDTH_OF_A_SEC)-cpu68k_clocks)
788 );
789 #endif
790
791
792 P->BSYLine=0;
793 return;
794 }
795
796 P->BSYLine=1;
797 if (EVENT_WRITE_NUL) return;
798
799 #ifdef DEBUG // don't fill up the log with useless shit
800 if (!(EVENT_WRITE_NUL))
801
802 DEBUG_LOG(0,"In state 2 - waiting for 55, last PA=%02x, last_a_accs:%d - BSY is now %d",
803 P->VIA_PA,
804 P->last_a_accs,P->BSYLine);
805 #endif
806
807 // if ( EVENT_WRITE_ORA)//P->last_a_accs)// now wait for 0x55 ACK from Lisa, else, go back to idle
808 //{
809 if (P->VIA_PA!=0x55 && EVENT_WRITE_ORA) P->VIA_PA=0x01;
810 if (P->VIA_PA==0x55 && !P->CMDLine)
811 {
812 PRO_STATUS_GOT55;
813 P->StateMachineStep=GET_CMDBLK_STATE; //DELAY_BEFORE_CMD_STATE; //GET_CMDBLK_STATE;
814 SET_PROFILE_LOOP_TIMEOUT(FIFTH_OF_A_SECOND);
815
816 DEBUG_LOG(0,"State Transition to 4 - got 0x55");
817 P->indexread=4; // start at offset 4
818 P->indexwrite=4; // (4 byte preable reserved for status for lisa to read later
819 return;
820 }
821
822 // else
823
824 if (P->VIA_PA!=0x55 && P->VIA_PA!=0x01)
825 {
826 DEBUG_LOG(0,"VIA:%d did not get 55, got %02x, will go back to idle now. last_a_accs=%d",
827 P->vianum,P->VIA_PA,P->last_a_accs);
828
829 P->StateMachineStep=IDLE_STATE;
830 return;
831 }
832 //}
833 // if (P->VIA_PA!=0x55) P->VIA_PA=0x01; // resend ACK if we got here since we didn't get 0x55.
834
835 return;
836
837
838
839
840
841 case GET_CMDBLK_STATE: // 4 // now copy command bytes into command buffer
842 #ifdef DEBUG // don't fill up the log with useless shit
843 if (!(EVENT_WRITE_NUL))
844
845 DEBUG_LOG(0,"In state 4 - waiting for command");
846 #endif
847
848
849 CHECK_PROFILE_LOOP_TIMEOUT;
850
851 // wait a bit before flopping busy, but if Lisa sends a byte, accept it
852 if ( TIMEPASSED_PROFILE_LOOP(HUN_THOUSANDTH_OF_A_SEC) && !(EVENT_WRITE_ORA)) //was 1/100th
853 {
854 DEBUG_LOG(0,"State 4 - wasting 1/100,000th of a sec");
855 P->BSYLine=0;
856 return;
857 }
858
859
860 P->BSYLine=1;
861 if (EVENT_WRITE_NUL) return;
862
863 // step 4a
864 #ifdef DEBUG // don't fill up the log with useless shit
865 if (!(EVENT_WRITE_NUL)) DEBUG_LOG(0,"State4a: Waiting for event=2:%02x RRWline=1:%02x and !P->CMDLine:%02x",
866 event,P->RRWLine,P->CMDLine);
867 #endif
868
869 if (EVENT_WRITE_ORA && !P->CMDLine)
870 {
871
872 SET_PROFILE_LOOP_NO_PREDELAY(TENTH_OF_A_SECOND); // reset timeout when we get a byte
873
874 // avoid a 2nd write as 0x55
875 if (P->VIA_PA==0x55 && P->indexwrite==4)
876 {
877 DEBUG_LOG(0,"Ignoring 2nd 0x55 write to avoid sync issues");
878 return;
879 }
880
881
882 P->DataBlock[P->indexwrite++]=P->VIA_PA;
883
884 switch(P->indexwrite-1)
885 {
886 case 4 : DEBUG_LOG(0,"Wrote CMD %02x into ProFile Data block index:%d",P->VIA_PA,P->indexwrite-1); break;
887 case 5 : DEBUG_LOG(0,"Wrote MSB %02x into ProFile Data block index:%d",P->VIA_PA,P->indexwrite-1); break;
888 case 6 : DEBUG_LOG(0,"Wrote mid %02x into ProFile Data block index:%d",P->VIA_PA,P->indexwrite-1); break;
889 case 7 : DEBUG_LOG(0,"Wrote LSB %02x into ProFile Data block index:%d",P->VIA_PA,P->indexwrite-1); break;
890 case 8 : DEBUG_LOG(0,"Wrote RTRY %02x into ProFile Data block index:%d",P->VIA_PA,P->indexwrite-1); break;
891 case 9 : DEBUG_LOG(0,"Wrote SPAR %02x into ProFile Data block index:%d",P->VIA_PA,P->indexwrite-1); break;
892
893 default: DEBUG_LOG(0,"Wrote ???? %02x into ProFile Data block index:%d",P->VIA_PA,P->indexwrite-1);
894 }
895
896 if (P->indexwrite>542) P->indexwrite=4; // prevent overrun ?
897 return;
898 }
899
900 #ifdef DEBUG // don't fill up the log with useless shit
901 if (!(EVENT_WRITE_NUL))
902 DEBUG_LOG(0,"State4b: Waiting for CMDLine");
903 #endif
904
905 //step 4b
906 if (P->CMDLine) //for lisaos// && !P->RRWLine) // we are done.
907 {
908
909 // interpret command
910 blocknumber=(P->DataBlock[5]<<16) |
911 (P->DataBlock[6]<< 8) |
912 (P->DataBlock[7] ) ;
913
914 DEBUG_LOG(0,"In 4b. Lisa raised CMDLine, might go to step 5. blk#%d",blocknumber);
915
916 switch (P->DataBlock[4])
917 { //20060515-P->BSYLINE=0 replaced with 1
918 case 0 : P->VIA_PA=0x02; P->last_a_accs=0; P->BSYLine=1; DEBUG_LOG(0,"4b: ACK READ"); // read block
919 P->StateMachineStep=WAIT_2nd_0x55_STATE;
920 SET_PROFILE_LOOP_NO_PREDELAY(HALF_OF_A_SECOND);
921 return;
922
923
924 case 1 : P->VIA_PA=0x03; P->last_a_accs=0; P->BSYLine=1; DEBUG_LOG(0,"4b: ACK WRITE"); // write block
925 P->StateMachineStep=WAIT_2nd_0x55_STATE;
926 SET_PROFILE_LOOP_NO_PREDELAY(HALF_OF_A_SECOND);
927 return;
928
929 case 2 : P->VIA_PA=0x04; P->last_a_accs=0; P->BSYLine=1; DEBUG_LOG(0,"4b: ACK WRITE/VERIFY"); // write/verify block
930 P->StateMachineStep=WAIT_2nd_0x55_STATE;
931 SET_PROFILE_LOOP_NO_PREDELAY(HALF_OF_A_SECOND);
932 return;
933
934 default: P->VIA_PA=0x00; P->BSYLine=0;
935 P->StateMachineStep=IDLE_STATE;
936
937 DEBUG_LOG(0,"S4B. Returning %02x as response to Lisa's command %02x and going to step %d",
938 P->VIA_PA,
939 P->DataBlock[4],
940 P->StateMachineStep);
941 }
942 }
943
944 return;
945
946 case WAIT_2nd_0x55_STATE: // 5
947
948 #ifdef DEBUG // don't fill up the log with useless shit
949 if (!(EVENT_WRITE_NUL)) DEBUG_LOG(0,"State 5");
950 #endif
951
952 CHECK_PROFILE_LOOP_TIMEOUT;
953
954 #ifdef DEBUG // don't fill up the log with useless shit
955 if (!(EVENT_WRITE_NUL))
956 DEBUG_LOG(0,"State5: Waiting for EVENT_WRITE_ORA:%02x && P->last_a_accs:%02x && P->CMDLine>0:%02x && RRWLine>0:%02x && PortA=0x55:%02x",
957 event,
958 P->last_a_accs,
959 P->CMDLine,
960 P->RRWLine,
961 P->VIA_PA);
962 #endif
963
964 P->BSYLine=1; //2006.05.09 was 0
965 if (EVENT_WRITE_NUL) return;
966 if (EVENT_WRITE_ORA) // && P->last_a_accs && P->CMDLine && P->RRWLine)
967 { DEBUG_LOG(0,"State 5: checking what we got:%02x==0x55",P->VIA_PA);
968 if (P->VIA_PA==0x55) {
969 P->StateMachineStep=PARSE_CMD_STATE;
970 SET_PROFILE_LOOP_TIMEOUT(HALF_OF_A_SECOND);
971 PRO_STATUS_GOT55;
972
973 DEBUG_LOG(0,"State5: got 0x55 w00t!");
974 }
975
976 else
977
978 {
979 P->StateMachineStep=0; // possibly our old code
980 PRO_STATUS_NO55;
981 DEBUG_LOG(0,"State5: going into state 0 now. oh well.");
982 }
983 }
984
985 return;
986
987 case PARSE_CMD_STATE: //6 // now we execute the command after simulating a busy profile
988 // play some profile sounds now?
989 CHECK_PROFILE_LOOP_TIMEOUT;
990
991 if ( !TIMEPASSED_PROFILE_LOOP(HUN_THOUSANDTH_OF_A_SEC) ) // this block was disabled -200604025
992 {
993
994 #ifdef DEBUG // don't fill up the log with useless shit
995 if (!(EVENT_WRITE_NUL))
996 DEBUG_LOG(0,"State 6 - wasting cycles for a bit to simulate a busy profile (%d cycles)",PROFILE_WAIT_EXEC_CYCLE);
997 #endif
998
999 return;
1000 }
1001
1002 PRO_STATUS_CLEAR;
1003
1004 #ifdef DEBUG // don't fill up the log with useless shit
1005 if (!(EVENT_WRITE_NUL))
1006 DEBUG_LOG(0,"Done wasting cycles in step 6");
1007 #endif
1008
1009 P->indexread=0;
1010
1011 blocknumber=(P->DataBlock[5]<<16) | (P->DataBlock[6]<< 8) | (P->DataBlock[7] ) ;
1012
1013
1014 P->BSYLine=1; //20060425-moved from step 5, and re-enabled above delay to slow down
1015 if (EVENT_WRITE_NUL) return;
1016
1017 switch (P->DataBlock[4]) // Now execute the command
1018 {
1019
1020 case 0 :
1021 #ifdef DEBUG
1022 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1023 DEBUG_LOG(0,"step6: Reading block#%d,0x%06x - buffer: %02x.%02x.%02x.%02x(%02x )[%02x %02x %02x]:%02x:%02x %02x %02x %02x %02x %02x %02x",
1024 blocknumber, blocknumber,
1025 P->DataBlock[ 0],
1026 P->DataBlock[ 1],
1027 P->DataBlock[ 2],
1028 P->DataBlock[ 3],
1029 P->DataBlock[ 4],
1030 P->DataBlock[ 5],
1031 P->DataBlock[ 6],
1032 P->DataBlock[ 7],
1033 P->DataBlock[ 8],
1034 P->DataBlock[ 9],
1035 P->DataBlock[10],
1036 P->DataBlock[11],
1037 P->DataBlock[12],
1038 P->DataBlock[13],
1039 P->DataBlock[14],
1040 P->DataBlock[15]);
1041 #endif
1042
1043 do_profile_read(P,blocknumber);
1044 P->StateMachineStep=SEND_DATA_AND_TAGS_STATE;
1045 SET_PROFILE_LOOP_TIMEOUT(FIFTH_OF_A_SECOND);
1046 break;
1047 //no, this is bad//PRO_STATUS_GOT55; // force status[0] to return the got 0x55 status.
1048
1049 case 1 :
1050 case 2 :
1051
1052 P->StateMachineStep=ACCEPT_DATA_FOR_WRITE_STATE;
1053 P->indexwrite=10; // bytes 0-3 are status, 4-6 are cmd block, 10-522 are byte, 523-542 are tags.
1054 SET_PROFILE_LOOP_TIMEOUT(FIFTH_OF_A_SECOND);
1055
1056 #ifdef DEBUG
1057
1058
1059
1060
1061 DEBUG_LOG(0,"step6: (cmd:%02x) Fixin to write to block#%d,0x%06x - buffer: %02x.%02x.%02x.%02x(%02x )[%02x %02x %02x]:%02x:%02x %02x %02x %02x %02x %02x %02x",
1062 P->DataBlock[4],
1063 blocknumber, blocknumber,
1064 P->DataBlock[ 0],
1065 P->DataBlock[ 1],
1066 P->DataBlock[ 2],
1067 P->DataBlock[ 3],
1068 P->DataBlock[ 4],
1069 P->DataBlock[ 5],
1070 P->DataBlock[ 6],
1071 P->DataBlock[ 7],
1072 P->DataBlock[ 8],
1073 P->DataBlock[ 9],
1074 P->DataBlock[10],
1075 P->DataBlock[11],
1076 P->DataBlock[12],
1077 P->DataBlock[13],
1078 P->DataBlock[14],
1079 P->DataBlock[15]);
1080 #endif
1081
1082
1083
1084
1085 break; // write/verify block
1086
1087 default: P->StateMachineStep=IDLE_STATE;
1088 }
1089 return;
1090
1091
1092 case ACCEPT_DATA_FOR_WRITE_STATE: // 7 // handle write/write+verify - read bytes from lisa into buffer
1093
1094 CHECK_PROFILE_LOOP_TIMEOUT;
1095
1096 P->BSYLine=0;
1097
1098 #ifdef DEBUG // don't fill up the log with useless shit
1099 if (!(EVENT_WRITE_NUL))
1100
1101 DEBUG_LOG(0,"State 7 - ready to read bytes from ProFile for writes event:%02x bsy:%02x cmd:%02x rrw:%02x PA:%02x @%d",
1102 event, P->BSYLine, P->CMDLine, P->RRWLine, P->VIA_PA, P->indexwrite );
1103 #endif
1104
1105 if (EVENT_WRITE_NUL) return; //2006.05.19
1106
1107
1108 if (EVENT_WRITE_ORA && P->RRWLine && !P->CMDLine)
1109 {
1110 P->DataBlock[P->indexwrite++]=P->VIA_PA;
1111 if (P->indexwrite>552) {PRO_STATUS_BUFFER_OVERFLOW; P->StateMachineStep=0; DEBUG_LOG(0,"State 7 write buffer Overflow");}
1112 else SET_PROFILE_LOOP_TIMEOUT(TENTH_OF_A_SECOND);
1113
1114 }
1115 else
1116 if (P->CMDLine)
1117 {
1118 P->BSYLine=1;
1119 P->VIA_PA=0x06;
1120 DEBUG_LOG(0,"State7 ACK WRITE command with 06");
1121
1122 P->StateMachineStep=WAIT_3rd_0x55_STATE;
1123 SET_PROFILE_LOOP_TIMEOUT(FIFTH_OF_A_SECOND);
1124 }
1125 else
1126 {
1127 DEBUG_LOG(0,"State 7 did not recognize byte event:%02x bsy:%02x cmd:%02x rrw:%02x",
1128 event,
1129 P->BSYLine,
1130 P->CMDLine,
1131 P->RRWLine);
1132 }
1133
1134 return;
1135
1136
1137 case WAIT_3rd_0x55_STATE: // 8 // wait for 0x55 again
1138
1139 #ifdef DEBUG // don't fill up the log with useless shit
1140 if (!(EVENT_WRITE_NUL))
1141
1142 DEBUG_LOG(0,"State 8 - wait for 3rd 0x55 - write:bsy:%d",P->BSYLine);
1143 #endif
1144
1145 CHECK_PROFILE_LOOP_TIMEOUT;
1146 //
1147 //if (EVENT_WRITE_ORA && P->RRWLine && !P->CMDLine)
1148 //
1149
1150 P->BSYLine=1; //no this should always be 1 - do not change it!
1151 if (EVENT_WRITE_NUL) return;
1152
1153 if (EVENT_WRITE_ORA)
1154 {if (P->VIA_PA==0x55)
1155 {
1156 P->StateMachineStep=WRITE_BLOCK_STATE; // accept command
1157 SET_PROFILE_LOOP_TIMEOUT(FIFTH_OF_A_SECOND);
1158
1159 P->indexread=0;
1160 PRO_STATUS_GOT55;
1161 DEBUG_LOG(0,"Command accepted, transition to 9");
1162 }
1163 else
1164 {P->StateMachineStep=0;
1165 PRO_STATUS_NO55;}
1166 }
1167 return;
1168
1169
1170 case WRITE_BLOCK_STATE: // 8 // do the write and waste some time
1171 #ifdef DEBUG // don't fill up the log with useless shit
1172 if (!(EVENT_WRITE_NUL))
1173
1174 DEBUG_LOG(0,"State 9 - write and waste more time (%d)",PROFILE_WAIT_EXEC_CYCLE);
1175 #endif
1176
1177 CHECK_PROFILE_LOOP_TIMEOUT;
1178 if ( !TIMEPASSED_PROFILE_LOOP(HUN_THOUSANDTH_OF_A_SEC) ) return;
1179
1180 blocknumber=(P->DataBlock[5]<<16) |
1181 (P->DataBlock[6]<< 8) |
1182 (P->DataBlock[7] ) ;
1183
1184 #ifdef DEBUG
1185 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1186
1187 DEBUG_LOG(0,"Writing block#%d,0x%06x - buffer: %02x.%02x.%02x.%02x(%02x )[%02x %02x %02x]:%02x:%02x|%02x %02x %02x %02x %02x %02x",
1188 blocknumber, blocknumber,
1189 P->DataBlock[ 0],
1190 P->DataBlock[ 1],
1191 P->DataBlock[ 2],
1192 P->DataBlock[ 3],
1193 P->DataBlock[ 4],
1194 P->DataBlock[ 5],
1195 P->DataBlock[ 6],
1196 P->DataBlock[ 7],
1197 P->DataBlock[ 8],
1198 P->DataBlock[ 9],
1199 P->DataBlock[10],
1200 P->DataBlock[11],
1201 P->DataBlock[12],
1202 P->DataBlock[13],
1203 P->DataBlock[14],
1204 P->DataBlock[15]);
1205
1206 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
1207 DEBUG_LOG(0,"Tags: %02x %02x %02x %02x[%02x %02x]%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x ",
1208 P->DataBlock[522+ 0],
1209 P->DataBlock[522+ 1],
1210 P->DataBlock[522+ 2],
1211 P->DataBlock[522+ 3],
1212 P->DataBlock[522+ 4],
1213 P->DataBlock[522+ 5],
1214 P->DataBlock[522+ 6],
1215 P->DataBlock[522+ 7],
1216 P->DataBlock[522+ 0],
1217 P->DataBlock[522+ 9],
1218 P->DataBlock[522+ 10],
1219 P->DataBlock[522+ 11],
1220 P->DataBlock[522+ 12],
1221 P->DataBlock[522+ 13],
1222 P->DataBlock[522+ 14],
1223 P->DataBlock[522+ 15],
1224 P->DataBlock[522+ 16],
1225 P->DataBlock[522+ 17],
1226 P->DataBlock[522+ 18],
1227 P->DataBlock[522+ 19]
1228 );
1229
1230
1231
1232 #endif
1233
1234 do_profile_write(P,blocknumber);
1235
1236 P->indexwrite=4;
1237 P->indexread=0;
1238
1239 P->DataBlock[0]=0;
1240 P->DataBlock[1]=0;
1241 P->DataBlock[2]=0;
1242 P->DataBlock[3]=0;
1243
1244 P->BSYLine=0; //2006.05.17 was 1
1245 P->StateMachineStep=SEND_STATUS_BYTES_STATE;
1246 SET_PROFILE_LOOP_TIMEOUT(HALF_OF_A_SECOND);
1247
1248 return;
1249
1250
1251 case SEND_DATA_AND_TAGS_STATE: //10 // Let Lisa read the status/data
1252 #ifdef DEBUG // don't fill up the log with useless shit
1253 if (!(EVENT_WRITE_NUL))
1254 DEBUG_LOG(0,"State 10, allow Lisa to read the status and data - pointer:%d",P->indexread);
1255 #endif
1256
1257 P->BSYLine=0;
1258
1259 CHECK_PROFILE_LOOP_TIMEOUT;
1260 if (EVENT_WRITE_NUL) return;
1261
1262 if (!P->CMDLine)
1263 {
1264
1265 P->BSYLine=0; //2006.05.15
1266 if (EVENT_READ_IRA)
1267 {
1268 //P->BSYLine=0; //2006.05.15
1269 P->VIA_PA=P->DataBlock[P->indexread++];
1270 if (P->indexread>542)
1271 {
1272 DEBUG_LOG(0,"IndexRead went over 542, resetting to 0");
1273 P->indexread=0;
1274 }
1275
1276 P->last_a_accs=0;
1277 SET_PROFILE_LOOP_TIMEOUT(HALF_OF_A_SECOND); // reset timeout // was FIFTH_OF_A_SECOND
1278 DEBUG_LOG(0,"Returning %02x from index:%d",P->VIA_PA,P->indexread-1);
1279 }
1280 }
1281 else
1282 {
1283 #ifdef DEBUG
1284 if (P->indexread != 536)
1285 {
1286 blocknumber=(P->DataBlock[5]<<16) | (P->DataBlock[6]<< 8) | (P->DataBlock[7] );
1287 DEBUG_LOG(0,"Warning: read %d bytes instead of 536 for block read of sector #%08x (%x)",P->indexread,blocknumber,blocknumber);
1288 }
1289 #endif
1290
1291 if (EVENT_READ_IRA) // oops we fell out of sync - recover please!
1292 {
1293 P->VIA_PA=1; P->last_a_accs=0;
1294 P->StateMachineStep=WAIT_1st_0x55_STATE;
1295 SET_PROFILE_LOOP_TIMEOUT(TENTH_OF_A_SECOND);
1296 P->BSYLine=1; // flip BSY
1297 return;
1298 }
1299
1300 P->BSYLine=1;
1301 P->StateMachineStep=FINAL_FLIP_TO_IDLE_STATE; SET_PROFILE_LOOP_TIMEOUT(TEN_THOUSANDTH_OF_A_SEC);
1302 }
1303
1304 return;
1305
1306
1307
1308 case FINAL_FLIP_TO_IDLE_STATE: // 11
1309
1310 // let ProFile see BSY strobe for a short period, this speeds up LisaTest immensely. returns to state 0 via timeout
1311 CHECK_PROFILE_LOOP_TIMEOUT;
1312
1313 if (EVENT_READ_IRA) // oops we fell out of sync - recover please!
1314 {
1315 P->VIA_PA=1; P->last_a_accs=0;
1316 P->StateMachineStep=WAIT_1st_0x55_STATE;
1317 SET_PROFILE_LOOP_TIMEOUT(TENTH_OF_A_SECOND);
1318 P->BSYLine=1; // flip BSY
1319 return;
1320 }
1321
1322 P->BSYLine=1;
1323 return;
1324
1325
1326 case SEND_STATUS_BYTES_STATE: //12 // Let Lisa read the status/data
1327
1328 #ifdef DEBUG // don't fill up the log with useless shit
1329 if (!(EVENT_WRITE_NUL))
1330 DEBUG_LOG(0,"State 12, post write - allow Lisa to read the status and data - pointer:%d",P->indexread);
1331 #endif
1332
1333
1334 CHECK_PROFILE_LOOP_TIMEOUT;
1335
1336 P->BSYLine=0;
1337
1338 if (EVENT_WRITE_NUL || EVENT_READ_IRB) return;
1339
1340 if (!P->CMDLine)
1341 {
1342
1343 if (EVENT_READ_IRA)
1344 {
1345 P->VIA_PA=P->DataBlock[P->indexread++]; if (P->indexread>3) P->indexread=0;
1346 P->last_a_accs=0;
1347 SET_PROFILE_LOOP_TIMEOUT(HALF_OF_A_SECOND); // reset timeout // was FIFTH_OF_A_SECOND
1348 DEBUG_LOG(0,"Returning %02x from index:%d",P->VIA_PA,P->indexread-1);
1349 }
1350 }
1351 else
1352 {
1353 P->StateMachineStep=IDLE_STATE;
1354 }
1355
1356
1357 return;
1358
1359 default:
1360 DEBUG_LOG(0,"Unknown ProFile state %d, returning to idle.",P->StateMachineStep);
1361 P->StateMachineStep=IDLE_STATE;
1362 return;
1363 }
1364
1365 }
1366
1367
1368 // I gotta get home, dirty,
1369 // I haveta code.
1370 // we gotta code all day all night
1371 // You know it sounds right - mc++
1372