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