192f2ca38SAlexander Graf /* 292f2ca38SAlexander Graf * S390 virtio-ccw loading program 392f2ca38SAlexander Graf * 492f2ca38SAlexander Graf * Copyright (c) 2013 Alexander Graf <agraf@suse.de> 592f2ca38SAlexander Graf * 692f2ca38SAlexander Graf * This work is licensed under the terms of the GNU GPL, version 2 or (at 792f2ca38SAlexander Graf * your option) any later version. See the COPYING file in the top-level 892f2ca38SAlexander Graf * directory. 992f2ca38SAlexander Graf */ 1092f2ca38SAlexander Graf 1192f2ca38SAlexander Graf #include "s390-ccw.h" 12*60612d5cSEugene (jno) Dvurechenski #include "virtio.h" 1392f2ca38SAlexander Graf 1492f2ca38SAlexander Graf char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); 15ff151f4eSDominik Dingel uint64_t boot_value; 1692f2ca38SAlexander Graf 1792f2ca38SAlexander Graf void virtio_panic(const char *string) 1892f2ca38SAlexander Graf { 1992f2ca38SAlexander Graf sclp_print(string); 207f61cbc1SChristian Borntraeger disabled_wait(); 2192f2ca38SAlexander Graf while (1) { } 2292f2ca38SAlexander Graf } 2392f2ca38SAlexander Graf 24ff151f4eSDominik Dingel static void virtio_setup(uint64_t dev_info) 2592f2ca38SAlexander Graf { 265d739a47SChristian Borntraeger struct subchannel_id blk_schid = { .one = 1 }; 2722d67ab5SCornelia Huck struct schib schib; 2892f2ca38SAlexander Graf int i; 2992f2ca38SAlexander Graf int r; 3092f2ca38SAlexander Graf bool found = false; 31ff151f4eSDominik Dingel bool check_devno = false; 32ff151f4eSDominik Dingel uint16_t dev_no = -1; 3392f2ca38SAlexander Graf 34ff151f4eSDominik Dingel if (dev_info != -1) { 35ff151f4eSDominik Dingel check_devno = true; 36ff151f4eSDominik Dingel dev_no = dev_info & 0xffff; 37ff151f4eSDominik Dingel debug_print_int("device no. ", dev_no); 38c8cda874SDominik Dingel blk_schid.ssid = (dev_info >> 16) & 0x3; 39c8cda874SDominik Dingel if (blk_schid.ssid != 0) { 40c8cda874SDominik Dingel debug_print_int("ssid ", blk_schid.ssid); 41c8cda874SDominik Dingel if (enable_mss_facility() != 0) { 42c8cda874SDominik Dingel virtio_panic("Failed to enable mss facility\n"); 43c8cda874SDominik Dingel } 44c8cda874SDominik Dingel } 45ff151f4eSDominik Dingel } 46ff151f4eSDominik Dingel 4792f2ca38SAlexander Graf for (i = 0; i < 0x10000; i++) { 4892f2ca38SAlexander Graf blk_schid.sch_no = i; 4922d67ab5SCornelia Huck r = stsch_err(blk_schid, &schib); 5022d67ab5SCornelia Huck if (r == 3) { 5122d67ab5SCornelia Huck break; 5222d67ab5SCornelia Huck } 5322d67ab5SCornelia Huck if (schib.pmcw.dnv) { 54ff151f4eSDominik Dingel if (!check_devno || (schib.pmcw.dev == dev_no)) { 5592f2ca38SAlexander Graf if (virtio_is_blk(blk_schid)) { 5692f2ca38SAlexander Graf found = true; 5792f2ca38SAlexander Graf break; 5892f2ca38SAlexander Graf } 5992f2ca38SAlexander Graf } 6092f2ca38SAlexander Graf } 61ff151f4eSDominik Dingel } 6292f2ca38SAlexander Graf 6392f2ca38SAlexander Graf if (!found) { 6492f2ca38SAlexander Graf virtio_panic("No virtio-blk device found!\n"); 6592f2ca38SAlexander Graf } 6692f2ca38SAlexander Graf 6792f2ca38SAlexander Graf virtio_setup_block(blk_schid); 68*60612d5cSEugene (jno) Dvurechenski 69*60612d5cSEugene (jno) Dvurechenski if (!virtio_ipl_disk_is_valid()) { 70*60612d5cSEugene (jno) Dvurechenski virtio_panic("No valid hard disk detected.\n"); 71*60612d5cSEugene (jno) Dvurechenski } 7292f2ca38SAlexander Graf } 7392f2ca38SAlexander Graf 7492f2ca38SAlexander Graf int main(void) 7592f2ca38SAlexander Graf { 7692f2ca38SAlexander Graf sclp_setup(); 77ff151f4eSDominik Dingel debug_print_int("boot reg[7] ", boot_value); 78ff151f4eSDominik Dingel virtio_setup(boot_value); 79ff151f4eSDominik Dingel 80*60612d5cSEugene (jno) Dvurechenski zipl_load(); /* no return */ 81*60612d5cSEugene (jno) Dvurechenski 82*60612d5cSEugene (jno) Dvurechenski virtio_panic("Failed to load OS from hard disk\n"); 83*60612d5cSEugene (jno) Dvurechenski return 0; /* make compiler happy */ 8492f2ca38SAlexander Graf } 85