GE-115 Emulator
An Emulator of the General Electrics GE-115 computer
disk.c
Go to the documentation of this file.
1/*
2 * disk.c — functional DSS 156-157 disk pack on a standard connector (3/4).
3 *
4 * A flat sectored image (SECTOR_BYTES logical bytes per sector). A read TPER
5 * transfers the current sector to CPU memory: each logical byte is split into
6 * its high then low nibble for presentation, because the connector's binary
7 * read mode (order-block z=0) packs the low nibble of two presented bytes into
8 * one memory byte (verified against the channel-1 datapath). So presenting
9 * (b>>4, b&0x0F) reconstructs b in memory.
10 *
11 * Scope (functional MVP): READ of the current sector works end to end. Sector
12 * addressing (SEEK) and WRITE are placeholders pending the real DSS order codes
13 * and geometry (descriptive volume not yet extracted) — see the TODOs.
14 */
15
16#include "disk.h"
17#include "ge.h"
18#include "connector34.h"
19#include "log.h"
20
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24
25/* TODO: real geometry from the DSS 156-157 descriptive volume. */
26#define SECTOR_BYTES 64
27#define DEFAULT_SECTORS 64
28
29/* TODO: real CPER order codes from the DSS 156-157 descriptive volume. */
36
37struct disk_ctx {
38 uint8_t connector;
39 uint8_t unit;
40 uint8_t *image;
41 size_t nbytes;
42 uint32_t nsectors;
45};
46
47static int disk_claims(void *opaque, struct std_unitname un)
48{
49 struct disk_ctx *d = (struct disk_ctx *)opaque;
50 return un.connector == d->connector && un.unit == d->unit;
51}
52
53static std_reaction disk_command(struct ge *ge, void *opaque,
54 struct std_unitname un, uint8_t order)
55{
56 struct disk_ctx *d = (struct disk_ctx *)opaque;
57 (void)ge; (void)un;
58
59 switch (order) {
60 case DISK_ORD_SEEK:
61 /* TODO: decode the target cylinder/head/sector from the real order
62 * block once the DSS format is known; for now SEEK is accepted as a
63 * no-op (the read transfers current_sector). */
65 case DISK_ORD_READ:
66 case DISK_ORD_WRITE:
67 case DISK_ORD_FORMAT:
69 default:
70 return STD_ACCEPTED_NO_END; /* unknown orders accepted, no effect */
71 }
72}
73
74static std_reaction disk_transfer(struct ge *ge, void *opaque,
75 struct std_unitname un, int dir,
76 uint8_t *buf, uint16_t *len, uint16_t cap)
77{
78 struct disk_ctx *d = (struct disk_ctx *)opaque;
79 (void)ge; (void)un;
80
81 if (d->current_sector >= d->nsectors) {
82 *len = 0;
83 return STD_NOT_POSSIBLE; /* addressed past end of pack */
84 }
85
86 const uint8_t *sec = d->image + (size_t)d->current_sector * SECTOR_BYTES;
87
88 if (dir == 0) {
89 /* READ: nibble-split each logical byte for the packing channel. */
90 uint16_t n = 0;
91 for (int i = 0; i < SECTOR_BYTES && n + 2 <= cap; i++) {
92 buf[n++] = (uint8_t)(sec[i] >> 4);
93 buf[n++] = (uint8_t)(sec[i] & 0x0F);
94 }
95 *len = n;
96 return STD_ACCEPTED_END;
97 }
98
99 /* dir == 1 (WRITE): the connector output path is not yet wired in the core
100 * (only the channel-1 input transfer is). TODO with the output micro-flow. */
101 *len = 0;
102 return STD_NOT_POSSIBLE;
103}
104
105int disk_register(struct ge *ge, const char *image_path,
106 uint8_t connector, uint8_t unit)
107{
108 struct disk_ctx *d = calloc(1, sizeof(*d));
109 if (!d)
110 return -1;
111
112 d->connector = connector;
113 d->unit = unit;
115 d->nbytes = (size_t)d->nsectors * SECTOR_BYTES;
116 d->current_sector = 0;
117 d->image = calloc(1, d->nbytes);
118 if (!d->image) {
119 free(d);
120 return -1;
121 }
122
123 if (image_path) {
124 FILE *f = fopen(image_path, "rb");
125 if (f) {
126 size_t got = fread(d->image, 1, d->nbytes, f);
127 fclose(f);
128 ge_log(LOG_PERI, "disk: loaded %zu bytes from %s\n", got, image_path);
129 } else {
130 ge_log(LOG_ERR, "disk: cannot open %s (blank pack)\n", image_path);
131 }
132 }
133
134 d->dev.name = "DSS disk";
135 d->dev.ctx = d;
139 d->dev.tick = NULL;
140
141 if (connector34_init(ge) != 0)
142 return -1;
143 return connector34_attach(ge, &d->dev, connector);
144}
int connector34_init(struct ge *ge)
int connector34_attach(struct ge *ge, struct ge_std_device *dev, uint8_t connector)
std_reaction
Definition connector34.h:32
@ STD_ACCEPTED_END
Definition connector34.h:34
@ STD_ACCEPTED_NO_END
Definition connector34.h:33
@ STD_NOT_POSSIBLE
Definition connector34.h:36
static std_reaction disk_command(struct ge *ge, void *opaque, struct std_unitname un, uint8_t order)
Definition disk.c:53
int disk_register(struct ge *ge, const char *image_path, uint8_t connector, uint8_t unit)
Definition disk.c:105
static int disk_claims(void *opaque, struct std_unitname un)
Definition disk.c:47
disk_order
Definition disk.c:30
@ DISK_ORD_READ
Definition disk.c:32
@ DISK_ORD_WRITE
Definition disk.c:33
@ DISK_ORD_SEEK
Definition disk.c:31
@ DISK_ORD_FORMAT
Definition disk.c:34
#define DEFAULT_SECTORS
Definition disk.c:27
#define SECTOR_BYTES
Definition disk.c:26
static std_reaction disk_transfer(struct ge *ge, void *opaque, struct std_unitname un, int dir, uint8_t *buf, uint16_t *len, uint16_t cap)
Definition disk.c:74
void ge_log(ge_log_type type, const char *format,...)
Log message.
Definition log.c:122
@ LOG_ERR
Emulator unrecoverable condition.
Definition log.h:18
@ LOG_PERI
Peripherals IO.
Definition log.h:27
uint8_t unit
Definition disk.c:39
uint32_t nsectors
Definition disk.c:42
uint8_t connector
Definition disk.c:38
size_t nbytes
Definition disk.c:41
struct ge_std_device dev
Definition disk.c:44
uint8_t * image
Definition disk.c:40
uint32_t current_sector
Definition disk.c:43
void(* tick)(struct ge *, void *ctx)
Definition connector34.h:72
int(* claims)(void *ctx, struct std_unitname un)
Definition connector34.h:56
const char * name
Definition connector34.h:51
std_reaction(* command)(struct ge *, void *ctx, struct std_unitname un, uint8_t order)
Definition connector34.h:60
std_reaction(* transfer)(struct ge *, void *ctx, struct std_unitname un, int dir, uint8_t *buf, uint16_t *len, uint16_t cap)
Definition connector34.h:68
The entire state of the emulated system, including registers, memory, peripherals and timings.
Definition ge.h:96
uint8_t unit
Definition connector34.h:43
uint8_t connector
Definition connector34.h:42