CODING ★ PROGRAMMATION : De port en port II - PROGRAMMATION DU CONTROLEUR DE DISQUETTES A TRAVERS LES PORTS (1ère partie) ★

De port en port : Programmation du contrôleur de disquettes à travers les ports [1/2] (Micro-Mag)Cours et Initiation MICROMAG

Prince de la programmation portuaire, le capitaine Rodriguez est de retour avec une nouvelle victime, le lecteur de disquettes.

Cette initiation à la programmation directe du circuit FDC 765 contrôlant le lecteur de disquettes nous éclaire sur les caractéristiques physiques des disquettes 3" et la façon dont le lecteur de disquettes, sous la férule du FDC, gère nos précieux fichiers. Assez d'informations pour nous permettre de réaliser à l'avenir nos propres routines de chargement. Aujourd'hui, la première partie de ce sujet important.

I - Ouvrons une disquette

Une disquette est divisée en pistes. Sur les disquettes 3” se trouvent exactement 42 pistes utilisables à tout moment. Mais les pistes n°40 et 41 (les deux dernières) sont particulières et la tête de lecture fait
des bruits bizarres lors de leur utilisation. De plus, elles peuvent engendrer quelques petits problèmes sur les DDI-1. C'est pourquoi il est recommandé aux néophytes d'éviter de les prendre en compte. Nous avons donc simplement 40 pistes (numérotées de 0 à 39). Chaque piste est divisée en secteurs, il y a en général 9 secteurs par piste. La longueur de chaque secteur est normalement de 512 octets, mais il est possible de modifier cette donnée afin de créer des secteurs plus longs ou plus courts. Le minimum est 128 octets, le maximum 4096 (dans ce cas, on ne peut guère mettre plus d'un secteur sur la piste considérée).

Lorsque nous formatons une disquette, nous créons en fait un certain nombre de secteurs d'une longueur donnée sur une ou plusieurs pistes. Il n'est pas obligatoire de donner la même longueur à tous les secteurs sur une même piste. La longueur d'un secteur s'exprime par une puissance de 2 (nous y reviendrons plus tard) grâce à la formule suivante: longueur = 128 x 2^n octets, "n" étant un nombre entier de 0 à 5.

Chaque secteur se distingue par un nom qui est un code hexadécimal de 8 bits; il peut donc aller de &00 à &FF. Lorsque l'on formate une disquette en data avec Discology (par exemple), le premier secteur sur le piste formatée a pour nom &C1. Logiquement, les 9 secteurs par piste de ce type de formatage auront pour noms respectifs &C1, &C2, &C3, &C4,.... , &C9. Pour une disquette formatée en Vendor, il y a également 9 secteurs par piste mais les noms sont &41, &42,.... , &49. Dans tous les cas, les secteurs font 512 octets chacun (n=2) et occupent donc 4608 octets par piste, soit une perte de 512 octets car une piste peut contenir jusqu'à 5 ko (5120 octets).

Nous pourrions également dire qu'un secteur est divisé en deux enregistrements de 128 octets et qu'un bloc contient deux secteurs, soit 1024 octets. Mais ces deux types de stockage ne sont que fictifs et créés par le système d'exploitation lui-même pour simplifier la tâche lors du chargement d'un fichier Basic ou binaire. Donc, nous les ignorerons pour nous intéresser à ce qui est réel et présent physiquement sur la disquette, c'est-à-dire les pistes et les secteurs.

II - Chargement de secteurs

Nous allons stocker en Ram le contenu de secteurs qui se trouvent sur une disquette. Prenons un exemple précis avec une disquette formatée en Vendor (comme par exemple, la disquette CP/M). Mettre le taquet de protection anti-écriture car lors de premiers essais, la disquette sacrifiée risque d'être mal en point. Nous ne pouvons charger un secteur par le Basic, ce n'est que par l'Assembleur que cette tâche est réalisable. Dans cet article est utilisé l'AmsDos. La Rom Disc (externe pour les possesseurs de 464) se situe entre les adresses &C000 et &FFFF et contient l'AmsDos et une partie de l'interpréteur du Logo. La routine permettant de lire un secteur se trouve à partir de &C666. Nous allons donc «connecter» pendant un instant cette Rom Disc, puis charger les registres qui contiendront les noms de code des pistes, secteurs, etc., et enfin appeler la routine précédemment citée. Finalement, nous «reconnecterons» le Rom Basic à la place de la Rom Disc, ceci afin de restaurer les mémoires.

Programme d'exemple à entrer sous un moniteur Assembleur.

Cette très courte routine charge à partir de &6000 le secteur de 512 octets de code &41, se trouvant sur la piste 2 d'une disquette formatée en Vendor (sur ce secteur se trouve une partie du directory, la mise au point d'un éditeur de secteurs devient  simple!).

A000 LD C,07       ' C-7 (adresse ROM Disc)
A002 CALL B90F   ' Connection ROM Disc entre &C000 et &FFFF.
A005 LD HL,6000  ' HL : adresse de départ du buffer de 512 octets.
A008 LD DE,0200  ' D : numéro piste, E : numéro disk drive (0=A, 1=B).
A00B LD C,41        ' C : code du secteur à charger.
A00D CALL C666    ' Chargement.
A010 LD C,00        ' C-0 (adresse ROMs OUT!).
A012 JP B90F        ' On déconnecte la ROM Disc et toutes les ROMs.

De façon analogue, il existe la fonction Ecrire un secteur qui se manipule exactement de la même manière (même chargement des registres). Cette routine est logée à l'adresse &C64E.

Une autre fonction intéressante est le formatage de pistes toujours en utilisant l'AmsDos. Le programme Format II que vous trouverez dans ce même article, vous permettra de formater n'importe quelle piste avec n'importe quels secteurs et n'importe quelles variables de base. N.B. La réponse aux questions du CPC concernant le formatage des pistes se trouve un peu plus loin (GAP#3, octet de formatage, ordre des secteurs,...). L'AmsDos possède une Ram système Disc qui est une zone de sauvegarde temporaire de données se trouvant entre &A700- &AB7F et entre &BE40-&BE7F. A ce sujet, certains programmes sur K7 ne peuvent être directement tranférés sur disquette, du fait de la zone &A700-&AB7F utilisée lors du chargement et qui plante l'ensemble. Il faut dans ce cas procéder à un découpage du programme, puis, une fois le programme chargé, recoller les morceaux. On peut taper dans la zone dise après un chargement sans que cela influence le cours des opérations. D'autre part, cette zone qui débute donc en &A700 peut commencer ailleurs. Il suffit de modifier le pointeur d'index IY se trouvant à l'adresse &BE7D-&BE7E.

Toujours dans le même ordre d'idée, une petite bidouille. Sachez que la zone &BE80-&BFC0 n'est jamais remise à zéro, même après une réinitialisation (CTRL/ SHIFT/ESC) ou encore CALL 0. Ceci peut être important pour développer des virus!

III - Le FDC765

Ignorons l'électronique de ce circuit que certains ouvrages traitent fort bien. Le FDC contient cinq registres d'état dont chacun de leur bits (8 x 5 = 40 bits), renvoie des informations sur la position de la tête de lecture par rapport à l'index (début d'une piste), la présence d'une disquette dans le lecteur, la protection ou non de la disquette,... et bien entendu un compte rendu d'état permettant de vérifier le bon déroulement d'une instruction.

Il y a en fait un registre d'état principal situé à l'adresse &FB7E qui peut être consulté à tout moment. Les quatre autres registres, situés à l'adresse &FB7F, peuvent être lus les uns après les autres. Remarque: ces registres (à lecture seule) ne sont lisibles que suite à une instruction déterminée.

On peut accéder en général aux registres d'état 0, 1 et 2 à la fin d'une instruction. En revanche, le registre d'état 3 ne peut être lu qu'après avoir lancé et attendu l'exécution de la routine permettant de connaître «l'état» du lecteur.

Description détaillée des cinq registres d'état du FDC

A - Registre principal

Bit 7: à 1, le FDC est prêt à recevoir ou à envoyer des données au Z80. S'il est à 0, il faut ajouter une routine de temporisation et re-tester ensuite ce bit.

  • Bit 6: quand le bit 7 est à la position high (1), ce bit 6 est significatif. S'il est à 1, le FDC attend une donnée. A 0, il en envoie une. Les bits 6 et 7 sont complémentaires et doivent être testés en permanence lors d'un chargement dise. Bit 5: à 1 lorsque les données envoyées par le FDC appartiennent à un secteur. Dans le cas contraire, elles appartiennent à la phase résultat qui suit la phase exécution.
  • Bit 4: à 1 lorsque le FDC est en train d'envoyer une donnée. Ne pas envoyer de données dans ce cas.
  • Bit 3-0: ces 4 bits indiquent le numéro du lecteur (quatre possibles) courant.

B - Registre d'état 0. Adresse : &FB7F

  • Bits 7 et 6: lors de l'exécution d'une instruction, ces deux bits indiquent si celle-ci se déroule bien ou non. Si les bits 7 & 6 sont tous deux à 1, alors l'instruction en cours est terminée et s'est bien déroulée. Dans tous les autres cas (3), un problème est apparu et l'instruction est interrompue.
  • Bit 5: à 1 lorsqu'une instruction est terminée.
  • Bit 4: est mis lorsqu'une erreur s'est produite dans le lecteur de disquettes.
  • Bit 3: à 1 si le lecteur de disquettes n'est pas prêt pour une opération de lecture ou d'enregistrement.
  • Bit 2: le FDC peut également gérer les lecteurs à double tête; ce 6it est mis lorsque c'est la deuxième tête qui travaille.
  • Bit 1, 0: ces 2 bits indiquent quel numéro du lecteur de disquettes est en fonctionnement au moment de la lecture du registre d'état. Deux bits donnent quatre possibilités, donc quatre lecteurs peuvent être connectés.

C - Registre d'état 1. Adresse : &FB7F

  • Bit 7: à 1 lorsque la tête de lecture vient de passer sur l'index indiquant la fin d'une piste.
  • Bit 6: non utilisé.
  • Bit 5: à 1 lorsqu'une erreur se produit quand le FDC lit la zone header d'un secteur.
  • Bit 4: à 1 lorsque la synchronisation entre l'envoi de données de la part du FDC et la réception de la part du Z80
    empêche le déroulement d'une instruction.
  • Bit 3: non utilisé.
  • Bit 2: est mis lorsque le FDC ne trouve pas un secteur ou une piste sur une disquette. Bit 1: à 1 si le taquet de protection contre l'écriture est mis alors que le FDC tente d'écrire sur la disquette.
  • Bit 0: à 1 lorsque le FDC ne trouve pas le header secteur (champ ID: identification).

D - Registre d'état 2. Adresse : &FB7F

  • Bit 7: non utilisé.
  • Bit 6: à 1 si le secteur courant (lo'ad or save) possède une «data adress» (control mark) utilisée pour les protections. Bit 5: même signification que le bit 5 du registre d'état 1.
  • Bit 4: est mis lorsque la piste courante lue n'est pas la même que celle demandée (différence dans le champ ID).
  • Bit 3: à 1 si, lors d'une instruction de vérification (SCAN), les données sont effectivement identiques.
  • Bit 2: contraire du bit 3.
  • Bit 1: identique au bit 4.
  • Bit 0: à 1 lorsque la data adress ne peut être lue lors d'une lecture du champ ID.

E - 5 registre d'état 3. Adresse : &FB7F

  • Bit 7: est mis lorsqu'une erreur se produit dans le lecteur de disquette.
  • Bit 6: est mis si la disquette dans le lecteur est protégée contre l'écriture.
  • Bit 5: à 0 s'il n'y a pas de disquette dans le lecteur sélectionné.
  • Bit 4: à 1 si la tête de lecture se trouve sur la piste 0.
  • Bit 3: à 1 = lecteur courant à double tête de lecture.
  • Bit 2: numéro de tête sélectionnée lors de la lecture.
  • Bits 1, 0: contiennent le numéro du lecteur de disquette courant.

Après cette overdose de bits, nous allons enfin pouvoir mettre en œuvre notre routine de chargement.

Le moteur du lecteur de disquettes peut être simplement mis en marche ou éteint, il suffit de faire OUT &FA7E,1 (on) ou OUT &FA7E,0 (off)

IV - Méthode générale

L'exécution d'une instruction programmée à travers les ports se divise en trois phases:

  • envoi de données du Z80 vers le FDC,
  • le FDC exécute l'instruction (le Z80 doit alors patienter),
  • le FDC envoie au Z80 les données relatives à l'instruction (contenu des registres d'état), afin de lui indiquer si elle s'est bien déroulée.

D'autre part, chaque secteur enregistré sur une piste possède son champ ID d'identification. Celui-ci contient quatre données: le numéro de piste sur laquelle il est enregistré, le numéro de la tête de lecture (0), le nom du secteur (0 à &FF) et la taille du secteur. Comme nous l'évoquions plus haut, la taille d'un secteur s'exprimant en octets se calcule par la formule t = 128 x 2^n octets.

On retrouve donc le nombre n dans l'ID.

Existe également le GAP, littéralement, le fossé: espace vide entre deux secteurs qui permet à la tête de lecture de se repositionner pour une autre action et surtout, pour que le FDC ait le temps de recevoir d'autres données
afin d'exécuter une autre instruction. Il y a plusieurs CAP, mais seulement le GAP#3 est intéressant car programmable par l'utilisateur. Il porte en général la valeur &52. Sachez toutefois que si la valeur donnée est trop petite, le formatage s'effectuera mal avec impossibilité de lire les secteurs ainsi formés. Si la valeur est trop grande (0 à &FF), vous ne pourrez stocker autant de secteurs voulus sur la disquette. La valeur &52 est celle du GAP#3 lors d'un formatage. Pour toute autre opération, la valeur doit être &2A.

L'octet de remplissage utilisé pour le formatage est la valeur 8 bits avec laquelle les secteurs seront remplis (en général, &E5).
Enfin, les secteurs peuvent être enregistrés sous la forme /CM (control mark), c'est-à-dire qu'ils sont considérés comme des secteurs effacés, mais ceci n'est que fictif. Le bit 6 du registre d'état 2 est mis lors de la lecture d'un tel secteur. On procède d'une façon analogue pour la lecture ou l'enregistrement d'un secteur /CM que pour un secteur «normal». Seuls changeVit les codes d'instruction qui ne sont plus &46,&00 (lecture d'un secteur normal), mais &4C,&00. De même pour l'écriture, ce n'est plus &45,&00 mais &49,&00. Rendez-vous le mois prochain avec la suite concrète (routine de chargement de secteurs et programme de formatage maison).

Stéphane Rodriguez, MICROMAG

★ EDITEUR: MICROMAG
★ ANNÉE: 1989
★ AUTEUR: STEPHANE RODRIGUEZ

CPCrulez[Content Management System] v8.7-desktop/cache
Page créée en 242 millisecondes et consultée 166 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.