/* To: SCSI-2 CAM Committee From: Patrick Manley SyQuest Technology Subject: Physical to/from logical block address conversion and algorithm to determine mapping of scsi drives into int 13h head cylinder sector format. Contained in this document are four "C" language programs originated by myself and then edited and tested by Norman Morse of Syquest Technology. 1. Setsize converts a READ CAPACITY value to int 13h head cylinder sector requirements. 2. ltop does logical to physical conversion 3. ptol does physical to logical conversion 4. main is a test routine for 1, 2, & 3 */ typedef unsigned int UINT; typedef unsigned long ULNG; /* * Convert from logical block count to Cylinder Sector and head (int 13) */ setsize(capacity,cyls,hds,secs) ULNG capacity; UINT *cyls; UINT *hds; UINT *secs; { UINT rv = 0; ULNG heads = 4; ULNG sectors = 17L; ULNG cylinders = 0xffff; while (1) { cylinders = capacity / (heads * sectors); if (cylinders < 1024L) break; if (heads < 16L) heads = heads * 2; else { if (sectors < 64L){ if (sectors == 17L) sectors = 16L; sectors = sectors * 2; } else { if (heads < 256L){ heads = heads * 2; sectors = 16L; } else { rv = 1; /* error, capacity too large */ break; } } } } *cyls = (UINT) cylinders; *secs = (UINT) sectors; *hds = (UINT) heads; return(rv); } /* * logical to physical conversion */ ltop(block,hd_count,sec_count,cyl,hd,sec) ULNG block; /* block to convert */ UINT hd_count,sec_count; UINT *cyl,*hd,*sec; /* returned address */ { UINT spc; spc = hd_count * sec_count; *cyl = block / spc; *hd = (block % spc) / sec_count; *sec = (block % spc) % sec_count; } /* * Physical to logical conversion */ ULNG ptol(cyl,hd,sec,cyl_count,hd_count,sec_count) UINT cyl,hd,sec; /* address to convert */ UINT cyl_count,hd_count,sec_count; { ULNG cylsize; cylsize = sec_count * hd_count; return((cyl * cylsize) + (hd * sec_count) + sec); } /* * Test routine */ main() { ULNG mblock,block,block1,t; UINT c,h,s,v; UINT cyl,hd,sec; UINT oldc,oldh,olds; printf("Block translation test\n"); /* Allow testing of various device sizes and addresses */ while (1) { printf("\nEnter Max block number:"); scanf("%lu",&mblock); if (mblock){ v = setsize(mblock,&c,&h,&s); t = ((ULNG) c) * h * ((ULNG) s); printf("Max block %8lu, C:%4u H:%3u S:%3u Cap:%8lu RV:%d\n", mblock,c,h,s,t,v); } else break; do { printf("\tEnter block number:"); scanf("%lu",&block); if (block){ ltop(block,h,s,&cyl,&hd,&sec); block1 = ptol(cyl,hd,sec,c,h,s); printf("\tblock %8lu becomes C:%4u H:%3u S:%3u becomes %8lu\n", block,cyl,hd,sec,block1); } } while (block); } /* now we show all translations */ printf(" Address Conversion Table for int 13\n"); oldc = oldh = olds = 0; for(block = 0; block < 0xffffffffL; block += (h * ((ULNG) s))){ v = setsize(block,&c,&h,&s); if (oldh != h || olds != s || v){ t = ((ULNG) c) * h * ((ULNG) s); printf("Max block %8lu, C:%4u H:%3u S:%3u Cap:%8lu RV:%d\n", block,c,h,s,t,v); oldh = h; olds = s; } if (v){ printf("break at %08lx hex blocks\n",block); break; } } }