11 /* SCSI Backbus interface */
12 #define BB_REG_LINES 0
13 #define BB_LINES_BSY 7
14 #define BB_LINES_SEL 6
15 #define BB_LINES_ACK 5
16 #define BB_LINES_ATN 4
17 #define BB_LINES_RST 3
19 #define BB_REG_ASSERT 1
20 #define BB_ASSERT_BSY 7
21 #define BB_ASSERT_SEL 6
22 #define BB_ASSERT_CD 5
23 #define BB_ASSERT_IO 4
24 #define BB_ASSERT_MSG 3
25 #define BB_ASSERT_REQ 2
26 #define BB_ASSERT_RST 1
27 #define BB_ASSERT_AUTO 0 /* Automatic mode */
29 #define BB_REG_ODATA 2
30 #define BB_REG_IDATA 3
31 #define BB_REG_ACNT_HI 4
32 #define BB_REG_ACNT_LO 5
34 #define MASK(bit) (1u << (bit))
36 static unsigned char scsi_cmd[12];
37 static unsigned char scsi_assert;
38 static unsigned long scsi_size;
40 #define scsi_dbg(fmt...)
46 size = fat_open("MACHD IMG");
48 printf("File MACHD.IMG not found !\n");
55 static unsigned char scsi_get_lines(void)
60 do_spi(BB_REG_SCSI_BASE | BB_REG_LINES);
68 static void scsi_set_assert(void)
71 do_spi(BB_WRITE | BB_REG_SCSI_BASE | BB_REG_ASSERT);
78 static unsigned char scsi_get_data(void)
83 do_spi(BB_REG_SCSI_BASE | BB_REG_ODATA);
91 static void scsi_set_data(unsigned char val)
94 do_spi(BB_WRITE | BB_REG_SCSI_BASE | BB_REG_IDATA);
99 static void scsi_set_autocnt(unsigned short cnt)
102 do_spi(BB_WRITE | BB_AUTOINC | BB_REG_SCSI_BASE | BB_REG_ACNT_HI);
108 static unsigned char scsi_do_data_in(unsigned short len)
110 unsigned short i = 0;
112 scsi_assert |= MASK(BB_ASSERT_AUTO) | MASK(BB_ASSERT_IO);
114 scsi_set_autocnt(len);
117 do_spi(BB_WRITE | BB_REG_SCSI_BASE | BB_REG_IDATA);
120 /* Handhake goes down approx. 160ns after the above
121 * and we then need to wait for it to go back up,
122 * the PIC executes an instruction in about 200ns so
123 * we shouldn't need any delay here before we test it
127 scsi_assert &= ~MASK(BB_ASSERT_AUTO);
132 static unsigned char scsi_do_data_out(unsigned short len)
134 unsigned short i = 0;
136 scsi_assert |= MASK(BB_ASSERT_AUTO);
137 scsi_assert &= ~MASK(BB_ASSERT_IO);
139 scsi_set_autocnt(len);
142 do_spi(BB_REG_SCSI_BASE | BB_REG_ODATA);
143 /* See handshake timing comment in scsi_do_data_in() */
152 secbuf[i++] = do_spi(0xff);
154 scsi_assert &= ~MASK(BB_ASSERT_AUTO);
159 static unsigned char scsi_do_read(unsigned long lba,
162 unsigned char rc = true;
170 rc = fat_file_read();
175 scsi_do_data_in(512);
177 rc = fat_file_next_sector();
183 static unsigned char scsi_do_write(unsigned long lba,
193 scsi_do_data_out(512);
194 rc = fat_file_write();
196 rc = fat_file_next_sector();
206 static unsigned char scsi_do_cmd(void)
211 switch(scsi_cmd[0]) {
213 printf("scsi: TEST_UNIT_READY !\n");
216 printf("scsi: REQUEST_SENSE !\n");
218 memset(secbuf, 0, 13);
220 return scsi_do_data_in(13);
222 printf("scsi: FORMAT_UNIT !\n");
225 lba = scsi_cmd[1] & 0x1f;
226 lba = (lba << 8) | scsi_cmd[2];
227 lba = (lba << 8) | scsi_cmd[3];
231 printf("scsi: READ6 (lba=%lx cnt=%x) !\n", lba, cnt);
232 return scsi_do_read(lba, cnt);
234 lba = scsi_cmd[1] & 0x1f;
235 lba = (lba << 8) | scsi_cmd[2];
236 lba = (lba << 8) | scsi_cmd[3];
240 printf("scsi: WRITE6 (lba=%lx cnt=%x) !\n", lba, cnt);
241 return scsi_do_write(lba, cnt);
243 printf("scsi: INQUIRY !\n");
245 memset(secbuf, 0, 36);
246 memcpy(secbuf + 8, " SEAGATE", 8);
247 memcpy(secbuf + 16, " ST225N", 16);
252 return scsi_do_data_in(cnt);
254 printf("scsi: MODE_SELECT !\n");
257 printf("scsi: MODE_SENSE !\n");
260 printf("scsi: START_STOP !\n");
263 printf("scsi: READ_CAPACITY !\n");
266 printf("scsi: READ10 !\n");
268 lba = (lba << 8) | scsi_cmd[3];
269 lba = (lba << 8) | scsi_cmd[4];
270 lba = (lba << 8) | scsi_cmd[5];
272 cnt = (cnt << 8) | scsi_cmd[8];
273 return scsi_do_read(lba, cnt);
275 printf("scsi: WRITE10 !\n");
277 lba = (lba << 8) | scsi_cmd[3];
278 lba = (lba << 8) | scsi_cmd[4];
279 lba = (lba << 8) | scsi_cmd[5];
281 cnt = (cnt << 8) | scsi_cmd[8];
282 return scsi_do_write(lba, cnt);
284 printf("scsi: VERIFY10 !\n");
287 printf("scsi: READ_BUFFER !\n");
293 static void scsi_req_ack(void)
297 scsi_assert |= MASK(BB_ASSERT_REQ);
300 l = scsi_get_lines();
301 while (!(l & MASK(BB_LINES_ACK)));
304 static void scsi_nreq_nack(void)
308 scsi_assert &= ~MASK(BB_ASSERT_REQ);
311 l = scsi_get_lines();
312 while (l & MASK(BB_LINES_ACK));
317 unsigned char lines, val, i, len, stat;
319 lines = scsi_get_lines();
320 if ((lines & MASK(BB_LINES_SEL)) /*&& !(lines & MASK(BB_LINES_BSY)) */) {
321 val = scsi_get_data();
322 if (!(val & MASK(6))) {
323 //printf("scsi: Wrong ID 0x%x\n", val);
326 scsi_assert = MASK(BB_ASSERT_BSY);
328 } else if (lines & MASK(BB_LINES_RST)) {
329 printf("scsi: RESET !\n");
332 printf("scsi: Glitch (reset ?) lines=%x!\n", lines);
335 while(lines & MASK(BB_LINES_SEL))
336 lines = scsi_get_lines();
337 /* XXX Check for ATN for MESSAGE_OUT phase, Mac ROM doesn't do it */
338 scsi_dbg("scsi: Selected, command phase...\n");
342 scsi_assert |= MASK(BB_ASSERT_CD);
346 val = scsi_get_data();
347 scsi_cmd[i++] = scsi_get_data();
348 scsi_dbg("scsi: CMD = 0x%x\n", val);
350 if (val == 0x00 || /* TEST_UNIT_READY */
351 val == 0x03 || /* REQUEST_SENSE */
352 val == 0x04 || /* FORMAT_UNIT */
353 val == 0x08 || /* READ6 */
354 val == 0x0a || /* WRITE6 */
355 val == 0x12 || /* INQUIRY */
356 val == 0x15 || /* MODE_SELECT */
357 val == 0x1a || /* MODE_SENSE */
358 val == 0x1b || /* START_STOP */
359 val == 0x3c || /* READ_BUFFER */
362 else if (val == 0x25 || /* READ_CAPACITY */
363 val == 0x28 || /* READ10 */
364 val == 0x2a || /* WRITE10 */
365 val == 0x2f || /* VERIFY10 */
377 scsi_assert &= ~MASK(BB_ASSERT_CD);
378 stat = scsi_do_cmd();
379 scsi_dbg("Status phase (stat=%x)\n", stat);
380 scsi_assert |= MASK(BB_ASSERT_IO) | MASK(BB_ASSERT_CD);
384 scsi_dbg("Message IN phase (stat=%x)\n", stat);
385 scsi_assert |= MASK(BB_ASSERT_MSG);