JAK CZYTAÁ BY ODCZYTAÁ CZYLI GRZEBANIA PO DYSKACH CZÂĆÁ DRUGA W poprzednim odcinku (jak pewnie pamiętasz) pokazaîem jak wîćczyç silnik dysku, jak odnaleűç ţćdanć őcieţkę, jak jć odczytaç uţywajćc DMA, wreszcie jak wyîćczyç silnik. Poza tym opowiedziaîem co nieco o sposobie zapisu danych (format sektora na őcieţce), oraz sposobie ich kodowania i dekodowania. Teraz chciaîbym zajćç się szczegóîowo tym ostatnim, czyli dekodowaniem sektora, oraz podaç peînć procedurę odczytu pojedynczego sektora o dowolnej pozycji na dysku. Co do procedury ReadDisk to wszystkie komentarze sć w języku angielskim (jeţeli umieszczam komentarze to zawsze sć one w tym języku), po prostu sć one w ten sposób zwięzîe i zrozumiaîe. Kod űródîowy powinien znaleűç się na dysku (moţe w katalogu sources ?). OK, to tyle tytuîem wstępu, a teraz przechodzę do pierwszego problemu, czyli dekodowanie sektora. Format sektora podaîem w poprzednim odcinku, więc tu go nie będę przypominaî. Zaznaczę tylko (co jest bardzo waţne), ţe kaţde dîugie sîowo jest zapisane w postaci zakodowanej MFM, czyli jest rozbite na dwa dîugie sîowa, najpierw dîugie sîowo nieparzyste a potem parzyste. Dekodowanie sektora polegaç będzie więc na poîćczeniu poszczególnych dîugich sîów a następnie zapisanie ich pod odpowiednim adresem (juţ jako zdekodowane). Oczywiőcie sektor zaczyna się nagîówkiem, moţna go pominćç caîkowicie (tak jak moja procedura) lub teţ policzyç odpowiednie sumy kontrolne w celu sprawdzenia poprawnoőci odczytu i wykrycia ewentualnych bîędów (co zostawiam czytelnikowi jako samodzielny problem). Sumy kontrolne danych i nagîówka sć obliczane przez zwykîe dziaîanie eor.l (jak pokazane w przykîadzie) na zakodowanych danych (lub nagîówku): move #255,d7 ;dane, 256 dîugich sîów czyli 1024 bajty lea data(pc),a0 ;adres poczćtku danych clr.l d0 ;w d0.l będzie obliczona suma kontrolna .loop move.l (a0)+,d1 eor.l d1,d0 dbf d7,.loop A oto procedura dekodowania pojedynczego sektora, bez obliczania jego sum kontrolnych. Przy wejőciu procedura potrzebuje w A2 adresu sektora (zaraz po sîowie SYNC), np. odszukanego procedurć SearchSector, natomiast w A3 adresu gdzie przesyîaç odkodowane dane. ;--------------- DECODE SINGLE SECTOR -------------------------------- DecodeSector: ;a2-sector addr, a3-data addr ;uses: d0,d1,d4,d6,a0,a4 movem.l d0/d1/d4/d6/a2-a4,-(sp) lea 56(a2),a2 ;skip header move.l #$55555555,d4 move.l #127,d6 ;128 long words lea $200(a2),a4 ;odd bits address .dloop move.l (a2)+,d0 ;even bits move.l (a4)+,d1 ;odd bits and.l d4,d0 ;filter add.l d0,d0 ;shift 1 bit left and.l d4,d1 ;filter or.l d0,d1 move.l d1,(a3)+ ;save decoded long word dbf d6,.dloop movem.l (sp)+,d0/d1/d4/d6/a2-a4 rts W trakcie prób odczytu z dysku pojawiî się następujćcy problem: okazaîo się, ţe stacja dysków nie odczytuje őcieţki zawsze od tego samego miejsca, tzn. nie zawsze sektory na odczytanej őcieţce sć w kolejnoőci, sektor 0, sektor 1, sektor 2, itd. aţ do sektora 10. Po prostu gîowica jest w dowolnym momencie opuszczana na dysk i odczytuje őcieţkę poczynajćc od pierwszego sîowa SYNC jakie napotka, a które znajdujć się w nagîówku kaţdego sektora. Czyli moţe się zdarzyç (i tak się dzieje prawie zawsze), ţe sektory będć miaîy kolejnoőç np. sektor 9, sektor 10, sektor 0, sektor 1, itd. aţ do sektora 8. Konieczne okazaîo się więc napisanie procedury wyszkujćcej dany sektor na odczytanej őcieţce. Procedura dziaîa w ten sposób, ţe szuka sîowa SYNC, omija je, a następnie z nagîówka sektora dekoduje tylko numer bloku i porównuje go z ţćdanym. Przy wejőciu procedura potrzebuje w D1 numer sektora szukanego (od 0 do 10) oraz w A1 adres pod którym znajdujć się dane őcieţki (odczytane z dysku). Po wyjőciu w rejestrze A2 znajduje się adres nagîówka ţćdanego sektora. ;--------------- SEARCH SECTOR IN TRACK ------------------------------ SearchSector: ;d1-sector nr., a1-track addr. ;uses: d0,d2,a2 movem.l d0/d2,-(sp) move.l a1,a2 .search cmp #$4489,(a2)+ bne.s .search cmp #$4489,(a2) beq.s .search move.l (a2),d0 move.l 4(a2),d2 and.l #$55555555,d0 add.l d0,d0 and.l #$55555555,d2 or.l d0,d2 and.l #$0000ff00,d2 lsr #8,d2 cmp d1,d2 bne.s .search movem.l (sp)+,d0/d2 rts ;a2-sector addr Poza tymi dwoma procedurami, największy kîopot sprawiî następujćcy problem: uţywajćc np. trackdisk.device i procedury DoIO, podajemy tylko adres gdzie dane z dysku majć byç umieszczone, numer pierwszego sektora z dysku, oraz iloőç sektorów do odczytania. Czyli np. moţe się zdarzyç, ţe potrzeba będzie odczytaç trzynaőcie sektorów, jeden ze őcieţki 2, jedenaőcie ze őcieţki 3 oraz jeden ze őcieţki 4. I ten problem rozwićzuje procedura ReadSectors. Nie będę jej tu opisywaî, zajęîo by to zbyt duţo miejsca, ale wydaje mi się, ţe wystarczy parę minut analizowania i okaţe się, ţe dziaîanie jest bardzo proste. Moja procedura dziaîa poprawnie, potrzebuje tylko 2 X $1900 sîow (czyli 12800 bajtów) pamięci na bufor őcieţki. A jak dziaîa moţesz zobaczyç sam, gdyţ zostaîa uţyta w music dysku "Artistic Noise". W trakcie pisania kodu okazaîo się, ţe w procedurce WaitAMoment zbyt maîa iloőç wykonanych pętli ($800) powodowaîa drobne przekîamania przy odczycie z niskiej jakoőci dysków, a nawet z dysków dwu- trzykrotnie nagranych !!!. Po zmianie wartoőci z $800 na $1000 wszystko dziaîa poprawnie, no moţe poza tym, ţe procedura dziaîa trochę wolniej ... Gdybyő miaî jakieő kîopoty, lub chciaîbyő dowiedzieç się więcej o odczycie sprzętowym z dysku, to napisz do mnie pod adres: PEPSI Drinkers HQ Radosîaw Chyra ul. Koőnego 36/2 45-056 OPOLE CHYRAS/PEPSI Drinkers Inc.